goud_engine/ecs/components/transform2d/
mat3x3.rs1use crate::core::math::Vec2;
4
5#[repr(C)]
17#[derive(Clone, Copy, Debug, PartialEq)]
18pub struct Mat3x3 {
19 pub m: [f32; 9],
21}
22
23impl Mat3x3 {
24 pub const IDENTITY: Mat3x3 = Mat3x3 {
26 m: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
27 };
28
29 #[inline]
31 pub const fn new(m: [f32; 9]) -> Self {
32 Self { m }
33 }
34
35 #[inline]
44 pub const fn from_rows(
45 m00: f32,
46 m01: f32,
47 m02: f32,
48 m10: f32,
49 m11: f32,
50 m12: f32,
51 m20: f32,
52 m21: f32,
53 m22: f32,
54 ) -> Self {
55 Self {
57 m: [m00, m10, m20, m01, m11, m21, m02, m12, m22],
58 }
59 }
60
61 #[inline]
63 pub fn translation(tx: f32, ty: f32) -> Self {
64 Self {
65 m: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, tx, ty, 1.0],
66 }
67 }
68
69 #[inline]
71 pub fn rotation(angle: f32) -> Self {
72 let (sin, cos) = angle.sin_cos();
73 Self {
74 m: [cos, sin, 0.0, -sin, cos, 0.0, 0.0, 0.0, 1.0],
75 }
76 }
77
78 #[inline]
80 pub fn scale(sx: f32, sy: f32) -> Self {
81 Self {
82 m: [sx, 0.0, 0.0, 0.0, sy, 0.0, 0.0, 0.0, 1.0],
83 }
84 }
85
86 #[inline]
88 pub fn get_translation(&self) -> Vec2 {
89 Vec2::new(self.m[6], self.m[7])
90 }
91
92 #[inline]
94 pub fn multiply(&self, other: &Self) -> Self {
95 let a = &self.m;
96 let b = &other.m;
97
98 Self {
99 m: [
100 a[0] * b[0] + a[3] * b[1] + a[6] * b[2],
101 a[1] * b[0] + a[4] * b[1] + a[7] * b[2],
102 a[2] * b[0] + a[5] * b[1] + a[8] * b[2],
103 a[0] * b[3] + a[3] * b[4] + a[6] * b[5],
104 a[1] * b[3] + a[4] * b[4] + a[7] * b[5],
105 a[2] * b[3] + a[5] * b[4] + a[8] * b[5],
106 a[0] * b[6] + a[3] * b[7] + a[6] * b[8],
107 a[1] * b[6] + a[4] * b[7] + a[7] * b[8],
108 a[2] * b[6] + a[5] * b[7] + a[8] * b[8],
109 ],
110 }
111 }
112
113 #[inline]
115 pub fn transform_point(&self, point: Vec2) -> Vec2 {
116 Vec2::new(
117 self.m[0] * point.x + self.m[3] * point.y + self.m[6],
118 self.m[1] * point.x + self.m[4] * point.y + self.m[7],
119 )
120 }
121
122 #[inline]
124 pub fn transform_direction(&self, direction: Vec2) -> Vec2 {
125 Vec2::new(
126 self.m[0] * direction.x + self.m[3] * direction.y,
127 self.m[1] * direction.x + self.m[4] * direction.y,
128 )
129 }
130
131 #[inline]
133 pub fn determinant(&self) -> f32 {
134 let m = &self.m;
135 m[0] * (m[4] * m[8] - m[7] * m[5]) - m[3] * (m[1] * m[8] - m[7] * m[2])
136 + m[6] * (m[1] * m[5] - m[4] * m[2])
137 }
138
139 pub fn inverse(&self) -> Option<Self> {
143 let det = self.determinant();
144 if det.abs() < f32::EPSILON {
145 return None;
146 }
147
148 let m = &self.m;
149 let inv_det = 1.0 / det;
150
151 Some(Self {
152 m: [
153 (m[4] * m[8] - m[7] * m[5]) * inv_det,
154 (m[7] * m[2] - m[1] * m[8]) * inv_det,
155 (m[1] * m[5] - m[4] * m[2]) * inv_det,
156 (m[6] * m[5] - m[3] * m[8]) * inv_det,
157 (m[0] * m[8] - m[6] * m[2]) * inv_det,
158 (m[3] * m[2] - m[0] * m[5]) * inv_det,
159 (m[3] * m[7] - m[6] * m[4]) * inv_det,
160 (m[6] * m[1] - m[0] * m[7]) * inv_det,
161 (m[0] * m[4] - m[3] * m[1]) * inv_det,
162 ],
163 })
164 }
165
166 #[inline]
176 pub fn to_mat4(&self) -> [f32; 16] {
177 [
178 self.m[0], self.m[1], 0.0, 0.0, self.m[3], self.m[4], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, self.m[6], self.m[7], 0.0, 1.0, ]
183 }
184}
185
186impl Default for Mat3x3 {
187 #[inline]
188 fn default() -> Self {
189 Self::IDENTITY
190 }
191}
192
193impl std::ops::Mul for Mat3x3 {
194 type Output = Self;
195
196 #[inline]
197 fn mul(self, other: Self) -> Self {
198 self.multiply(&other)
199 }
200}