forked from StudioInfinity/dyna3
Encapsulate scene data
This commit is contained in:
parent
d5eaf11a17
commit
cedb1d5b83
1 changed files with 102 additions and 52 deletions
|
@ -4,7 +4,6 @@ use sycamore::{prelude::*, motion::create_raf};
|
||||||
use web_sys::{
|
use web_sys::{
|
||||||
console,
|
console,
|
||||||
window,
|
window,
|
||||||
Element,
|
|
||||||
KeyboardEvent,
|
KeyboardEvent,
|
||||||
MouseEvent,
|
MouseEvent,
|
||||||
WebGl2RenderingContext,
|
WebGl2RenderingContext,
|
||||||
|
@ -15,7 +14,77 @@ use web_sys::{
|
||||||
wasm_bindgen::{JsCast, JsValue}
|
wasm_bindgen::{JsCast, JsValue}
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{AppState, assembly::{ElementKey, ElementMotion}};
|
use crate::{AppState, assembly::{Element, ElementKey, ElementColor, ElementMotion}};
|
||||||
|
|
||||||
|
// --- scene data ---
|
||||||
|
|
||||||
|
struct SceneSpheres {
|
||||||
|
representations: Vec<DVector<f64>>,
|
||||||
|
colors: Vec<ElementColor>,
|
||||||
|
highlights: Vec<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SceneSpheres {
|
||||||
|
fn new() -> SceneSpheres{
|
||||||
|
SceneSpheres {
|
||||||
|
representations: Vec::new(),
|
||||||
|
colors: Vec::new(),
|
||||||
|
highlights: Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len_i32(&self) -> i32 {
|
||||||
|
self.representations.len().try_into().expect("Number of spheres must fit in a 32-bit integer")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(&mut self, representation: DVector<f64>, color: ElementColor, highlight: f32) {
|
||||||
|
self.representations.push(representation);
|
||||||
|
self.colors.push(color);
|
||||||
|
self.highlights.push(highlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ScenePoints {
|
||||||
|
representations: Vec<DVector<f64>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ScenePoints {
|
||||||
|
fn new() -> ScenePoints {
|
||||||
|
ScenePoints {
|
||||||
|
representations: Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Scene {
|
||||||
|
spheres: SceneSpheres,
|
||||||
|
points: ScenePoints
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scene {
|
||||||
|
fn new() -> Scene {
|
||||||
|
Scene {
|
||||||
|
spheres: SceneSpheres::new(),
|
||||||
|
points: ScenePoints::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait DisplayItem {
|
||||||
|
fn show(&self, scene: &mut Scene, selected: bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DisplayItem for Element {
|
||||||
|
fn show(&self, scene: &mut Scene, selected: bool) {
|
||||||
|
const HIGHLIGHT: f32 = 0.2; /* SCAFFOLDING */
|
||||||
|
let representation = self.representation.get_clone_untracked();
|
||||||
|
let color = if selected { self.color.map(|channel| 0.2 + 0.8*channel) } else { self.color };
|
||||||
|
let highlight = if selected { 1.0 } else { HIGHLIGHT };
|
||||||
|
scene.spheres.push(representation, color, highlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- WebGL utilities ---
|
||||||
|
|
||||||
fn compile_shader(
|
fn compile_shader(
|
||||||
context: &WebGl2RenderingContext,
|
context: &WebGl2RenderingContext,
|
||||||
|
@ -140,7 +209,7 @@ fn load_new_buffer(
|
||||||
|
|
||||||
// the direction in camera space that a mouse event is pointing along
|
// the direction in camera space that a mouse event is pointing along
|
||||||
fn event_dir(event: &MouseEvent) -> Vector3<f64> {
|
fn event_dir(event: &MouseEvent) -> Vector3<f64> {
|
||||||
let target: Element = event.target().unwrap().unchecked_into();
|
let target: web_sys::Element = event.target().unwrap().unchecked_into();
|
||||||
let rect = target.get_bounding_client_rect();
|
let rect = target.get_bounding_client_rect();
|
||||||
let width = rect.width();
|
let width = rect.width();
|
||||||
let height = rect.height();
|
let height = rect.height();
|
||||||
|
@ -157,6 +226,8 @@ fn event_dir(event: &MouseEvent) -> Vector3<f64> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- display component ---
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Display() -> View {
|
pub fn Display() -> View {
|
||||||
let state = use_context::<AppState>();
|
let state = use_context::<AppState>();
|
||||||
|
@ -225,7 +296,6 @@ pub fn Display() -> View {
|
||||||
|
|
||||||
// display parameters
|
// display parameters
|
||||||
const OPACITY: f32 = 0.5; /* SCAFFOLDING */
|
const OPACITY: f32 = 0.5; /* SCAFFOLDING */
|
||||||
const HIGHLIGHT: f32 = 0.2; /* SCAFFOLDING */
|
|
||||||
const LAYER_THRESHOLD: i32 = 0; /* DEBUG */
|
const LAYER_THRESHOLD: i32 = 0; /* DEBUG */
|
||||||
const DEBUG_MODE: i32 = 0; /* DEBUG */
|
const DEBUG_MODE: i32 = 0; /* DEBUG */
|
||||||
|
|
||||||
|
@ -421,6 +491,8 @@ pub fn Display() -> View {
|
||||||
|
|
||||||
// --- get the assembly ---
|
// --- get the assembly ---
|
||||||
|
|
||||||
|
let mut scene = Scene::new();
|
||||||
|
|
||||||
// find the map from assembly space to world space
|
// find the map from assembly space to world space
|
||||||
let location = {
|
let location = {
|
||||||
let u = -location_z;
|
let u = -location_z;
|
||||||
|
@ -435,50 +507,24 @@ pub fn Display() -> View {
|
||||||
let asm_to_world = &location * &orientation;
|
let asm_to_world = &location * &orientation;
|
||||||
|
|
||||||
// get the spheres
|
// get the spheres
|
||||||
let (
|
state.assembly.elements.with_untracked(
|
||||||
sphere_cnt,
|
|elts| for (key, elt) in elts {
|
||||||
sphere_reps_world,
|
let selected = state.selection.with(|sel| sel.contains(&key));
|
||||||
sphere_colors,
|
elt.show(&mut scene, selected);
|
||||||
sphere_highlights
|
}
|
||||||
) = state.assembly.elements.with(|elts| {
|
);
|
||||||
(
|
let sphere_cnt = scene.spheres.len_i32();
|
||||||
// number of elements
|
|
||||||
elts.len() as i32,
|
// write the spheres in world coordinates
|
||||||
|
let sphere_reps_world: Vec<_> = scene.spheres.representations.into_iter().map(
|
||||||
// representation vectors in world coordinates
|
|rep| &asm_to_world * rep
|
||||||
elts.iter().map(
|
).collect();
|
||||||
|(_, elt)| elt.representation.with(|rep| &asm_to_world * rep)
|
|
||||||
).collect::<Vec<_>>(),
|
|
||||||
|
|
||||||
// colors
|
|
||||||
elts.iter().map(|(key, elt)| {
|
|
||||||
if state.selection.with(|sel| sel.contains(&key)) {
|
|
||||||
elt.color.map(|ch| 0.2 + 0.8*ch)
|
|
||||||
} else {
|
|
||||||
elt.color
|
|
||||||
}
|
|
||||||
}).collect::<Vec<_>>(),
|
|
||||||
|
|
||||||
// highlight levels
|
|
||||||
elts.iter().map(|(key, _)| {
|
|
||||||
if state.selection.with(|sel| sel.contains(&key)) {
|
|
||||||
1.0_f32
|
|
||||||
} else {
|
|
||||||
HIGHLIGHT
|
|
||||||
}
|
|
||||||
}).collect::<Vec<_>>()
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
/* SCAFFOLDING */
|
/* SCAFFOLDING */
|
||||||
// get the points
|
// get the points
|
||||||
let point_positions = {
|
scene.points.representations.append({
|
||||||
use crate::engine::point;
|
use crate::engine::point;
|
||||||
|
&mut vec![
|
||||||
/* DEBUG */
|
|
||||||
// hard-code the origin and the centers of the spheres in
|
|
||||||
// the general test assembly
|
|
||||||
let point_reps = [
|
|
||||||
point(0.0, 0.0, 0.0),
|
point(0.0, 0.0, 0.0),
|
||||||
point(0.5, 0.5, 0.0),
|
point(0.5, 0.5, 0.0),
|
||||||
point(-0.5, -0.5, 0.0),
|
point(-0.5, -0.5, 0.0),
|
||||||
|
@ -486,12 +532,16 @@ pub fn Display() -> View {
|
||||||
point(0.5, -0.5, 0.0),
|
point(0.5, -0.5, 0.0),
|
||||||
point(0.0, 0.15, 1.0),
|
point(0.0, 0.15, 1.0),
|
||||||
point(0.0, -0.15, -1.0)
|
point(0.0, -0.15, -1.0)
|
||||||
];
|
]
|
||||||
|
});
|
||||||
let asm_to_world_sp = asm_to_world.rows(0, SPACE_DIM);
|
|
||||||
let point_reps_world_sp = point_reps.map(|rep| &asm_to_world_sp * rep);
|
// write the points in world coordinates
|
||||||
DMatrix::from_columns(&point_reps_world_sp).cast::<f32>()
|
let asm_to_world_sp = asm_to_world.rows(0, SPACE_DIM);
|
||||||
};
|
let point_positions = DMatrix::from_columns(
|
||||||
|
&scene.points.representations.into_iter().map(
|
||||||
|
|rep| &asm_to_world_sp * rep
|
||||||
|
).collect::<Vec<_>>().as_slice()
|
||||||
|
).cast::<f32>();
|
||||||
|
|
||||||
// --- draw the spheres ---
|
// --- draw the spheres ---
|
||||||
|
|
||||||
|
@ -518,11 +568,11 @@ pub fn Display() -> View {
|
||||||
);
|
);
|
||||||
ctx.uniform3fv_with_f32_array(
|
ctx.uniform3fv_with_f32_array(
|
||||||
sphere_color_locs[n].as_ref(),
|
sphere_color_locs[n].as_ref(),
|
||||||
&sphere_colors[n]
|
&scene.spheres.colors[n]
|
||||||
);
|
);
|
||||||
ctx.uniform1f(
|
ctx.uniform1f(
|
||||||
sphere_highlight_locs[n].as_ref(),
|
sphere_highlight_locs[n].as_ref(),
|
||||||
sphere_highlights[n]
|
scene.spheres.highlights[n]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue