renderling/
stage.rs

1//! Scene staging.
2//!
3//! The [`Stage`] is the entrypoint for staging data on the GPU and
4//! interacting with lighting.
5
6#[cfg(cpu)]
7mod cpu;
8#[cfg(cpu)]
9pub use cpu::*;
10
11#[cfg(test)]
12mod test {
13    use craballoc::{prelude::SlabAllocator, runtime::CpuRuntime};
14    use glam::{Mat4, Quat, Vec3};
15
16    use crate::{
17        math::IsMatrix,
18        transform::{shader::TransformDescriptor, NestedTransform},
19    };
20
21    #[test]
22    fn matrix_hierarchy_sanity() {
23        let a: Mat4 = TransformDescriptor {
24            translation: Vec3::new(100.0, 100.0, 0.0),
25            ..Default::default()
26        }
27        .into();
28        let b: Mat4 = TransformDescriptor {
29            scale: Vec3::splat(0.5),
30            ..Default::default()
31        }
32        .into();
33        let c1 = a * b;
34        let c2 = b * a;
35        assert_ne!(c1, c2);
36    }
37
38    #[test]
39    fn nested_transform_fox_rigging() {
40        pub fn legacy_get_world_transform(tfrm: &NestedTransform) -> (Vec3, Quat, Vec3) {
41            let mut mat = Mat4::IDENTITY;
42            let mut local = Some(tfrm.clone());
43            while let Some(t) = local.take() {
44                let transform = t.local_descriptor();
45                mat = Mat4::from_scale_rotation_translation(
46                    transform.scale,
47                    transform.rotation,
48                    transform.translation,
49                ) * mat;
50                local = t.parent();
51            }
52            let (s, r, t) = mat.to_scale_rotation_translation_or_id();
53            (t, r, s)
54        }
55
56        let slab = SlabAllocator::new(CpuRuntime, "transform", ());
57        let a = NestedTransform::new(&slab);
58        a.set_local_translation(Vec3::splat(100.0));
59        let b = NestedTransform::new(&slab);
60        b.set_local_rotation(Quat::from_scaled_axis(Vec3::Z));
61        let c = NestedTransform::new(&slab);
62        c.set_local_scale(Vec3::splat(2.0));
63
64        a.add_child(&b);
65        b.add_child(&c);
66
67        let TransformDescriptor {
68            translation,
69            rotation,
70            scale,
71        } = c.global_descriptor();
72        let global_transform = (translation, rotation, scale);
73        let legacy_transform = legacy_get_world_transform(&c);
74        assert_eq!(legacy_transform, global_transform);
75
76        c.set_local_translation(Vec3::ONE);
77
78        let all_updates = slab.get_updated_source_ids();
79        assert_eq!(
80            std::collections::HashSet::from_iter([
81                a.global_transform.descriptor.notifier_index(),
82                b.global_transform.descriptor.notifier_index(),
83                c.global_transform.descriptor.notifier_index()
84            ]),
85            all_updates
86        );
87
88        let TransformDescriptor {
89            translation,
90            rotation,
91            scale,
92        } = c.global_descriptor();
93        let global_transform = (translation, rotation, scale);
94        let legacy_transform = legacy_get_world_transform(&c);
95        assert_eq!(legacy_transform, global_transform);
96    }
97}