Add a point element

Also add a new test assembly, "Pointed," to try out the new element.
This commit is contained in:
Aaron Fenyes 2025-04-24 14:08:15 -07:00
parent 873de78f2d
commit 1945086586
3 changed files with 179 additions and 51 deletions

View file

@ -14,7 +14,10 @@ use web_sys::{
wasm_bindgen::{JsCast, JsValue}
};
use crate::{AppState, assembly::{ElementKey, ElementColor, ElementMotion, Sphere}};
use crate::{
AppState,
assembly::{ElementKey, ElementColor, ElementMotion, Point, Sphere}
};
// --- scene data ---
@ -129,6 +132,18 @@ impl DisplayItem for Sphere {
}
}
impl DisplayItem for Point {
fn show(&self, scene: &mut Scene, _selected: bool) {
let representation = self.representation.get_clone_untracked();
scene.points.representations.push(representation);
}
/* SCAFFOLDING */
fn cast(&self, _dir: Vector3<f64>, _assembly_to_world: &DMatrix<f64>) -> Option<f64> {
None
}
}
// --- WebGL utilities ---
fn compile_shader(
@ -551,7 +566,7 @@ pub fn Display() -> View {
};
let asm_to_world = &location * &orientation;
// get the spheres
// set up the scene
state.assembly.elements.with_untracked(
|elts| for (key, elt) in elts {
let selected = state.selection.with(|sel| sel.contains(&key));
@ -560,39 +575,16 @@ pub fn Display() -> View {
);
let sphere_cnt = scene.spheres.len_i32();
// write the spheres in world coordinates
let sphere_reps_world: Vec<_> = scene.spheres.representations.into_iter().map(
|rep| (&asm_to_world * rep).cast::<f32>()
).collect();
/* SCAFFOLDING */
// get the points
scene.points.representations.append({
use crate::engine::point;
&mut vec![
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),
point(0.0, 0.15, 1.0),
point(0.0, -0.15, -1.0)
]
});
// 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 ---
// use the sphere rendering program
ctx.use_program(Some(&sphere_program));
// write the spheres in world coordinates
let sphere_reps_world: Vec<_> = scene.spheres.representations.into_iter().map(
|rep| (&asm_to_world * rep).cast::<f32>()
).collect();
// set the resolution
let width = canvas.width() as f32;
let height = canvas.height() as f32;
@ -635,16 +627,26 @@ pub fn Display() -> View {
// --- draw the points ---
// use the point rendering program
ctx.use_program(Some(&point_program));
// load the point positions into a new buffer and bind it to the
// position attribute in the vertex shader
let point_position_buffer = load_new_buffer(&ctx, point_positions.as_slice());
bind_to_attribute(&ctx, point_position_attr, SPACE_DIM as i32, &point_position_buffer);
// draw the scene
ctx.draw_arrays(WebGl2RenderingContext::POINTS, 0, point_positions.ncols() as i32);
if !scene.points.representations.is_empty() {
// use the point rendering program
ctx.use_program(Some(&point_program));
// 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>();
// load the point positions into a new buffer and bind it to the
// position attribute in the vertex shader
let point_position_buffer = load_new_buffer(&ctx, point_positions.as_slice());
bind_to_attribute(&ctx, point_position_attr, SPACE_DIM as i32, &point_position_buffer);
// draw the scene
ctx.draw_arrays(WebGl2RenderingContext::POINTS, 0, point_positions.ncols() as i32);
}
// --- update the display state ---