Implement keyboard navigation
This commit is contained in:
parent
2efc08d6c0
commit
c67f37c934
@ -9,9 +9,17 @@
|
|||||||
|
|
||||||
extern crate js_sys;
|
extern crate js_sys;
|
||||||
use core::array;
|
use core::array;
|
||||||
use nalgebra::{DMatrix, DVector};
|
use nalgebra::{DMatrix, DVector, Rotation3, Vector3};
|
||||||
use sycamore::{prelude::*, motion::create_raf, rt::{JsCast, JsValue}};
|
use sycamore::{prelude::*, motion::create_raf, rt::{JsCast, JsValue}};
|
||||||
use web_sys::{console, window, WebGl2RenderingContext, WebGlProgram, WebGlShader, WebGlUniformLocation};
|
use web_sys::{
|
||||||
|
console,
|
||||||
|
window,
|
||||||
|
KeyboardEvent,
|
||||||
|
WebGl2RenderingContext,
|
||||||
|
WebGlProgram,
|
||||||
|
WebGlShader,
|
||||||
|
WebGlUniformLocation
|
||||||
|
};
|
||||||
|
|
||||||
mod engine;
|
mod engine;
|
||||||
|
|
||||||
@ -157,6 +165,12 @@ fn main() {
|
|||||||
// tab selection
|
// tab selection
|
||||||
let tab_selection = create_signal(Tab::GenTab);
|
let tab_selection = create_signal(Tab::GenTab);
|
||||||
|
|
||||||
|
// navigation
|
||||||
|
let pitch_up = create_signal(0.0);
|
||||||
|
let pitch_down = create_signal(0.0);
|
||||||
|
let yaw_right = create_signal(0.0);
|
||||||
|
let yaw_left = create_signal(0.0);
|
||||||
|
|
||||||
// controls for general example
|
// controls for general example
|
||||||
let gen_controls = create_node_ref();
|
let gen_controls = create_node_ref();
|
||||||
let ctrl_x = create_signal(0.0);
|
let ctrl_x = create_signal(0.0);
|
||||||
@ -246,8 +260,21 @@ fn main() {
|
|||||||
let mut last_time = 0.0;
|
let mut last_time = 0.0;
|
||||||
|
|
||||||
// scene parameters
|
// scene parameters
|
||||||
const TURNTABLE_SPEED: f64 = 0.5;
|
const NAV_SPEED: f64 = 0.4; // in radians per second
|
||||||
let mut turntable_angle = 0.0;
|
const TURNTABLE_SPEED: f64 = 0.1; // in radians per second
|
||||||
|
let mut orientation = DMatrix::<f64>::identity(5, 5);
|
||||||
|
let mut rotation = DMatrix::<f64>::identity(5, 5);
|
||||||
|
let location = {
|
||||||
|
const LEN: f64 = -5.0;
|
||||||
|
const LEN_SQ: f64 = LEN*LEN;
|
||||||
|
DMatrix::from_column_slice(5, 5, &[
|
||||||
|
1.0, 0.0, 0.0, 0.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0, 0.0, 0.0,
|
||||||
|
0.0, 0.0, 1.0, 0.0, LEN,
|
||||||
|
0.0, 0.0, 2.0*LEN, 1.0, LEN_SQ,
|
||||||
|
0.0, 0.0, 0.0, 0.0, 1.0
|
||||||
|
])
|
||||||
|
};
|
||||||
|
|
||||||
/* INSTRUMENTS */
|
/* INSTRUMENTS */
|
||||||
let performance = window().unwrap().performance().unwrap();
|
let performance = window().unwrap().performance().unwrap();
|
||||||
@ -353,11 +380,36 @@ fn main() {
|
|||||||
let time_step = 0.001*(time - last_time);
|
let time_step = 0.001*(time - last_time);
|
||||||
last_time = time;
|
last_time = time;
|
||||||
|
|
||||||
// move the turntable
|
// get the navigation state
|
||||||
|
let pitch_up_val = pitch_up.get();
|
||||||
|
let pitch_down_val = pitch_down.get();
|
||||||
|
let yaw_right_val = yaw_right.get();
|
||||||
|
let yaw_left_val = yaw_left.get();
|
||||||
let turntable_val = turntable.get();
|
let turntable_val = turntable.get();
|
||||||
if turntable_val {
|
|
||||||
turntable_angle += TURNTABLE_SPEED * time_step;
|
// update the construction's orientation
|
||||||
}
|
let ang_vel = {
|
||||||
|
let pitch = pitch_up_val - pitch_down_val;
|
||||||
|
let yaw = yaw_right_val - yaw_left_val;
|
||||||
|
let ang_vel_from_keyboard =
|
||||||
|
if pitch != 0.0 || yaw != 0.0 {
|
||||||
|
NAV_SPEED * Vector3::new(-pitch, yaw, 0.0).normalize()
|
||||||
|
} else {
|
||||||
|
Vector3::zeros()
|
||||||
|
};
|
||||||
|
let ang_vel_from_turntable =
|
||||||
|
if turntable_val {
|
||||||
|
Vector3::new(0.0, TURNTABLE_SPEED, 0.0)
|
||||||
|
} else {
|
||||||
|
Vector3::zeros()
|
||||||
|
};
|
||||||
|
ang_vel_from_keyboard + ang_vel_from_turntable
|
||||||
|
};
|
||||||
|
let mut rotation_sp = rotation.fixed_view_mut::<3, 3>(0, 0);
|
||||||
|
rotation_sp.copy_from(
|
||||||
|
Rotation3::from_scaled_axis(time_step * ang_vel).matrix()
|
||||||
|
);
|
||||||
|
orientation = &rotation * &orientation;
|
||||||
|
|
||||||
if scene_changed.get() {
|
if scene_changed.get() {
|
||||||
/* INSTRUMENTS */
|
/* INSTRUMENTS */
|
||||||
@ -369,30 +421,8 @@ fn main() {
|
|||||||
frames_since_last_sample = 0;
|
frames_since_last_sample = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the orientation and translation
|
// find the map from construction space to world space
|
||||||
let orientation = {
|
let construction_to_world = &location * &orientation;
|
||||||
let ang_cos = turntable_angle.cos();
|
|
||||||
let ang_sin = turntable_angle.sin();
|
|
||||||
DMatrix::from_column_slice(5, 5, &[
|
|
||||||
ang_cos, 0.0, ang_sin, 0.0, 0.0,
|
|
||||||
0.0, 1.0, 0.0, 0.0, 0.0,
|
|
||||||
-ang_sin, 0.0, ang_cos, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 0.0, 1.0, 0.0,
|
|
||||||
0.0, 0.0, 0.0, 0.0, 1.0
|
|
||||||
])
|
|
||||||
};
|
|
||||||
let translation = {
|
|
||||||
const LEN: f64 = -5.0;
|
|
||||||
const LEN_SQ: f64 = LEN*LEN;
|
|
||||||
DMatrix::from_column_slice(5, 5, &[
|
|
||||||
1.0, 0.0, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 1.0, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 1.0, 0.0, LEN,
|
|
||||||
0.0, 0.0, 2.0*LEN, 1.0, LEN_SQ,
|
|
||||||
0.0, 0.0, 0.0, 0.0, 1.0
|
|
||||||
])
|
|
||||||
};
|
|
||||||
let construction_to_world = &translation * orientation;
|
|
||||||
|
|
||||||
// update the construction
|
// update the construction
|
||||||
sphere_vec.clear();
|
sphere_vec.clear();
|
||||||
@ -450,7 +480,13 @@ fn main() {
|
|||||||
ctx.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, VERTEX_CNT as i32);
|
ctx.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, VERTEX_CNT as i32);
|
||||||
|
|
||||||
// clear scene change flag
|
// clear scene change flag
|
||||||
scene_changed.set(turntable_val);
|
scene_changed.set(
|
||||||
|
pitch_up_val != 0.0
|
||||||
|
|| pitch_down_val != 0.0
|
||||||
|
|| yaw_left_val != 0.0
|
||||||
|
|| yaw_right_val != 0.0
|
||||||
|
|| turntable_val
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
frames_since_last_sample = 0;
|
frames_since_last_sample = 0;
|
||||||
mean_frame_interval.set(-1.0);
|
mean_frame_interval.set(-1.0);
|
||||||
@ -482,7 +518,46 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
div { "Mean frame interval: " (mean_frame_interval.get()) " ms" }
|
div { "Mean frame interval: " (mean_frame_interval.get()) " ms" }
|
||||||
canvas(ref=display, width=600, height=600, tabindex=0)
|
canvas(
|
||||||
|
ref=display,
|
||||||
|
width=600,
|
||||||
|
height=600,
|
||||||
|
tabindex=0,
|
||||||
|
on:keydown=move |event: KeyboardEvent| {
|
||||||
|
let mut navigating = true;
|
||||||
|
match event.key().as_str() {
|
||||||
|
"ArrowUp" => pitch_up.set(1.0),
|
||||||
|
"ArrowDown" => pitch_down.set(1.0),
|
||||||
|
"ArrowRight" => yaw_right.set(1.0),
|
||||||
|
"ArrowLeft" => yaw_left.set(1.0),
|
||||||
|
_ => navigating = false
|
||||||
|
};
|
||||||
|
if navigating {
|
||||||
|
scene_changed.set(true);
|
||||||
|
event.prevent_default();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on:keyup=move |event: KeyboardEvent| {
|
||||||
|
let mut navigating = true;
|
||||||
|
match event.key().as_str() {
|
||||||
|
"ArrowUp" => pitch_up.set(0.0),
|
||||||
|
"ArrowDown" => pitch_down.set(0.0),
|
||||||
|
"ArrowRight" => yaw_right.set(0.0),
|
||||||
|
"ArrowLeft" => yaw_left.set(0.0),
|
||||||
|
_ => navigating = false
|
||||||
|
};
|
||||||
|
if navigating {
|
||||||
|
scene_changed.set(true);
|
||||||
|
event.prevent_default();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on:blur=move |_| {
|
||||||
|
pitch_up.set(0.0);
|
||||||
|
pitch_down.set(0.0);
|
||||||
|
yaw_right.set(0.0);
|
||||||
|
yaw_left.set(0.0);
|
||||||
|
}
|
||||||
|
)
|
||||||
div(ref=gen_controls) {
|
div(ref=gen_controls) {
|
||||||
label(class="control") {
|
label(class="control") {
|
||||||
span { "Sphere 0 depth" }
|
span { "Sphere 0 depth" }
|
||||||
|
Loading…
Reference in New Issue
Block a user