renderling/
transform.rs

1//! Decomposed 3d transforms and hierarchies.
2
3#[cfg(cpu)]
4mod cpu;
5#[cfg(cpu)]
6pub use cpu::*;
7
8pub mod shader {
9    use crabslab::SlabItem;
10    use glam::{Mat4, Quat, Vec3};
11
12    use crate::math::IsMatrix;
13
14    #[derive(Clone, Copy, PartialEq, SlabItem, core::fmt::Debug)]
15    /// A GPU descriptor of a decomposed transformation.
16    ///
17    /// `TransformDescriptor` can be converted to/from [`Mat4`].
18    pub struct TransformDescriptor {
19        pub translation: Vec3,
20        pub rotation: Quat,
21        pub scale: Vec3,
22    }
23
24    impl Default for TransformDescriptor {
25        fn default() -> Self {
26            Self::IDENTITY
27        }
28    }
29
30    impl From<Mat4> for TransformDescriptor {
31        fn from(value: Mat4) -> Self {
32            let (scale, rotation, translation) = value.to_scale_rotation_translation_or_id();
33            TransformDescriptor {
34                translation,
35                rotation,
36                scale,
37            }
38        }
39    }
40
41    impl From<TransformDescriptor> for Mat4 {
42        fn from(
43            TransformDescriptor {
44                translation,
45                rotation,
46                scale,
47            }: TransformDescriptor,
48        ) -> Self {
49            Mat4::from_scale_rotation_translation(scale, rotation, translation)
50        }
51    }
52
53    impl TransformDescriptor {
54        pub const IDENTITY: Self = TransformDescriptor {
55            translation: Vec3::ZERO,
56            rotation: Quat::IDENTITY,
57            scale: Vec3::ONE,
58        };
59    }
60}
61
62#[cfg(test)]
63mod test {
64    use crabslab::*;
65    use glam::{Quat, Vec3};
66
67    use crate::transform::shader::TransformDescriptor;
68
69    #[test]
70    fn transform_roundtrip() {
71        assert_eq!(3, Vec3::SLAB_SIZE, "unexpected Vec3 slab size");
72        assert_eq!(4, Quat::SLAB_SIZE, "unexpected Quat slab size");
73        assert_eq!(10, TransformDescriptor::SLAB_SIZE);
74        let t = TransformDescriptor::default();
75        let mut slab = CpuSlab::new(vec![]);
76        let t_id = slab.append(&t);
77        pretty_assertions::assert_eq!(
78            &[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0],
79            bytemuck::cast_slice::<u32, f32>(slab.as_ref().as_slice())
80        );
81        pretty_assertions::assert_eq!(t, slab.read(t_id));
82    }
83}