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::{
|
||||
console,
|
||||
window,
|
||||
Element,
|
||||
KeyboardEvent,
|
||||
MouseEvent,
|
||||
WebGl2RenderingContext,
|
||||
|
@ -15,7 +14,77 @@ use web_sys::{
|
|||
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(
|
||||
context: &WebGl2RenderingContext,
|
||||
|
@ -140,7 +209,7 @@ fn load_new_buffer(
|
|||
|
||||
// the direction in camera space that a mouse event is pointing along
|
||||
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 width = rect.width();
|
||||
let height = rect.height();
|
||||
|
@ -157,6 +226,8 @@ fn event_dir(event: &MouseEvent) -> Vector3<f64> {
|
|||
)
|
||||
}
|
||||
|
||||
// --- display component ---
|
||||
|
||||
#[component]
|
||||
pub fn Display() -> View {
|
||||
let state = use_context::<AppState>();
|
||||
|
@ -225,7 +296,6 @@ pub fn Display() -> View {
|
|||
|
||||
// display parameters
|
||||
const OPACITY: f32 = 0.5; /* SCAFFOLDING */
|
||||
const HIGHLIGHT: f32 = 0.2; /* SCAFFOLDING */
|
||||
const LAYER_THRESHOLD: i32 = 0; /* DEBUG */
|
||||
const DEBUG_MODE: i32 = 0; /* DEBUG */
|
||||
|
||||
|
@ -421,6 +491,8 @@ pub fn Display() -> View {
|
|||
|
||||
// --- get the assembly ---
|
||||
|
||||
let mut scene = Scene::new();
|
||||
|
||||
// find the map from assembly space to world space
|
||||
let location = {
|
||||
let u = -location_z;
|
||||
|
@ -435,50 +507,24 @@ pub fn Display() -> View {
|
|||
let asm_to_world = &location * &orientation;
|
||||
|
||||
// get the spheres
|
||||
let (
|
||||
sphere_cnt,
|
||||
sphere_reps_world,
|
||||
sphere_colors,
|
||||
sphere_highlights
|
||||
) = state.assembly.elements.with(|elts| {
|
||||
(
|
||||
// number of elements
|
||||
elts.len() as i32,
|
||||
state.assembly.elements.with_untracked(
|
||||
|elts| for (key, elt) in elts {
|
||||
let selected = state.selection.with(|sel| sel.contains(&key));
|
||||
elt.show(&mut scene, selected);
|
||||
}
|
||||
);
|
||||
let sphere_cnt = scene.spheres.len_i32();
|
||||
|
||||
// representation vectors in world coordinates
|
||||
elts.iter().map(
|
||||
|(_, 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<_>>()
|
||||
)
|
||||
});
|
||||
// write the spheres in world coordinates
|
||||
let sphere_reps_world: Vec<_> = scene.spheres.representations.into_iter().map(
|
||||
|rep| &asm_to_world * rep
|
||||
).collect();
|
||||
|
||||
/* SCAFFOLDING */
|
||||
// get the points
|
||||
let point_positions = {
|
||||
scene.points.representations.append({
|
||||
use crate::engine::point;
|
||||
|
||||
/* DEBUG */
|
||||
// hard-code the origin and the centers of the spheres in
|
||||
// the general test assembly
|
||||
let point_reps = [
|
||||
&mut vec![
|
||||
point(0.0, 0.0, 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.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);
|
||||
DMatrix::from_columns(&point_reps_world_sp).cast::<f32>()
|
||||
};
|
||||
// write the points in world coordinates
|
||||
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 ---
|
||||
|
||||
|
@ -518,11 +568,11 @@ pub fn Display() -> View {
|
|||
);
|
||||
ctx.uniform3fv_with_f32_array(
|
||||
sphere_color_locs[n].as_ref(),
|
||||
&sphere_colors[n]
|
||||
&scene.spheres.colors[n]
|
||||
);
|
||||
ctx.uniform1f(
|
||||
sphere_highlight_locs[n].as_ref(),
|
||||
sphere_highlights[n]
|
||||
scene.spheres.highlights[n]
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue