1use glium::uniforms::AsUniformValue;
2use crate::{matrices::Mat4, quaternions::Quat, vectors::{Vec3, Vec2}};
3
4use super::Mat2;
5
6#[derive(Clone, Copy, PartialEq, Debug)]
7pub struct Mat3 {
9 matrix: [[f32; 3]; 3]
10}
11impl Mat3{
12 pub const IDENTITY: Self = Mat3::from_values(
13 1.0, 0.0, 0.0,
14 0.0, 1.0, 0.0,
15 0.0, 0.0, 1.0,
16 );
17 pub const fn from_colum_major_array(array: [[f32; 3]; 3]) -> Self { Self { matrix: array } }
18 pub const fn into_column_major_array(self) -> [[f32; 3]; 3] { self.matrix }
19 pub const fn from_row_major_array(array: [[f32; 3]; 3]) -> Self { Self { matrix: array }.transpose() }
20 pub const fn into_row_major_array(self) -> [[f32; 3]; 3] { self.transpose().matrix }
21 pub const fn from_scale(scale: Vec3) -> Self {
22 let (x, y, z) = (scale.x, scale.y, scale.z);
23 Mat3::from_values(
24 x, 0.0, 0.0,
25 0.0, y, 0.0,
26 0.0, 0.0, z,
27 )
28 }
29 pub fn from_2d_transform(pos: Vec2, scale: Vec2, rot: f32) -> Self {
30 Self::from_values(
31 scale.x * rot.cos(), scale.y * -rot.sin(), pos.x,
32 scale.x * rot.sin(), scale.y * rot.cos(), pos.y,
33 0.0, 0.0, 1.0
34 )
35 }
36 pub fn from_transform(scale: Vec3, rot: Quat) -> Self{
37 let (r, i, j, k) = (rot.r, rot.i, rot.j, rot.k);
38 let (sx, sy, sz) = (scale.x * 2.0, scale.y * 2.0, scale.z * 2.0);
39 Mat3::from_values(
40 sx*(0.5 - (j*j + k*k)), sy*(i*j - k*r), sz*(i*k + j*r),
41 sx*(i*j + k*r), sy*(0.5 - (i*i + k*k)), sz*(j*k - i*r),
42 sx*(i*k - j*r), sy*(j*k + i*r), sz*(0.5 - (i*i + j*j))
43 )
44 }
45 pub fn from_rot(rot: Quat) -> Self { rot.into() }
46 #[allow(clippy::too_many_arguments)]
58 pub const fn from_values(
59 a: f32, b: f32, c: f32,
60 d: f32, e: f32, f: f32,
61 g: f32, h: f32, i: f32
62 ) -> Self{
63 Self{
64 matrix: [
66 [a, d, g],
67 [b, e, h],
68 [c, f, i],
69 ]
70 }
71 }
72 pub fn scale(&self, scalar: f32) -> Mat3{
73 let Mat3 { matrix: [
74 [a, d, g],
75 [b, e, h],
76 [c, f, i],
77 ]} = self;
78 Self::from_values(
79 a * scalar, b * scalar, c * scalar,
80 d * scalar, e * scalar, f * scalar,
81 g * scalar, h * scalar, i * scalar
82 )
83 }
84 pub fn determinant(&self) -> f32{
85 let Mat3 { matrix: [
86 [a, d, g],
87 [b, e, h],
88 [c, f, i],
89 ]} = self;
90 a*(e*i - f*h) - b*(d*i - f*g) + c*(d*h - e*g)
91 }
92 #[allow(non_snake_case)]
93 pub fn inverse(&self) -> Mat3{
94 let Mat3 { matrix: [
95 [a, d, g],
96 [b, e, h],
97 [c, f, i],
98 ]} = self;
99 let A = e*i - f*h;
100 let B = -(d*i - f*g);
101 let C = d*h - e*g;
102
103 let determinet = a*A + b*B + c*C;
104 let scalar = 1.0/determinet;
105 Self::from_values(
106 A, -(b*i - c*h), b*f - c*e,
107 B, a*i - c*g, -(a*f - c*d),
108 C, -(a*h - b*g), a*e - b*d
109 ).scale(scalar)
110 }
111 pub const fn transpose(self) -> Self {
112 let Mat3 { matrix: [
113 [a, d, g],
114 [b, e, h],
115 [c, f, i],
116 ]} = self;
117 Mat3::from_values(
118 a, d, g,
119 b, e, h,
120 c, f, i
121 )
122 }
123 pub const fn column(&self, pos: usize) -> [f32; 3] {
124 self.matrix[pos]
125 }
126 pub const fn row(&self, pos: usize) -> [f32; 3] {
127 let matrix = self.matrix;
128 [matrix[0][pos], matrix[1][pos], matrix[2][pos]]
129 }
130}
131
132impl Default for Mat3 {
133 fn default() -> Self {
134 Self { matrix: [
135 [1.0, 0.0, 0.0,],
136 [0.0, 1.0, 0.0,],
137 [0.0, 0.0, 1.0,],
138 ] }
139 }
140
141}
142impl std::ops::Mul<Vec3> for Mat3 {
143 fn mul(self, rhs: Vec3) -> Self::Output { rhs.transform(self) }
144 type Output = Vec3;
145}
146impl std::ops::Mul<f32> for Mat3 {
147 fn mul(self, rhs: f32) -> Self::Output { self.scale(rhs) }
148 type Output = Self;
149}
150impl std::ops::Mul<Mat3> for f32 {
151 fn mul(self, rhs: Mat3) -> Self::Output { rhs * self }
152 type Output = Mat3;
153}
154impl std::ops::MulAssign<f32> for Mat3 {
155 fn mul_assign(&mut self, rhs: f32) { *self = *self * rhs }
156}
157impl std::ops::Div<Mat3> for f32 {
158 fn div(self, rhs: Mat3) -> Self::Output {
159 let Mat3 { matrix: [
160 [a, d, g],
161 [b, e, h],
162 [c, f, i],
163 ]} = rhs;
164 Mat3::from_values(
165 self/a, self/b, self/c,
166 self/d, self/e, self/f,
167 self/g, self/h, self/i
168 )
169 }
170 type Output = Mat3;
171}
172impl std::ops::Div<f32> for Mat3 {
173 fn div(self, rhs: f32) -> Self::Output { self.scale(1.0/rhs) }
174 type Output = Self;
175}
176impl std::ops::DivAssign<f32> for Mat3 {
177 fn div_assign(&mut self, rhs: f32) { *self = *self / rhs }
178}
179impl std::ops::Rem<Mat3> for f32 {
180 fn rem(self, rhs: Mat3) -> Self::Output {
181 let Mat3 { matrix: [
182 [a, d, g],
183 [b, e, h],
184 [c, f, i],
185 ]} = rhs;
186 Mat3::from_values(
187 self%a, self%b, self%c,
188 self%d, self%e, self%f,
189 self%g, self%h, self%i
190 )
191 }
192 type Output = Mat3;
193}
194impl std::ops::Rem<f32> for Mat3 {
195 fn rem(self, rhs: f32) -> Self::Output {
196 let Mat3 { matrix: [
197 [a, d, g],
198 [b, e, h],
199 [c, f, i],
200 ]} = self;
201 Mat3::from_values(
202 a%rhs, b%rhs, c%rhs,
203 d%rhs, e%rhs, f%rhs,
204 g%rhs, h%rhs, i%rhs
205 )
206 }
207 type Output = Self;
208}
209impl std::ops::RemAssign<f32> for Mat3 {
210 fn rem_assign(&mut self, rhs: f32) { *self = *self % rhs }
211}
212#[allow(clippy::needless_range_loop)]
213impl std::ops::Mul for Mat3{
214 fn mul(self, rhs: Self) -> Self::Output {
215 let mut matrix = [[0.0; 3]; 3];
216 for x in 0..3 {
217 for y in 0..3 {
218 matrix[x][y] = Vec3::dot(self.row(y).into(), rhs.column(x).into());
219 }
220 }
221 Self {
222 matrix
223 }
224 }
225 type Output = Self;
226}
227impl std::ops::MulAssign for Mat3 {
228 fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs }
229}
230#[allow(clippy::suspicious_arithmetic_impl)]
231impl std::ops::Div for Mat3 {
232 fn div(self, rhs: Self) -> Self::Output { self * rhs.inverse() }
233 type Output = Self;
234}
235impl std::ops::DivAssign for Mat3 {
236 fn div_assign(&mut self, rhs: Self) { *self = *self / rhs }
237}
238impl AsUniformValue for Mat3 {
239 fn as_uniform_value(&self) -> glium::uniforms::UniformValue<'_> {
240 glium::uniforms::UniformValue::Mat3(self.matrix)
241 }
242}
243impl std::ops::Add for Mat3{
244 fn add(self, rhs: Self) -> Self::Output {
245 let a = self.matrix;
246 let b = rhs.matrix;
247 Self{
248 matrix:[
249 [a[0][0] + b[0][0], a[0][1] + b[0][1], a[0][2] + b[0][2]],
250 [a[1][0] + b[1][0], a[1][1] + b[1][1], a[1][2] + b[1][2]],
251 [a[2][0] + b[2][0], a[2][1] + b[2][1], a[2][2] + b[2][2]],
252 ]
253 }
254 }
255 type Output = Self;
256}
257impl std::ops::AddAssign for Mat3{
258 fn add_assign(&mut self, rhs: Self) {
259 let a = self.matrix;
260 let b = rhs.matrix;
261 *self = Self{
262 matrix:[
263 [a[0][0] + b[0][0], a[0][1] + b[0][1], a[0][2] + b[0][2]],
264 [a[1][0] + b[1][0], a[1][1] + b[1][1], a[1][2] + b[1][2]],
265 [a[2][0] + b[2][0], a[2][1] + b[2][1], a[2][2] + b[2][2]],
266 ]
267 };
268 }
269}
270impl std::ops::Sub for Mat3{
271 fn sub(self, rhs: Self) -> Self::Output {
272 let a = self.matrix;
273 let b = rhs.matrix;
274 Self { matrix:[
275 [a[0][0] - b[0][0], a[0][1] - b[0][1], a[0][2] - b[0][2]],
276 [a[1][0] - b[1][0], a[1][1] - b[1][1], a[1][2] - b[1][2]],
277 [a[2][0] - b[2][0], a[2][1] - b[2][1], a[2][2] - b[2][2]],
278 ] }
279 }
280 type Output = Self;
281}
282impl std::ops::SubAssign for Mat3{
283 fn sub_assign(&mut self, rhs: Self) {
284 let a = self.matrix;
285 let b = rhs.matrix;
286 *self = Self { matrix:[
287 [a[0][0] - b[0][0], a[0][1] - b[0][1], a[0][2] - b[0][2]],
288 [a[1][0] - b[1][0], a[1][1] - b[1][1], a[1][2] - b[1][2]],
289 [a[2][0] - b[2][0], a[2][1] - b[2][1], a[2][2] - b[2][2]],
290 ] };
291 }
292}
293impl From<Mat4> for Mat3{
294 fn from(value: Mat4) -> Self {
295 Self::from_values(
296 value[0][0], value[0][1], value[0][2],
297 value[1][0], value[1][1], value[1][2],
298 value[2][0], value[2][1], value[2][2]
299 )
300 }
301}
302impl From<Mat2> for Mat3{
303 fn from(value: Mat2) -> Self {
304 Self::from_values(
305 value[0][0], value[0][1], 0.0,
306 value[1][0], value[1][1], 0.0,
307 0.0, 0.0, 1.0
308 )
309 }
310}
311impl From<Quat> for Mat3 {
312 fn from(value: Quat) -> Mat3 {
313 let Quat { r, i, j, k } = value;
314 Mat3::from_values(
315 1.0 - 2.0*(j*j + k*k), 2.0*(i*j - k*r), 2.0*(i*k + j*r),
316 2.0*(i*j + k*r), 1.0 - 2.0*(i*i + k*k), 2.0*(j*k - i*r),
317 2.0*(i*k - j*r), 2.0*(j*k + i*r), 1.0 - 2.0*(i*i + j*j)
318 )
319 }
320}
321impl std::ops::Index<usize> for Mat3{
322 fn index(&self, index: usize) -> &Self::Output {
323 &self.matrix[index]
324 }
325 type Output = [f32; 3];
326}
327impl std::ops::IndexMut<usize> for Mat3{
328 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
329 &mut self.matrix[index]
330 }
331}
332#[test]
333fn test_inverse(){
334 let mut a = Mat3::from_values(
335 4.0, 0.0, 2.0,
336 1.0, 3.0, 8.0,
337 2.0, 3.0, 4.0
338 );
339 a = a.inverse() * a;
340 assert!(a == Mat3::IDENTITY)
341}