Skip to main content

flow_ngin/data_structures/
scene_graph.rs

1//! Scene graph and hierarchical scene organization.
2//!
3//! Provides traits and structures for building a scene graph: a hierarchical
4//! representation of objects in a scene, including animation support and
5//! renderable object composition.
6
7use std::{collections::HashMap, ops::Range};
8
9use cgmath::{InnerSpace, SquareMatrix, Zero};
10use log::warn;
11use wgpu::{Device, Queue, util::DeviceExt};
12
13use crate::{
14    context::GPUResource, data_structures::{
15        instance::{Instance, InstanceRaw},
16        model::{self, DrawModel},
17    }, pick::PickId, render::{Instanced, Render}, resources::{animation::Keyframes, load_model_obj, pick::load_pick_model}
18};
19
20/// An animation clip: a named animation with keyframes and timing.
21#[derive(Clone, Debug)]
22pub struct AnimationClip {
23    pub name: String,
24    pub keyframes: Keyframes,
25    pub timestamps: Vec<f32>,
26}
27
28#[derive(Clone, Debug, Default)]
29pub struct ModelAnimation {
30    pub name: String,
31    pub instances: Vec<Instance>,
32    pub timestamps: Vec<f32>,
33}
34
35/**
36 * Intermediate state when converting between `AnimationClip` and `ModelAnimation`
37 */
38#[derive(Default)]
39struct ModelState {
40    animations: Vec<ModelAnimation>,
41    trans: Vec<cgmath::Vector3<f32>>,
42    rots: Vec<cgmath::Quaternion<f32>>,
43    scals: Vec<cgmath::Vector3<f32>>,
44    timestamps: Vec<f32>,
45    current_clip: String,
46}
47impl ModelState {
48    fn reset(&mut self, clip: &AnimationClip) {
49        self.timestamps = vec![];
50        self.trans = vec![];
51        self.rots = vec![];
52        self.scals = vec![];
53        self.current_clip = clip.name.clone();
54    }
55}
56
57pub fn to_scene_node(
58    id: impl Into<PickId>,
59    node: gltf::scene::Node,
60    buf: &Vec<Vec<u8>>,
61    device: &wgpu::Device,
62    mats: &Vec<model::Material>,
63    anims: &HashMap<usize, Vec<AnimationClip>>,
64) -> Box<dyn SceneNode> {
65    let animations = match anims.get(&node.index()) {
66        Some(clips) => merge(clips.clone()),
67        None => Default::default(),
68    };
69    let id = id.into();
70    // TODO: only select materials for current mesh
71    let mut scene_node: Box<dyn SceneNode> = match node.mesh() {
72        Some(mesh) => {
73            let mut meshes = Vec::new();
74            let primitives = mesh.primitives();
75
76            primitives.for_each(|primitive| {
77                let reader = primitive.reader(|buffer| Some(&buf[buffer.index()]));
78
79                let mut indices = Vec::new();
80                if let Some(indices_raw) = reader.read_indices() {
81                    indices.append(&mut indices_raw.into_u32().collect::<Vec<u32>>());
82                } else {
83                    if let Some(positions) = reader.read_positions() {
84                        indices = (0..positions.len() as u32).collect();
85                    }
86                }
87
88                let mut vertices = Vec::with_capacity(indices.len());
89                if let Some(vertex_attribute) = reader.read_positions() {
90                    vertex_attribute.for_each(|vertex| {
91                        vertices.push(model::ModelVertex {
92                            position: vertex,
93                            tex_coords: Default::default(),
94                            normal: Default::default(),
95                            bitangent: Default::default(),
96                            tangent: Default::default(),
97                        })
98                    });
99                }
100                if let Some(normal_attribute) = reader.read_normals() {
101                    let mut normal_index = 0;
102                    normal_attribute.for_each(|normal| {
103                        vertices[normal_index].normal = normal;
104
105                        normal_index += 1;
106                    });
107                }
108                let texcoord_set = primitive
109                    .material()
110                    .pbr_metallic_roughness()
111                    .base_color_texture()
112                    .map(|t| t.tex_coord())
113                    .unwrap_or(0);
114                if let Some(tex_coord_attribute) = reader.read_tex_coords(texcoord_set).map(|v| v.into_f32()) {
115                    let mut tex_coord_index = 0;
116                    tex_coord_attribute.for_each(|tex_coord| {
117                        vertices[tex_coord_index].tex_coords = tex_coord;
118
119                        tex_coord_index += 1;
120                    });
121                }
122                if let Some(tangent_attribute) = reader.read_tangents() {
123                    let mut tangent_index = 0;
124                    tangent_attribute.for_each(|tangent| {
125                        // GLTF represents tangents as vec4 where the 4th elem can be used to calculate the bitangent
126                        let tangent: cgmath::Vector4<f32> = tangent.into();
127                        vertices[tangent_index].tangent = tangent.truncate().into();
128                        let normal: cgmath::Vector3<f32> = vertices[tangent_index].normal.into();
129                        let bitangent = normal.cross(tangent.truncate()) * tangent[3];
130                        vertices[tangent_index].bitangent = bitangent.into();
131
132                        tangent_index += 1;
133                    });
134                } else {
135                    if !indices.is_empty() && !vertices.is_empty() {
136                        compute_tangents(&mut vertices, &indices);
137                    }
138                };
139
140                let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
141                    label: Some(&format!("{:?} Vertex Buffer", mesh.name())),
142                    contents: bytemuck::cast_slice(&vertices),
143                    usage: wgpu::BufferUsages::VERTEX,
144                });
145
146                let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
147                    label: Some(&format!("{:?} Index Buffer", mesh.name())),
148                    contents: bytemuck::cast_slice(&indices),
149                    usage: wgpu::BufferUsages::INDEX,
150                });
151                let mat_idx = primitive.material().index().unwrap_or(0);
152
153                meshes.push(model::Mesh {
154                    name: mesh.name().unwrap_or("unknown_mesh").to_string(),
155                    vertex_buffer,
156                    index_buffer,
157                    num_elements: indices.len() as u32,
158                    material: mat_idx,
159                });
160            });
161            /* TOOD: don't store all materials in one place (insert Walter White meme here)
162                Instead adjust the mesh/anim index above as well as the vec below
163                e.g. mats [1,2,3,4] for mesh1[1,2] and mesh2[3,4] must become mats1 [1, 2] mesh1[1,2] and mats2 [1, 2] mesh2 [1, 2]
164            */
165            let model = model::Model {
166                meshes,
167                materials: mats.clone(),
168            };
169            Box::new(ModelNode::from_model(1, id, device, model, animations))
170        }
171        None => Box::new(ContainerNode::new(1, animations)),
172    };
173    let decomp_pos = node.transform().decomposed();
174    let instance = Instance {
175        position: decomp_pos.0.into(),
176        rotation: decomp_pos.1.into(),
177        scale: decomp_pos.2.into(),
178    };
179    scene_node.set_local_transform(0, instance);
180    for child in node.children() {
181        let child_node = to_scene_node(id, child, buf, device, mats, anims);
182        scene_node.add_child(child_node);
183    }
184
185    scene_node
186}
187
188fn compute_tangents(vertices: &mut Vec<model::ModelVertex>, indices: &[u32]) {
189    // 1. Allocate temporary storage for tangent and bitangent accumulators.
190    // We need these to accumulate contributions from all triangles sharing a vertex.
191    let mut tan1 = vec![cgmath::Vector3::zero(); vertices.len()];
192    let mut tan2 = vec![cgmath::Vector3::zero(); vertices.len()];
193
194    // 2. Iterate over all triangles (chunks of 3 indices)
195    for c in indices.chunks(3) {
196        if c.len() < 3 {
197            break;
198        } // Safety check
199
200        let i1 = c[0] as usize;
201        let i2 = c[1] as usize;
202        let i3 = c[2] as usize;
203
204        let v1 = &vertices[i1];
205        let v2 = &vertices[i2];
206        let v3 = &vertices[i3];
207
208        let p1: cgmath::Vector3<f32> = v1.position.into();
209        let p2: cgmath::Vector3<f32> = v2.position.into();
210        let p3: cgmath::Vector3<f32> = v3.position.into();
211
212        let w1: cgmath::Vector2<f32> = v1.tex_coords.into();
213        let w2: cgmath::Vector2<f32> = v2.tex_coords.into();
214        let w3: cgmath::Vector2<f32> = v3.tex_coords.into();
215
216        let x1 = p2.x - p1.x;
217        let x2 = p3.x - p1.x;
218        let y1 = p2.y - p1.y;
219        let y2 = p3.y - p1.y;
220        let z1 = p2.z - p1.z;
221        let z2 = p3.z - p1.z;
222
223        let s1 = w2.x - w1.x;
224        let s2 = w3.x - w1.x;
225        let t1 = w2.y - w1.y;
226        let t2 = w3.y - w1.y;
227
228        // Prevent division by zero if UVs are degenerate
229        let r_denom = s1 * t2 - s2 * t1;
230        let r = if r_denom.abs() < 1e-6 {
231            0.0
232        } else {
233            1.0 / r_denom
234        };
235
236        let sdir = cgmath::Vector3::new(
237            (t2 * x1 - t1 * x2) * r,
238            (t2 * y1 - t1 * y2) * r,
239            (t2 * z1 - t1 * z2) * r,
240        );
241
242        let tdir = cgmath::Vector3::new(
243            (s1 * x2 - s2 * x1) * r,
244            (s1 * y2 - s2 * y1) * r,
245            (s1 * z2 - s2 * z1) * r,
246        );
247
248        // Accumulate for each vertex of the triangle
249        tan1[i1] += sdir;
250        tan1[i2] += sdir;
251        tan1[i3] += sdir;
252
253        tan2[i1] += tdir;
254        tan2[i2] += tdir;
255        tan2[i3] += tdir;
256    }
257
258    for (i, vert) in vertices.iter_mut().enumerate() {
259        let n: cgmath::Vector3<f32> = vert.normal.into();
260        let t = tan1[i];
261
262        // Gram-Schmidt orthogonalize:
263        let tangent_xyz = (t - n * n.dot(t)).normalize();
264
265        let w = if n.cross(t).dot(tan2[i]) < 0.0 {
266            -1.0
267        } else {
268            1.0
269        };
270
271        if tangent_xyz.x.is_nan() {
272            vert.tangent = [1.0, 0.0, 0.0];
273            vert.bitangent = [0.0, 1.0, 0.0];
274        } else {
275            vert.tangent = tangent_xyz.into();
276            let bitangent = n.cross(tangent_xyz) * w;
277            vert.bitangent = bitangent.into();
278        }
279    }
280}
281
282fn save_current_anim(state: &mut ModelState, clip: &AnimationClip) -> ModelAnimation {
283    let t_len = state.trans.len();
284    let r_len = state.rots.len();
285    let s_len = state.scals.len();
286    let max_len = t_len.max(r_len.max(s_len));
287    if t_len != r_len || r_len != s_len {
288        log::warn!(
289            "warning, animation track len() doesn't match and will matched with defaults. previous animation: {}, current: {}",
290            state.current_clip,
291            clip.name
292        );
293        // Use first frame as default (this is important as child nodes have offsets)
294        state.trans.append(
295            &mut (t_len..max_len)
296                .into_iter()
297                .filter_map(|_| state.trans.first())
298                .cloned()
299                .collect(),
300        );
301        state.rots.append(
302            &mut (r_len..max_len)
303                .into_iter()
304                .filter_map(|_| state.rots.first())
305                .cloned()
306                .collect(),
307        );
308        state.scals.append(
309            &mut (s_len..max_len)
310                .into_iter()
311                .filter_map(|_| state.scals.first())
312                .cloned()
313                .collect(),
314        );
315    }
316    // now assume the're all the same length
317    let mut instances = Vec::with_capacity(t_len);
318    for i in 0..max_len {
319        let instance = Instance {
320            position: state.trans[i],
321            rotation: state.rots[i],
322            scale: state.scals[i],
323        };
324        instances.push(instance);
325    }
326    // new clip, reset vecs
327    let animation = ModelAnimation {
328        name: clip.name.clone(),
329        instances,
330        timestamps: state.timestamps.clone(),
331    };
332    animation
333}
334
335/**
336 * Merges keyframes with the same name to have all transformations in one place.
337 *
338 * GLTF:
339 * AnimationClip {
340 *      name: anim1
341 *      keyframes: Scale(
342 *          [[data]]
343 *      )
344 * }
345 * AnimationClip {
346 *      name: anim1
347 *      keyframes: Rotation(
348 *          [[data]]
349 *      )
350 * }
351 * ...
352 *
353 * to
354 *
355 * ModelAnimation {
356 *      name: anim1
357 *      keyframes: [
358 *          rot: []
359 *          tr: []
360 *          sc: []
361 *      ]
362 * }
363 */
364fn merge(clips: Vec<AnimationClip>) -> Vec<ModelAnimation> {
365    let mut state = ModelState {
366        current_clip: clips.first().unwrap().name.clone(),
367        ..Default::default()
368    };
369    for clip in clips.iter() {
370        if clip.name != state.current_clip {
371            let animation = save_current_anim(&mut state, clip);
372            state.animations.push(animation);
373            state.reset(clip);
374        }
375        match &clip.keyframes {
376            Keyframes::Translation(translations) => translations
377                .into_iter()
378                .for_each(|&tr| state.trans.push(tr)),
379            Keyframes::Rotation(rotations) => {
380                rotations.into_iter().for_each(|&rot| state.rots.push(rot));
381            }
382            Keyframes::Scale(scalations) => {
383                scalations.into_iter().for_each(|&sc| state.scals.push(sc));
384            }
385            Keyframes::Other => todo!(),
386        }
387        // in case some tracks have fewer steps than others we want to have the largest set of timestamps for smooth animations
388        if clip.timestamps.len() > state.timestamps.len() {
389            state.timestamps = clip.timestamps.clone();
390        }
391    }
392    if let Some(clip) = clips.last() {
393        let animation = save_current_anim(&mut state, clip);
394        state.animations.push(animation);
395        state.reset(clip);
396    }
397    state.animations
398}
399
400pub trait SceneNode: Send {
401    fn get_world_transforms(&self) -> Vec<Instance>;
402
403    fn get_world_transform(&self, idx: usize) -> Option<&Instance>;
404
405    fn get_local_transform(&self, idx: usize) -> Option<&Instance>;
406
407    fn draw<'a, 'pass>(
408        &self,
409        camera_bind_group_layout: &'a wgpu::BindGroup,
410        light_bind_group: &'a wgpu::BindGroup,
411        render_pass: &'pass mut wgpu::RenderPass<'a>,
412    ) where
413        'a: 'pass;
414
415    fn to_clickable(&self, device: &wgpu::Device, id: PickId) -> Box<dyn SceneNode>;
416
417    fn get_children(&self) -> &Vec<Box<dyn SceneNode>>;
418
419    /// Adds a child node to the tree and returns the childs index
420    fn add_child(&mut self, child: Box<dyn SceneNode>) -> usize;
421
422    fn remove_child(&mut self, idx: usize) -> Box<dyn SceneNode>;
423
424    fn set_local_transform(&mut self, idx: usize, instance: Instance);
425
426    fn set_local_transform_all(&mut self, mutation: &mut dyn FnMut(&mut Instance));
427
428    fn get_children_mut(&mut self) -> &mut Vec<Box<dyn SceneNode>>;
429
430    fn write_to_buffers(&mut self, queue: &wgpu::Queue, device: &wgpu::Device);
431
432    /// Multiple instances of a parent can be passed down to multiple instances of multiple children.
433    /// The argument `parents_world_transform` with a matching `range` size provides control over which instances are transformed.
434    fn update_world_transforms(
435        &mut self,
436        range: Range<usize>,
437        parents_world_transform: &Vec<Instance>,
438    );
439
440    fn update_world_transform_all(&mut self);
441
442    /// Adds an instance to the scene node (and its children) and returns the index of the added instance
443    fn add_instance(&mut self, instance: Instance) -> usize;
444
445    /// Adds multiple instance to the scene node (and its children) and returns index of the last instance
446    fn add_instances(&mut self, instances: Vec<Instance>) -> usize;
447
448    fn set_instances(&mut self, instances: Vec<Instance>) -> usize;
449
450    fn remove_instance(&mut self, idx: usize) -> (Instance, Instance);
451
452    fn duplicate_instance(&mut self, i: usize) -> usize;
453
454    fn get_animation(&self) -> &Vec<ModelAnimation>;
455
456    fn get_render(&self) -> Vec<Instanced<'_>>;
457
458    fn get_render_dir(&self) -> wgpu::FrontFace {
459        wgpu::FrontFace::Ccw
460    }
461
462    fn render_inverted(&mut self);
463}
464impl dyn SceneNode {
465    pub fn transform_local(&mut self, instance: Instance) -> Instance {
466        let idx = self.add_child(Box::new(ContainerNode::from(instance)));
467        self.update_world_transforms(idx..idx + 1, &vec![Instance::new()]);
468        let child = self.remove_child(idx);
469        child.get_world_transforms()[0].clone()
470    }
471    pub fn transform_locals(&mut self, instances: Vec<Instance>) -> Vec<Instance> {
472        self.add_instances((0..instances.len()).map(|_| Instance::new()).collect());
473        let idx = self.add_child(Box::new(ContainerNode::from(instances)));
474        self.update_world_transforms(idx..idx + 1, &vec![Instance::new()]);
475        let child = self.remove_child(idx);
476        child.get_world_transforms()
477    }
478}
479
480/// Returns the local transformation of `children` in the `parent` space coordinates
481pub fn transform_locals(parent: &Instance, children: Vec<Instance>) -> Vec<Instance> {
482    let len = children.len();
483    let parents: Vec<_> = (0..len).map(|_| parent.clone()).collect();
484    let mut scene = ContainerNode::from(parents);
485    let child = scene.add_child(Box::new(ContainerNode::from(children)));
486    scene.update_world_transforms(0..len, &(0..len).map(|_| Instance::new()).collect());
487    scene.remove_child(child).get_world_transforms()
488}
489
490/// Returns the local transformation `child` in the `parent` coordinates
491pub fn transform_local(parent: &Instance, child: Instance) -> Instance {
492    parent * &child
493}
494
495#[cfg(feature = "integration-tests")]
496impl<'a, 'pass> GPUResource<'a, 'pass> for Box<dyn SceneNode> {
497    fn write_to_buffer(&mut self, queue: &wgpu::Queue, device: &wgpu::Device) {
498        // Delegate to the inner dyn SceneNode
499        (*self).write_to_buffers(queue, device);
500    }
501    fn get_render(&'a self) -> Render<'a, 'pass> {
502        Render::Defaults((**self).get_render())
503    }
504}
505
506impl<'a, 'pass, T> GPUResource<'a, 'pass> for T
507where
508    T: SceneNode,
509{
510    fn write_to_buffer(&mut self, queue: &wgpu::Queue, device: &wgpu::Device) {
511        self.write_to_buffers(queue, device);
512    }
513
514    fn get_render(&'a self) -> Render<'a, 'pass> {
515        Render::Defaults(self.get_render())
516    }
517}
518
519pub struct ContainerNode {
520    pub children: Vec<Box<dyn SceneNode>>,
521    pub instances: Vec<(Instance, Instance)>,
522    animations: Vec<ModelAnimation>,
523}
524
525impl ContainerNode {
526    pub fn new(amount: usize, animations: Vec<ModelAnimation>) -> Self {
527        let instances = (0..amount)
528            .map(|_| (Instance::default(), Instance::default()))
529            .collect();
530        let children = vec![];
531        Self {
532            instances,
533            children,
534            animations,
535        }
536    }
537}
538
539impl From<Instance> for ContainerNode {
540    fn from(value: Instance) -> Self {
541        ContainerNode {
542            children: vec![],
543            instances: vec![(value, Instance::default())],
544            animations: vec![],
545        }
546    }
547}
548
549impl From<Vec<Instance>> for ContainerNode {
550    fn from(value: Vec<Instance>) -> Self {
551        ContainerNode {
552            children: vec![],
553            instances: value
554                .iter()
555                .zip(value.iter())
556                .map(|(fst, snd)| (fst.clone(), snd.clone()))
557                .collect(),
558            animations: vec![],
559        }
560    }
561}
562
563impl SceneNode for ContainerNode {
564    fn remove_child(&mut self, idx: usize) -> Box<dyn SceneNode> {
565        self.children.remove(idx)
566    }
567
568    fn add_child(&mut self, child: Box<dyn SceneNode>) -> usize {
569        self.children.push(child);
570        return self.children.len() - 1;
571    }
572
573    fn set_local_transform(&mut self, idx: usize, instance: Instance) {
574        self.instances
575            .get_mut(idx)
576            .and_then(|(local, _)| Some(*local = instance));
577    }
578
579    fn set_local_transform_all(&mut self, mutation: &mut dyn FnMut(&mut Instance)) {
580        self.instances.iter_mut().for_each(|(local, _)| {
581            mutation(local);
582        });
583    }
584
585    fn get_world_transforms(&self) -> Vec<Instance> {
586        self.instances
587            .iter()
588            .map(|(_, world)| world)
589            .cloned()
590            .collect()
591    }
592
593    /**
594     * Multiple instances of a parent can be passed down to multiple instances of multiple children.
595     * The argument `parents_world_transform` with a matching `range` size provides control over which instances are transformed.
596     */
597    fn update_world_transforms(
598        &mut self,
599        range: Range<usize>,
600        parents_world_transform: &Vec<Instance>,
601    ) {
602        if parents_world_transform.len() > self.instances.len() {
603            warn!(
604                "You tried to transform with len {}, but there are only {} instances to transform.",
605                parents_world_transform.len(),
606                self.instances.len()
607            );
608            return;
609        }
610        if let None = self.instances.get(range.clone()) {
611            warn!(
612                "You tried to transform range {}..{}, which is out of bounds for parent len {}.",
613                range.clone().start,
614                range.end,
615                self.instances.len(),
616            );
617            return;
618        }
619        let world_transforms = self.instances[range.clone()]
620            .iter_mut()
621            .zip(parents_world_transform.into_iter())
622            .map(|((local, world), parent)| {
623                let world_transform = parent * local;
624                *world = parent * local;
625                world_transform
626            })
627            .collect::<Vec<_>>();
628        for child in self.children.iter_mut() {
629            child.update_world_transforms(range.clone(), &world_transforms);
630        }
631    }
632
633    fn get_children_mut(&mut self) -> &mut Vec<Box<dyn SceneNode>> {
634        &mut self.children
635    }
636
637    fn get_local_transform(&self, idx: usize) -> Option<&Instance> {
638        self.instances.get(idx).map(|(local, _)| local)
639    }
640
641    fn write_to_buffers(&mut self, queue: &wgpu::Queue, device: &wgpu::Device) {
642        self.get_children_mut()
643            .iter_mut()
644            .for_each(|child| child.write_to_buffers(queue, device));
645    }
646
647    fn draw<'a, 'pass>(
648        &self,
649        camera_bind_group: &'a wgpu::BindGroup,
650        light_bind_group: &'a wgpu::BindGroup,
651        render_pass: &'pass mut wgpu::RenderPass<'a>,
652    ) where
653        'a: 'pass,
654    {
655        for child in &self.children {
656            child.draw(camera_bind_group, light_bind_group, render_pass);
657        }
658    }
659
660    fn get_children(&self) -> &Vec<Box<dyn SceneNode>> {
661        &self.children
662    }
663
664    fn to_clickable(&self, device: &Device, id: PickId) -> Box<dyn SceneNode> {
665        let children = self
666            .children
667            .iter()
668            .map(|child| child.to_clickable(device, id))
669            .collect();
670
671        Box::new(Self {
672            children,
673            instances: self.instances.clone(),
674            animations: Vec::new(),
675        })
676    }
677
678    fn add_instance(&mut self, instance: Instance) -> usize {
679        self.instances.push((instance.clone(), instance));
680        for child in &mut self.children {
681            child.add_instance(Instance::default());
682        }
683        self.instances.len() - 1
684    }
685
686    fn update_world_transform_all(&mut self) {
687        let range = 0..self.instances.len();
688        let default_instances = range.clone().map(|_| Instance::default()).collect();
689        self.update_world_transforms(range, &default_instances);
690    }
691
692    /**
693     * Inserts a new instance which is a clone of the instance with index `i`.
694     *
695     * The return value is the index of the newly created instance.
696     */
697    fn duplicate_instance(&mut self, i: usize) -> usize {
698        self.instances
699            .push((self.instances[i].clone().0, self.instances[i].clone().1));
700        for child in &mut self.children {
701            child.duplicate_instance(i);
702        }
703        self.instances.len()
704    }
705
706    fn get_animation(&self) -> &Vec<ModelAnimation> {
707        &self.animations
708    }
709
710    fn get_render(&self) -> Vec<Instanced<'_>> {
711        self.children
712            .iter()
713            .flat_map(|child| (**child).get_render())
714            .collect()
715    }
716
717    fn remove_instance(&mut self, idx: usize) -> (Instance, Instance) {
718        self.children.iter_mut().for_each(|c| {
719            c.remove_instance(idx);
720        });
721        self.instances.remove(idx)
722    }
723
724    fn add_instances(&mut self, instances: Vec<Instance>) -> usize {
725        let cloned = instances.clone();
726        let len = instances.len();
727        let mut instances = instances.into_iter().zip(cloned).collect();
728        self.instances.append(&mut instances);
729        for child in &mut self.children {
730            child.add_instances((0..len).map(|_| Instance::default()).collect());
731        }
732        self.instances.len() - 1
733    }
734
735    fn get_world_transform(&self, idx: usize) -> Option<&Instance> {
736        self.instances.get(idx).map(|(_, world)| world)
737    }
738
739    fn set_instances(&mut self, instances: Vec<Instance>) -> usize {
740        let len = instances.len();
741        self.instances = instances.to_vec().into_iter().zip(instances).collect();
742        for child in &mut self.children {
743            child.set_instances((0..len).map(|_| Instance::default()).collect());
744        }
745        self.instances.len() - 1
746    }
747
748    fn render_inverted(&mut self) {}
749}
750
751pub struct ModelNode {
752    children: Vec<Box<dyn SceneNode>>,
753    front_face: wgpu::FrontFace,
754    instance_buffer: wgpu::Buffer,
755    instances: Vec<(Instance, Instance)>,
756    animations: Vec<ModelAnimation>,
757    buffer_size_needs_change: bool,
758    model: model::Model,
759    id: PickId,
760}
761
762impl ModelNode {
763    pub async fn new(
764        amount: usize,
765        id: impl Into<PickId>,
766        device: &Device,
767        queue: &Queue,
768        obj_file: &str,
769    ) -> Self {
770        let obj_model = load_model_obj(obj_file, &device, &queue).await;
771        if let Err(e) = obj_model {
772            panic!("Error failed to load model: {}, at {}", e, obj_file);
773        }
774        let obj_model = obj_model.unwrap();
775
776        Self::from_model(amount, id, device, obj_model, Vec::new())
777    }
778
779    pub fn from_model(
780        amount: usize,
781        id: impl Into<PickId>,
782        device: &Device,
783        obj_model: model::Model,
784        animations: Vec<ModelAnimation>,
785    ) -> Self {
786        let instances = (0..amount)
787            .map(|_| (Instance::default(), Instance::default()))
788            .collect::<Vec<_>>();
789
790        let instance_data = instances
791            .iter()
792            .map(|(_, world)| world)
793            .map(Instance::to_raw)
794            .collect::<Vec<_>>();
795
796        let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
797            label: Some("Instance Buffer"),
798            contents: bytemuck::cast_slice(&instance_data),
799            usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
800        });
801
802        let size_changed = false;
803        let direction = wgpu::FrontFace::Ccw;
804
805        Self {
806            children: vec![],
807            front_face: direction,
808            instance_buffer,
809            instances,
810            model: obj_model,
811            buffer_size_needs_change: size_changed,
812            animations,
813            id: id.into(),
814        }
815    }
816}
817
818impl SceneNode for ModelNode {
819    fn add_child(&mut self, child: Box<dyn SceneNode>) -> usize {
820        self.children.push(child);
821        self.children.len() - 1
822    }
823
824    fn set_local_transform(&mut self, idx: usize, instance: Instance) {
825        self.instances
826            .get_mut(idx)
827            .and_then(|(local, _)| Some(*local = instance));
828    }
829
830    fn set_local_transform_all(&mut self, mutation: &mut dyn FnMut(&mut Instance)) {
831        self.instances
832            .iter_mut()
833            .for_each(|(local, _)| mutation(local));
834    }
835
836    fn get_world_transforms(&self) -> Vec<Instance> {
837        self.instances
838            .iter()
839            .map(|(_, world)| world)
840            .cloned()
841            .collect()
842    }
843
844    /**
845     * Multiple instances of a parent can be passed down to multiple instances of multiple children.
846     * The argument `parents_world_transform` with a matching `range` size provides control over which instances are transformed.
847     */
848    fn update_world_transforms(
849        &mut self,
850        range: Range<usize>,
851        parents_world_transform: &Vec<Instance>,
852    ) {
853        if parents_world_transform.len() > self.instances.len() {
854            warn!(
855                "You tried to transform with len {}, but there are only {} instances to transform.",
856                parents_world_transform.len(),
857                self.instances.len()
858            );
859            return;
860        }
861        if let None = self.instances.get(range.clone()) {
862            warn!(
863                "you tried to transform range {}..{}, which is out of bounds for parent len {}.",
864                range.clone().start,
865                range.end,
866                self.instances.len(),
867            );
868            return;
869        }
870        let world_transforms = self.instances[range.clone()]
871            .iter_mut()
872            .zip(parents_world_transform.into_iter())
873            .map(|((local, world), parent)| {
874                let world_transform = parent * local;
875                *world = parent * local;
876                world_transform
877            })
878            .collect::<Vec<_>>();
879        for child in self.children.iter_mut() {
880            child.update_world_transforms(range.clone(), &world_transforms);
881        }
882    }
883
884    fn get_children_mut(&mut self) -> &mut Vec<Box<dyn SceneNode>> {
885        &mut self.children
886    }
887
888    fn get_local_transform(&self, idx: usize) -> Option<&Instance> {
889        self.instances.get(idx).map(|(local, _)| local)
890    }
891
892    fn write_to_buffers(&mut self, queue: &wgpu::Queue, device: &wgpu::Device) {
893        // If the underlying model is inverted then so are all instances (TODO: confirm)
894        if let Some((_, world)) = self.instances.first() {
895            let det = world.to_matrix().determinant().signum();
896            if det < 0.0 {
897                self.front_face = wgpu::FrontFace::Cw;
898            } else {
899                self.front_face = wgpu::FrontFace::Ccw;
900            }
901        }
902        let raw_instances: Vec<InstanceRaw> = self
903            .instances
904            .iter()
905            .map(|(_, world)| world.to_raw())
906            .collect();
907        if self.buffer_size_needs_change {
908            self.instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
909                label: Some("Instance Buffer"),
910                contents: bytemuck::cast_slice(&raw_instances),
911                usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
912            });
913            self.buffer_size_needs_change = false;
914        } else {
915            queue.write_buffer(
916                &self.instance_buffer,
917                0,
918                bytemuck::cast_slice(&raw_instances),
919            );
920        }
921        self.get_children_mut()
922            .iter_mut()
923            .for_each(|child| child.write_to_buffers(queue, device));
924    }
925
926    fn draw<'a, 'b>(
927        &self,
928        camera_bind_group: &'a wgpu::BindGroup,
929        light_bind_group: &'a wgpu::BindGroup,
930        render_pass: &'b mut wgpu::RenderPass<'a>,
931    ) where
932        'a: 'b,
933    {
934        let instances = self.get_world_transforms();
935        if !instances.is_empty() {
936            render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..));
937            render_pass.draw_model_instanced(
938                &self.model,
939                0..instances.len() as u32,
940                &camera_bind_group,
941                &light_bind_group,
942            );
943        }
944        for child in &self.children {
945            child.draw(camera_bind_group, light_bind_group, render_pass);
946        }
947    }
948
949    fn get_children(&self) -> &Vec<Box<dyn SceneNode>> {
950        &self.children
951    }
952
953    fn to_clickable(&self, device: &wgpu::Device, id: PickId) -> Box<dyn SceneNode> {
954        let obj_model = load_pick_model(&device, id, self.model.meshes.clone()).unwrap();
955
956        let children = self
957            .children
958            .iter()
959            .map(|child| child.to_clickable(device, id))
960            .collect();
961
962        Box::new(Self {
963            children,
964            front_face: self.front_face,
965            instance_buffer: self.instance_buffer.clone(),
966            instances: self.instances.clone(),
967            buffer_size_needs_change: false,
968            model: obj_model,
969            animations: Vec::new(),
970            id: id.into(),
971        })
972    }
973
974    fn add_instance(&mut self, instance: Instance) -> usize {
975        self.instances.push((instance.clone(), instance));
976        for child in &mut self.children {
977            child.add_instance(Instance::default());
978        }
979        self.buffer_size_needs_change = true;
980        self.instances.len() - 1
981    }
982
983    fn update_world_transform_all(&mut self) {
984        let range = 0..self.instances.len();
985        let default_instances = range.clone().map(|_| Instance::default()).collect();
986        self.update_world_transforms(range, &default_instances);
987    }
988
989    fn duplicate_instance(&mut self, i: usize) -> usize {
990        self.instances
991            .push((self.instances[i].clone().0, self.instances[i].clone().1));
992        for child in &mut self.children {
993            child.duplicate_instance(i);
994        }
995        self.buffer_size_needs_change = true;
996        self.instances.len() - 1
997    }
998
999    fn get_animation(&self) -> &Vec<ModelAnimation> {
1000        &self.animations
1001    }
1002
1003    fn get_render(&self) -> Vec<Instanced<'_>> {
1004        self.children
1005            .iter()
1006            .flat_map(|child| (**child).get_render())
1007            .chain([Instanced {
1008                instance: &self.instance_buffer,
1009                model: &self.model,
1010                amount: self.instances.len(),
1011                front_face: self.front_face,
1012                id: self.id,
1013            }])
1014            .collect()
1015    }
1016
1017    fn remove_instance(&mut self, idx: usize) -> (Instance, Instance) {
1018        self.children.iter_mut().for_each(|c| {
1019            c.remove_instance(idx);
1020        });
1021        self.buffer_size_needs_change = true;
1022        self.instances.remove(idx)
1023    }
1024
1025    fn add_instances(&mut self, instances: Vec<Instance>) -> usize {
1026        let cloned = instances.clone();
1027        let len = instances.len();
1028        let mut instances = instances.into_iter().zip(cloned).collect();
1029        self.instances.append(&mut instances);
1030        for child in &mut self.children {
1031            child.add_instances((0..len).map(|_| Instance::default()).collect());
1032        }
1033        self.buffer_size_needs_change = true;
1034        self.instances.len() - 1
1035    }
1036
1037    fn get_world_transform(&self, idx: usize) -> Option<&Instance> {
1038        self.instances.get(idx).map(|(_, world)| world)
1039    }
1040
1041    fn remove_child(&mut self, idx: usize) -> Box<dyn SceneNode> {
1042        self.children.remove(idx)
1043    }
1044
1045    fn set_instances(&mut self, instances: Vec<Instance>) -> usize {
1046        let len = instances.len();
1047        self.instances = instances.to_vec().into_iter().zip(instances).collect();
1048        for child in &mut self.children {
1049            child.set_instances((0..len).map(|_| Instance::default()).collect());
1050        }
1051        self.buffer_size_needs_change = true;
1052        self.instances.len() - 1
1053    }
1054
1055    fn render_inverted(&mut self) {
1056        self.front_face = wgpu::FrontFace::Cw;
1057    }
1058}
1059
1060pub async fn mk_flat_scene_graph(
1061    amount: usize,
1062    id: impl Into<PickId>,
1063    models: Vec<&'static str>,
1064    device: &wgpu::Device,
1065    queue: &wgpu::Queue,
1066) -> anyhow::Result<Box<dyn SceneNode + Send>> {
1067    let mut parent: Box<dyn SceneNode> = Box::new(ContainerNode::new(amount, Vec::new()));
1068    let id = id.into();
1069    futures::future::join_all(
1070        models
1071            .into_iter()
1072            .map(|obj_file| ModelNode::new(amount, id, device, queue, obj_file)),
1073    )
1074    .await
1075    .into_iter()
1076    .map(Box::new)
1077    .for_each(|boxed_model_node| {
1078        parent.add_child(boxed_model_node);
1079    });
1080    Ok(parent)
1081}
1082
1083#[cfg(test)]
1084mod tests {
1085    use super::*;
1086
1087    #[test]
1088    fn preserves_number_of_children() {
1089        let parent = Instance::default();
1090        let children = vec![
1091            Instance::default(),
1092            Instance::default(),
1093            Instance::default(),
1094        ];
1095
1096        let result = transform_locals(&parent, children.clone());
1097
1098        assert_eq!(result.len(), children.len());
1099    }
1100
1101    #[test]
1102    fn identity_parent_does_not_change_children() {
1103        let parent = Instance::default();
1104        let children = vec![
1105            Instance::from(cgmath::Vector3::from([1.0, 0.0, 0.0])),
1106            Instance::from(cgmath::Vector3::from([0.0, 2.0, 0.0])),
1107        ];
1108
1109        let result = transform_locals(&parent, children.clone());
1110
1111        for (a, b) in result.iter().zip(children.iter()) {
1112            assert_eq!(a.position, b.position);
1113            assert_eq!(a.scale, b.scale);
1114            assert_eq!(a.rotation, b.rotation);
1115        }
1116    }
1117
1118    #[test]
1119    fn existing_children_unchanged() {
1120        let parent = Instance::default();
1121        let children = vec![
1122            Instance::from(cgmath::Vector3::from([1.0, 0.0, 0.0])),
1123            Instance::from(cgmath::Vector3::from([0.0, 2.0, 0.0])),
1124        ];
1125
1126        let result = transform_locals(&parent, children.clone());
1127
1128        for (a, b) in result.iter().zip(children.iter()) {
1129            assert_eq!(a.position, b.position);
1130            assert_eq!(a.scale, b.scale);
1131            assert_eq!(a.rotation, b.rotation);
1132        }
1133    }
1134
1135    #[test]
1136    fn parent_translation_is_removed() {
1137        let parent = Instance::from(cgmath::Vector3::from([10.0, 0.0, 0.0]));
1138
1139        let children = vec![
1140            Instance::from(cgmath::Vector3::from([1.0, 0.0, 0.0])),
1141            Instance::from(cgmath::Vector3::from([2.0, 0.0, 0.0])),
1142        ];
1143
1144        let result = transform_locals(&parent, children);
1145
1146        let expected = vec![
1147            Instance::from(cgmath::Vector3::from([11.0, 0.0, 0.0])),
1148            Instance::from(cgmath::Vector3::from([12.0, 0.0, 0.0])),
1149        ];
1150
1151        for (a, b) in result.iter().zip(expected.iter()) {
1152            assert_eq!(a.position, b.position);
1153            assert_eq!(a.scale, b.scale);
1154            assert_eq!(a.rotation, b.rotation);
1155        }
1156    }
1157
1158    #[test]
1159    fn empty_children_returns_empty() {
1160        let parent = Instance::default();
1161        let children = Vec::new();
1162
1163        let result = transform_locals(&parent, children);
1164
1165        assert!(result.is_empty());
1166    }
1167}