diff --git a/app-proto/inversive-display/src/main.rs b/app-proto/inversive-display/src/main.rs index 15c2518..4da24f5 100644 --- a/app-proto/inversive-display/src/main.rs +++ b/app-proto/inversive-display/src/main.rs @@ -9,7 +9,7 @@ extern crate js_sys; use core::array; -use nalgebra::DVector; +use nalgebra::{DMatrix, DVector}; use sycamore::{prelude::*, motion::create_raf, rt::{JsCast, JsValue}}; use web_sys::{console, window, WebGl2RenderingContext, WebGlProgram, WebGlShader, WebGlUniformLocation}; @@ -96,14 +96,15 @@ fn main() { let radius_y = create_signal(1.0); let opacity = create_signal(0.5); let highlight = create_signal(0.2); - let layer_threshold = create_signal(0.0); - let debug_mode = create_signal(false); + let turntable = create_signal(false); + let layer_threshold = create_signal(0.0); /* DEBUG */ + let debug_mode = create_signal(false); /* DEBUG */ /* INSTRUMENTS */ const SAMPLE_PERIOD: i32 = 20; - let mut last_frame_moment = 0.0; + let mut last_sample_time = 0.0; let mut frames_since_last_sample = 0; - let frame_time = create_signal(0.0); + let mean_frame_interval = create_signal(0.0); // display let display = create_node_ref(); @@ -117,6 +118,7 @@ fn main() { radius_y.track(); opacity.track(); highlight.track(); + turntable.track(); layer_threshold.track(); debug_mode.track(); @@ -133,6 +135,13 @@ fn main() { [0.25_f32, 0.00_f32, 1.00_f32] ]; + // timing + let mut last_time = 0.0; + + // scene parameters + const TURNTABLE_SPEED: f64 = 0.5; + let mut turntable_angle = 0.0; + /* INSTRUMENTS */ let performance = window().unwrap().performance().unwrap(); @@ -232,22 +241,57 @@ fn main() { // set up a repainting routine let (_, start_animation_loop, _) = create_raf(move || { + // get the time step + let time = performance.now(); + let time_step = 0.001*(time - last_time); + last_time = time; + + // move the turntable + let turntable_val = turntable.get(); + if turntable_val { + turntable_angle += TURNTABLE_SPEED * time_step; + } + if scene_changed.get() { /* INSTRUMENTS */ - // measure frame time + // measure mean frame interval frames_since_last_sample += 1; if frames_since_last_sample >= SAMPLE_PERIOD { - let frame_moment = performance.now(); - frame_time.set((frame_moment - last_frame_moment) / (SAMPLE_PERIOD as f64)); - last_frame_moment = frame_moment; + mean_frame_interval.set((time - last_sample_time) / (SAMPLE_PERIOD as f64)); + last_sample_time = time; frames_since_last_sample = 0; } + // set the orientation and translation + let 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 sphere_vec.clear(); - sphere_vec.push(engine::sphere(0.5, 0.5, -5.0 + ctrl_x.get(), radius_x.get())); - sphere_vec.push(engine::sphere(-0.5, -0.5, -5.0 + ctrl_y.get(), radius_y.get())); - sphere_vec.push(engine::sphere(-0.5, 0.5, -5.0, 0.75)); + sphere_vec.push(&construction_to_world * engine::sphere(0.5, 0.5, ctrl_x.get(), radius_x.get())); + sphere_vec.push(&construction_to_world * engine::sphere(-0.5, -0.5, ctrl_y.get(), radius_y.get())); + sphere_vec.push(&construction_to_world * engine::sphere(-0.5, 0.5, 0.0, 0.75)); // set the resolution let width = canvas.width() as f32; @@ -285,10 +329,10 @@ fn main() { ctx.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, VERTEX_CNT as i32); // clear scene change flag - scene_changed.set(false); + scene_changed.set(turntable_val); } else { frames_since_last_sample = 0; - frame_time.set(-1.0); + mean_frame_interval.set(-1.0); } }); start_animation_loop(); @@ -296,7 +340,7 @@ fn main() { view! { div(id="app") { - div { (frame_time.get()) " ms" } + div { "Mean frame interval: " (mean_frame_interval.get()) " ms" } canvas(ref=display, width="600", height="600") div(class="control") { label(for="ctrl-x") { "Sphere 0 depth" } @@ -362,6 +406,14 @@ fn main() { bind:valueAsNumber=highlight ) } + div(class="control") { + label(for="turntable") { "Turntable" } + input( + type="checkbox", + id="turntable", + bind:checked=turntable + ) + } div(class="control") { label(for="layer-threshold") { "Layer threshold" } input(