dreamwell_engine/
transform.rs1use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
13pub struct GlobalTransform(pub [f32; 16]);
14
15impl GlobalTransform {
16 pub fn identity() -> Self {
18 #[rustfmt::skip]
19 let m = [
20 1.0, 0.0, 0.0, 0.0,
21 0.0, 1.0, 0.0, 0.0,
22 0.0, 0.0, 1.0, 0.0,
23 0.0, 0.0, 0.0, 1.0,
24 ];
25 Self(m)
26 }
27
28 pub fn mul(&self, rhs: &GlobalTransform) -> GlobalTransform {
30 let a = &self.0;
31 let b = &rhs.0;
32 let mut out = [0.0f32; 16];
33 for col in 0..4 {
34 for row in 0..4 {
35 out[col * 4 + row] = a[row] * b[col * 4]
36 + a[4 + row] * b[col * 4 + 1]
37 + a[8 + row] * b[col * 4 + 2]
38 + a[12 + row] * b[col * 4 + 3];
39 }
40 }
41 GlobalTransform(out)
42 }
43
44 pub fn translation(&self) -> [f32; 3] {
46 [self.0[12], self.0[13], self.0[14]]
47 }
48}
49
50impl Default for GlobalTransform {
51 fn default() -> Self {
52 Self::identity()
53 }
54}
55
56pub fn mat4_mul(a: &[f32; 16], b: &[f32; 16]) -> [f32; 16] {
59 let mut out = [0.0f32; 16];
60 for col in 0..4 {
61 for row in 0..4 {
62 out[col * 4 + row] = a[row] * b[col * 4]
63 + a[4 + row] * b[col * 4 + 1]
64 + a[8 + row] * b[col * 4 + 2]
65 + a[12 + row] * b[col * 4 + 3];
66 }
67 }
68 out
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn identity_default() {
77 let g = GlobalTransform::default();
78 assert_eq!(g, GlobalTransform::identity());
79 }
80
81 #[test]
82 fn identity_mul_identity() {
83 let id = GlobalTransform::identity();
84 let result = id.mul(&id);
85 for i in 0..16 {
86 assert!((result.0[i] - id.0[i]).abs() < 1e-6);
87 }
88 }
89
90 #[test]
91 fn translation_extraction() {
92 let mut g = GlobalTransform::identity();
93 g.0[12] = 5.0;
94 g.0[13] = 10.0;
95 g.0[14] = -3.0;
96 assert_eq!(g.translation(), [5.0, 10.0, -3.0]);
97 }
98
99 #[test]
100 fn mul_with_translation() {
101 let mut a = GlobalTransform::identity();
102 a.0[12] = 1.0; let mut b = GlobalTransform::identity();
104 b.0[12] = 2.0; let c = a.mul(&b);
106 assert!((c.0[12] - 3.0).abs() < 1e-6); }
108
109 #[test]
110 fn mat4_mul_identity() {
111 #[rustfmt::skip]
112 let id = [
113 1.0, 0.0, 0.0, 0.0,
114 0.0, 1.0, 0.0, 0.0,
115 0.0, 0.0, 1.0, 0.0,
116 0.0, 0.0, 0.0, 1.0,
117 ];
118 let result = mat4_mul(&id, &id);
119 for i in 0..16 {
120 assert!((result[i] - id[i]).abs() < 1e-6);
121 }
122 }
123
124 #[test]
125 fn mat4_mul_translation_compose() {
126 #[rustfmt::skip]
127 let a = [
128 1.0, 0.0, 0.0, 0.0,
129 0.0, 1.0, 0.0, 0.0,
130 0.0, 0.0, 1.0, 0.0,
131 10.0, 0.0, 0.0, 1.0,
132 ];
133 #[rustfmt::skip]
134 let b = [
135 1.0, 0.0, 0.0, 0.0,
136 0.0, 1.0, 0.0, 0.0,
137 0.0, 0.0, 1.0, 0.0,
138 5.0, 0.0, 0.0, 1.0,
139 ];
140 let c = mat4_mul(&a, &b);
141 assert!((c[12] - 15.0).abs() < 1e-6);
142 }
143}