1use crate::vec3::Vec3;
2use crate::vec4::{Vec4, Meters, Pixels, World, Local, Screen};
3use core::ops::{Add, Mul, Sub};
4use core::marker::PhantomData;
5use crate::math;
6#[cfg(feature = "unit_vec")]
7use crate::unit_vec::UnitVec3;
8
9#[derive(Debug, Clone, Copy, PartialEq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Mat4<Unit: Copy = (), Space: Copy = ()> {
12 pub x_col: Vec4<Unit, Space>,
13 pub y_col: Vec4<Unit, Space>,
14 pub z_col: Vec4<Unit, Space>,
15 pub w_col: Vec4<Unit, Space>,
16 #[cfg_attr(feature = "serde", serde(skip))]
17 pub _unit: PhantomData<Unit>,
18 #[cfg_attr(feature = "serde", serde(skip))]
19 pub _space: PhantomData<Space>,
20}
21
22pub type Mat4f32 = Mat4<(),()>;
24pub type Mat4Meters = Mat4<Meters,()>;
25pub type Mat4Pixels = Mat4<Pixels,()>;
26pub type Mat4World = Mat4<(),World>;
27pub type Mat4Local = Mat4<(),Local>;
28pub type Mat4Screen = Mat4<(),Screen>;
29pub type Mat4MetersWorld = Mat4<Meters,World>;
30pub type Mat4PixelsScreen = Mat4<Pixels,Screen>;
31
32impl<Unit: Copy, Space: Copy> Mat4<Unit, Space> {
33 pub const ZERO: Self = Self {
34 x_col: Vec4::ZERO,
35 y_col: Vec4::ZERO,
36 z_col: Vec4::ZERO,
37 w_col: Vec4::ZERO,
38 _unit: PhantomData,
39 _space: PhantomData,
40 };
41
42 pub const IDENTITY: Self = Self {
43 x_col: Vec4::new(1.0, 0.0, 0.0, 0.0),
44 y_col: Vec4::new(0.0, 1.0, 0.0, 0.0),
45 z_col: Vec4::new(0.0, 0.0, 1.0, 0.0),
46 w_col: Vec4::new(0.0, 0.0, 0.0, 1.0),
47 _unit: PhantomData,
48 _space: PhantomData,
49 };
50
51 #[inline]
52 pub const fn new(x_col: Vec4<Unit, Space>, y_col: Vec4<Unit, Space>, z_col: Vec4<Unit, Space>, w_col: Vec4<Unit, Space>) -> Self {
53 Self { x_col, y_col, z_col, w_col, _unit: PhantomData, _space: PhantomData }
54 }
55
56 #[inline]
58 pub const fn from_cols_array(data: &[f32; 16]) -> Self {
59 Self {
60 x_col: Vec4::new(data[0], data[1], data[2], data[3]),
61 y_col: Vec4::new(data[4], data[5], data[6], data[7]),
62 z_col: Vec4::new(data[8], data[9], data[10], data[11]),
63 w_col: Vec4::new(data[12], data[13], data[14], data[15]),
64 _unit: PhantomData,
65 _space: PhantomData,
66 }
67 }
68
69 #[inline]
71 pub const fn from_rows(
72 r0c0: f32,
73 r0c1: f32,
74 r0c2: f32,
75 r0c3: f32,
76 r1c0: f32,
77 r1c1: f32,
78 r1c2: f32,
79 r1c3: f32,
80 r2c0: f32,
81 r2c1: f32,
82 r2c2: f32,
83 r2c3: f32,
84 r3c0: f32,
85 r3c1: f32,
86 r3c2: f32,
87 r3c3: f32,
88 ) -> Self {
89 Self {
90 x_col: Vec4::new(r0c0, r1c0, r2c0, r3c0),
91 y_col: Vec4::new(r0c1, r1c1, r2c1, r3c1),
92 z_col: Vec4::new(r0c2, r1c2, r2c2, r3c2),
93 w_col: Vec4::new(r0c3, r1c3, r2c3, r3c3),
94 _unit: PhantomData,
95 _space: PhantomData,
96 }
97 }
98
99 #[inline]
101 pub const fn from_translation(v: Vec3) -> Self {
102 Self {
103 x_col: Vec4::new(1.0, 0.0, 0.0, 0.0),
104 y_col: Vec4::new(0.0, 1.0, 0.0, 0.0),
105 z_col: Vec4::new(0.0, 0.0, 1.0, 0.0),
106 w_col: Vec4::new(v.x, v.y, v.z, 1.0),
107 _unit: PhantomData,
108 _space: PhantomData,
109 }
110 }
111
112 #[inline]
114 pub fn from_axis_angle_radians(axis: Vec3, angle: crate::angle::Radians) -> Self {
115 let c = math::cos(angle.0);
116 let s = math::sin(angle.0);
117
118 let axis_norm = axis.normalize(); let t = axis_norm * (1.0 - c); let r0c0 = c + t.x * axis_norm.x;
128 let r1c0 = t.y * axis_norm.x - s * axis_norm.z;
129 let r2c0 = t.z * axis_norm.x + s * axis_norm.y;
130
131 let r0c1 = t.x * axis_norm.y + s * axis_norm.z;
132 let r1c1 = c + t.y * axis_norm.y;
133 let r2c1 = t.z * axis_norm.y - s * axis_norm.x;
134
135 let r0c2 = t.x * axis_norm.z - s * axis_norm.y;
136 let r1c2 = t.y * axis_norm.z + s * axis_norm.x;
137 let r2c2 = c + t.z * axis_norm.z;
138
139 Self {
140 x_col: Vec4::new(r0c0, r1c0, r2c0, 0.0),
141 y_col: Vec4::new(r0c1, r1c1, r2c1, 0.0),
142 z_col: Vec4::new(r0c2, r1c2, r2c2, 0.0),
143 w_col: Vec4::new(0.0, 0.0, 0.0, 1.0),
144 _unit: PhantomData,
145 _space: PhantomData,
146 }
147 }
148
149 #[inline]
151 pub fn from_axis_angle_deg(axis: Vec3, angle: crate::angle::Degrees) -> Self {
152 Self::from_axis_angle_radians(axis, angle.to_radians())
153 }
154
155 #[inline]
157 #[cfg(feature = "unit_vec")]
158 pub fn from_unit_axis_angle_radians(axis: UnitVec3<Unit, Space>, angle: crate::angle::Radians) -> Self {
159 Self::from_quat(crate::quat::Quat::from_unit_axis_angle_radians(axis, angle))
161 }
162
163 #[inline]
165 #[cfg(feature = "unit_vec")]
166 pub fn from_unit_axis_angle_deg(axis: UnitVec3<Unit, Space>, angle: crate::angle::Degrees) -> Self {
167 Self::from_unit_axis_angle_radians(axis, angle.to_radians())
168 }
169
170 #[inline]
175 pub fn from_rotation_x_radians(angle: crate::angle::Radians) -> Self {
176 Self::from_quat(crate::quat::Quat::from_axis_angle_radians(Vec3::new(1.0, 0.0, 0.0), angle))
177 }
178
179 #[inline]
181 pub fn from_rotation_x_deg(angle: crate::angle::Degrees) -> Self {
182 Self::from_rotation_x_radians(angle.to_radians())
183 }
184
185 #[inline]
190 pub fn from_rotation_y_radians(angle: crate::angle::Radians) -> Self {
191 Self::from_quat(crate::quat::Quat::from_axis_angle_radians(Vec3::new(0.0, 1.0, 0.0), angle))
192 }
193
194 #[inline]
196 pub fn from_rotation_y_deg(angle: crate::angle::Degrees) -> Self {
197 Self::from_rotation_y_radians(angle.to_radians())
198 }
199
200 #[inline]
205 pub fn from_rotation_z_radians(angle: crate::angle::Radians) -> Self {
206 Self::from_quat(crate::quat::Quat::from_axis_angle_radians(Vec3::new(0.0, 0.0, 1.0), angle))
207 }
208
209 #[inline]
211 pub fn from_rotation_z_deg(angle: crate::angle::Degrees) -> Self {
212 Self::from_rotation_z_radians(angle.to_radians())
213 }
214
215 #[inline]
217 pub const fn from_scale(v: Vec3) -> Self {
218 Self {
219 x_col: Vec4::new(v.x, 0.0, 0.0, 0.0),
220 y_col: Vec4::new(0.0, v.y, 0.0, 0.0),
221 z_col: Vec4::new(0.0, 0.0, v.z, 0.0),
222 w_col: Vec4::new(0.0, 0.0, 0.0, 1.0),
223 _unit: PhantomData,
224 _space: PhantomData,
225 }
226 }
227
228 #[inline]
230 pub const fn transpose(&self) -> Self {
231 Self {
232 x_col: Vec4::new(self.x_col.x, self.y_col.x, self.z_col.x, self.w_col.x),
233 y_col: Vec4::new(self.x_col.y, self.y_col.y, self.z_col.y, self.w_col.y),
234 z_col: Vec4::new(self.x_col.z, self.y_col.z, self.z_col.z, self.w_col.z),
235 w_col: Vec4::new(self.x_col.w, self.y_col.w, self.z_col.w, self.w_col.w),
236 _unit: PhantomData,
237 _space: PhantomData,
238 }
239 }
240
241 #[inline]
245 pub fn inverse(&self) -> Option<Self> {
246 let m = self; let sf00 = m.z_col.z * m.w_col.w - m.w_col.z * m.z_col.w;
249 let sf01 = m.z_col.y * m.w_col.w - m.w_col.y * m.z_col.w;
250 let sf02 = m.z_col.y * m.w_col.z - m.w_col.y * m.z_col.z;
251 let sf03 = m.z_col.x * m.w_col.w - m.w_col.x * m.z_col.w;
252 let sf04 = m.z_col.x * m.w_col.z - m.w_col.x * m.z_col.z;
253 let sf05 = m.z_col.x * m.w_col.y - m.w_col.x * m.z_col.y; let sf06 = m.y_col.z * m.w_col.w - m.w_col.z * m.y_col.w;
256 let sf07 = m.y_col.y * m.w_col.w - m.w_col.y * m.y_col.w;
257 let sf08 = m.y_col.y * m.w_col.z - m.w_col.y * m.y_col.z;
258 let sf09 = m.y_col.x * m.w_col.w - m.w_col.x * m.y_col.w;
259 let sf10 = m.y_col.x * m.w_col.z - m.w_col.x * m.y_col.z;
260 let sf11 = m.y_col.y * m.w_col.w - m.w_col.y * m.y_col.w; let sf12 = m.y_col.x * m.w_col.y - m.w_col.x * m.y_col.y;
262
263 let sf13 = m.y_col.z * m.z_col.w - m.z_col.z * m.y_col.w;
264 let sf14 = m.y_col.y * m.z_col.w - m.z_col.y * m.y_col.w;
265 let sf15 = m.y_col.y * m.z_col.z - m.z_col.y * m.y_col.z;
266 let sf16 = m.y_col.x * m.z_col.w - m.z_col.x * m.y_col.w;
267 let sf17 = m.y_col.x * m.z_col.z - m.z_col.x * m.y_col.z;
268 let sf18 = m.y_col.x * m.z_col.y - m.z_col.x * m.y_col.y;
269
270 let mut o = Self::ZERO; o.x_col.x = m.y_col.y * sf00 - m.y_col.z * sf01 + m.y_col.w * sf02;
273 o.y_col.x = -m.y_col.x * sf00 + m.y_col.z * sf03 - m.y_col.w * sf04;
274 o.z_col.x = m.y_col.x * sf01 - m.y_col.y * sf03 + m.y_col.w * sf05;
275 o.w_col.x = -m.y_col.x * sf02 + m.y_col.y * sf04 - m.y_col.z * sf05;
276
277 o.x_col.y = -m.x_col.y * sf00 + m.x_col.z * sf01 - m.x_col.w * sf02;
278 o.y_col.y = m.x_col.x * sf00 - m.x_col.z * sf03 + m.x_col.w * sf04;
279 o.z_col.y = -m.x_col.x * sf01 + m.x_col.y * sf03 - m.x_col.w * sf05;
280 o.w_col.y = m.x_col.x * sf02 - m.x_col.y * sf04 + m.x_col.z * sf05;
281
282 o.x_col.z = m.x_col.y * sf06 - m.x_col.z * sf07 + m.x_col.w * sf08;
283 o.y_col.z = -m.x_col.x * sf06 + m.x_col.z * sf09 - m.x_col.w * sf10;
284 o.z_col.z = m.x_col.x * sf11 - m.x_col.y * sf09 + m.x_col.w * sf12;
285 o.w_col.z = -m.x_col.x * sf08 + m.x_col.y * sf10 - m.x_col.z * sf12;
286
287 o.x_col.w = -m.x_col.y * sf13 + m.x_col.z * sf14 - m.x_col.w * sf15;
288 o.y_col.w = m.x_col.x * sf13 - m.x_col.z * sf16 + m.x_col.w * sf17;
289 o.z_col.w = -m.x_col.x * sf14 + m.x_col.y * sf16 - m.x_col.w * sf18;
290 o.w_col.w = m.x_col.x * sf15 - m.x_col.y * sf17 + m.x_col.z * sf18;
291
292 let det_check = m.x_col.x * o.x_col.x
293 + m.x_col.y * o.y_col.x
294 + m.x_col.z * o.z_col.x
295 + m.x_col.w * o.w_col.x;
296
297 if det_check.abs() < 1e-7 {
298 return None;
300 }
301
302 let ood = 1.0 / det_check;
303
304 o.x_col = o.x_col * ood;
305 o.y_col = o.y_col * ood;
306 o.z_col = o.z_col * ood;
307 o.w_col = o.w_col * ood;
308
309 Some(o)
310 }
311
312 #[inline]
314 pub fn try_inverse(&self) -> Option<Self> {
315 self.inverse()
316 }
317
318 #[inline]
320 pub fn determinant(&self) -> f32 {
321 let m = self;
322 let m00 = m.x_col.x;
323 let m01 = m.y_col.x;
324 let m02 = m.z_col.x;
325 let m03 = m.w_col.x;
326 let m10 = m.x_col.y;
327 let m11 = m.y_col.y;
328 let m12 = m.z_col.y;
329 let m13 = m.w_col.y;
330 let m20 = m.x_col.z;
331 let m21 = m.y_col.z;
332 let m22 = m.z_col.z;
333 let m23 = m.w_col.z;
334 let m30 = m.x_col.w;
335 let m31 = m.y_col.w;
336 let m32 = m.z_col.w;
337 let m33 = m.w_col.w;
338
339 #[inline]
340 fn det3(
341 a00: f32, a01: f32, a02: f32,
342 a10: f32, a11: f32, a12: f32,
343 a20: f32, a21: f32, a22: f32,
344 ) -> f32 {
345 a00 * (a11 * a22 - a12 * a21)
346 - a01 * (a10 * a22 - a12 * a20)
347 + a02 * (a10 * a21 - a11 * a20)
348 }
349
350 m00 * det3(m11, m12, m13, m21, m22, m23, m31, m32, m33)
351 - m01 * det3(m10, m12, m13, m20, m22, m23, m30, m32, m33)
352 + m02 * det3(m10, m11, m13, m20, m21, m23, m30, m31, m33)
353 - m03 * det3(m10, m11, m12, m20, m21, m22, m30, m31, m32)
354 }
355
356 #[inline]
359 pub fn orthographic_lh_zo(
360 left: f32,
361 right: f32,
362 bottom: f32,
363 top: f32,
364 near: f32,
365 far: f32,
366 ) -> Self {
367 let r_minus_l = right - left;
368 let t_minus_b = top - bottom;
369 let f_minus_n = far - near;
370
371 let mut m = Self::ZERO;
376
377 m.x_col.x = 2.0 / r_minus_l;
378 m.y_col.y = 2.0 / t_minus_b;
379 m.z_col.z = 1.0 / f_minus_n; m.w_col.w = 1.0;
381
382 m.w_col.x = -(right + left) / r_minus_l;
383 m.w_col.y = -(top + bottom) / t_minus_b;
384 m.w_col.z = -near / f_minus_n; m
387 }
388
389 #[inline]
392 pub fn perspective_lh_zo(
393 fovy_radians: f32,
394 aspect_ratio: f32,
395 near_plane: f32,
396 far_plane: f32,
397 ) -> Self {
398 let tan_half_fovy = math::tan(0.5 * fovy_radians);
399
400 let mut m = Self::ZERO;
404
405 m.x_col.x = 1.0 / (aspect_ratio * tan_half_fovy);
406 m.y_col.y = 1.0 / tan_half_fovy;
407 m.z_col.z = far_plane / (far_plane - near_plane);
408 m.z_col.w = 1.0; m.w_col.z = -near_plane * far_plane / (far_plane - near_plane);
410 m
413 }
414
415 #[inline]
418 pub fn look_at_lh(eye: Vec3, target: Vec3, world_up: Vec3) -> Self {
419 let f = (target - eye).normalize(); let s = f.cross(world_up).normalize(); let u = s.cross(f); Self {
440 x_col: Vec4::new(s.x, u.x, -f.x, 0.0),
441 y_col: Vec4::new(s.y, u.y, -f.y, 0.0),
442 z_col: Vec4::new(s.z, u.z, -f.z, 0.0),
443 w_col: Vec4::new(-s.dot(eye), -u.dot(eye), f.dot(eye), 1.0),
444 _unit: PhantomData,
445 _space: PhantomData,
446 }
447 }
448
449 pub const fn col(&self, i: usize) -> Option<Vec4<Unit, Space>> {
451 match i {
452 0 => Some(self.x_col),
453 1 => Some(self.y_col),
454 2 => Some(self.z_col),
455 3 => Some(self.w_col),
456 _ => None,
457 }
458 }
459
460 pub fn set_col(&mut self, i: usize, v: Vec4<Unit, Space>) {
462 match i {
463 0 => self.x_col = v,
464 1 => self.y_col = v,
465 2 => self.z_col = v,
466 3 => self.w_col = v,
467 _ => {}
468 }
469 }
470
471 pub const fn row(&self, i: usize) -> Option<Vec4<Unit, Space>> {
473 match i {
474 0 => Some(Vec4::new(
475 self.x_col.x,
476 self.y_col.x,
477 self.z_col.x,
478 self.w_col.x,
479 )),
480 1 => Some(Vec4::new(
481 self.x_col.y,
482 self.y_col.y,
483 self.z_col.y,
484 self.w_col.y,
485 )),
486 2 => Some(Vec4::new(
487 self.x_col.z,
488 self.y_col.z,
489 self.z_col.z,
490 self.w_col.z,
491 )),
492 3 => Some(Vec4::new(
493 self.x_col.w,
494 self.y_col.w,
495 self.z_col.w,
496 self.w_col.w,
497 )),
498 _ => None,
499 }
500 }
501
502 pub fn set_row(&mut self, i: usize, v: Vec4<Unit, Space>) {
504 match i {
505 0 => {
506 self.x_col.x = v.x;
507 self.y_col.x = v.y;
508 self.z_col.x = v.z;
509 self.w_col.x = v.w;
510 }
511 1 => {
512 self.x_col.y = v.x;
513 self.y_col.y = v.y;
514 self.z_col.y = v.z;
515 self.w_col.y = v.w;
516 }
517 2 => {
518 self.x_col.z = v.x;
519 self.y_col.z = v.y;
520 self.z_col.z = v.z;
521 self.w_col.z = v.w;
522 }
523 3 => {
524 self.x_col.w = v.x;
525 self.y_col.w = v.y;
526 self.z_col.w = v.z;
527 self.w_col.w = v.w;
528 }
529 _ => {}
530 }
531 }
532
533 pub fn is_orthonormal(&self) -> bool {
535 let c0 = self.x_col.xyz();
536 let c1 = self.y_col.xyz();
537 let c2 = self.z_col.xyz();
538 (c0.length() - 1.0).abs() < 1e-5
539 && (c1.length() - 1.0).abs() < 1e-5
540 && (c2.length() - 1.0).abs() < 1e-5
541 && (c0.dot(c1)).abs() < 1e-5
542 && (c0.dot(c2)).abs() < 1e-5
543 && (c1.dot(c2)).abs() < 1e-5
544 }
545
546 pub const fn from_shear(shxy: f32, shxz: f32, shyx: f32, shyz: f32, shzx: f32, shzy: f32) -> Self {
548 Self {
554 x_col: Vec4::new(1.0, shyx, shzx, 0.0),
555 y_col: Vec4::new(shxy, 1.0, shzy, 0.0),
556 z_col: Vec4::new(shxz, shyz, 1.0, 0.0),
557 w_col: Vec4::new(0.0, 0.0, 0.0, 1.0),
558 _unit: PhantomData,
559 _space: PhantomData,
560 }
561 }
562
563 pub fn from_quat(q: crate::quat::Quat<Unit, Space>) -> Self {
565 let (x, y, z, w) = (q.x, q.y, q.z, q.w);
566 let x2 = x + x;
567 let y2 = y + y;
568 let z2 = z + z;
569 let xx = x * x2;
570 let yy = y * y2;
571 let zz = z * z2;
572 let xy = x * y2;
573 let xz = x * z2;
574 let yz = y * z2;
575 let wx = w * x2;
576 let wy = w * y2;
577 let wz = w * z2;
578 Self {
579 x_col: Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0),
580 y_col: Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0),
581 z_col: Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0),
582 w_col: Vec4::new(0.0, 0.0, 0.0, 1.0),
583 _unit: PhantomData,
584 _space: PhantomData,
585 }
586 }
587
588 pub fn to_quat(&self) -> crate::quat::Quat {
590 let m00 = self.x_col.x;
592 let m01 = self.x_col.y;
593 let m02 = self.x_col.z;
594 let m10 = self.y_col.x;
595 let m11 = self.y_col.y;
596 let m12 = self.y_col.z;
597 let m20 = self.z_col.x;
598 let m21 = self.z_col.y;
599 let m22 = self.z_col.z;
600 let four_x_squared_minus_1 = m00 - m11 - m22;
601 let four_y_squared_minus_1 = m11 - m00 - m22;
602 let four_z_squared_minus_1 = m22 - m00 - m11;
603 let four_w_squared_minus_1 = m00 + m11 + m22;
604 let mut biggest_index = 0;
605 let mut four_biggest_squared_minus_1 = four_w_squared_minus_1;
606 if four_x_squared_minus_1 > four_biggest_squared_minus_1 {
607 four_biggest_squared_minus_1 = four_x_squared_minus_1;
608 biggest_index = 1;
609 }
610 if four_y_squared_minus_1 > four_biggest_squared_minus_1 {
611 four_biggest_squared_minus_1 = four_y_squared_minus_1;
612 biggest_index = 2;
613 }
614 if four_z_squared_minus_1 > four_biggest_squared_minus_1 {
615 four_biggest_squared_minus_1 = four_z_squared_minus_1;
616 biggest_index = 3;
617 }
618 let biggest_value = math::sqrt(four_biggest_squared_minus_1 + 1.0) * 0.5;
619 let mult = 0.25 / biggest_value;
620 let mut q = crate::quat::Quat::ZERO;
621 match biggest_index {
622 0 => {
623 q.w = biggest_value;
624 q.x = (m12 - m21) * mult;
625 q.y = (m20 - m02) * mult;
626 q.z = (m01 - m10) * mult;
627 }
628 1 => {
629 q.w = (m12 - m21) * mult;
630 q.x = biggest_value;
631 q.y = (m01 + m10) * mult;
632 q.z = (m20 + m02) * mult;
633 }
634 2 => {
635 q.w = (m20 - m02) * mult;
636 q.x = (m01 + m10) * mult;
637 q.y = biggest_value;
638 q.z = (m12 + m21) * mult;
639 }
640 3 => {
641 q.w = (m01 - m10) * mult;
642 q.x = (m20 + m02) * mult;
643 q.y = (m12 + m21) * mult;
644 q.z = biggest_value;
645 }
646 _ => unreachable!(),
647 }
648 q
649 }
650
651 pub fn transform_point(&self, p: Vec3) -> Vec3 {
653 let v = Vec4::new(p.x, p.y, p.z, 1.0);
654 let r = *self * v;
655 Vec3::new(r.x, r.y, r.z)
656 }
657
658 pub fn transform_vector(&self, v: Vec3) -> Vec3 {
660 let v4 = Vec4::new(v.x, v.y, v.z, 0.0);
661 let r = *self * v4;
662 Vec3::new(r.x, r.y, r.z)
663 }
664
665 pub fn decompose(&self) -> (Vec3, crate::quat::Quat, Vec3) {
667 let translation = Vec3::new(self.w_col.x, self.w_col.y, self.w_col.z);
669 let sx = self.x_col.xyz().length();
671 let sy = self.y_col.xyz().length();
672 let sz = self.z_col.xyz().length();
673 let scale = Vec3::new(sx, sy, sz);
674 let mut rot = *self;
676 rot.x_col = rot.x_col / sx;
677 rot.y_col = rot.y_col / sy;
678 rot.z_col = rot.z_col / sz;
679 let rotation = rot.to_quat();
680 (translation, rotation, scale)
681 }
682
683 pub fn compose(translation: Vec3, rotation: crate::quat::Quat<Unit, Space>, scale: Vec3) -> Self {
685 let rot = Self::from_quat(rotation);
686 let mut m = rot;
687 m.x_col = m.x_col * scale.x;
688 m.y_col = m.y_col * scale.y;
689 m.z_col = m.z_col * scale.z;
690 m.w_col = Vec4::new(translation.x, translation.y, translation.z, 1.0);
691 m
692 }
693
694 #[inline]
698 pub fn from_trs(translation: Vec3, rotation: crate::quat::Quat<Unit, Space>, scale: Vec3) -> Self {
699 Self::compose(translation, rotation, scale)
700 }
701}
702
703impl<Unit: Copy, Space: Copy> Add for Mat4<Unit, Space> {
704 type Output = Self;
705 #[inline]
706 fn add(self, rhs: Self) -> Self::Output {
707 Self {
708 x_col: self.x_col + rhs.x_col,
709 y_col: self.y_col + rhs.y_col,
710 z_col: self.z_col + rhs.z_col,
711 w_col: self.w_col + rhs.w_col,
712 _unit: PhantomData,
713 _space: PhantomData,
714 }
715 }
716}
717
718impl<Unit: Copy, Space: Copy> Sub for Mat4<Unit, Space> {
719 type Output = Self;
720 #[inline]
721 fn sub(self, rhs: Self) -> Self::Output {
722 Self {
723 x_col: self.x_col - rhs.x_col,
724 y_col: self.y_col - rhs.y_col,
725 z_col: self.z_col - rhs.z_col,
726 w_col: self.w_col - rhs.w_col,
727 _unit: PhantomData,
728 _space: PhantomData,
729 }
730 }
731}
732
733impl<Unit: Copy, Space: Copy> Mul<Mat4<Unit, Space>> for Mat4<Unit, Space> {
734 type Output = Self;
735 #[inline]
736 fn mul(self, rhs: Mat4<Unit, Space>) -> Self::Output {
737 let x_col_x = self.x_col.x * rhs.x_col.x
747 + self.y_col.x * rhs.x_col.y
748 + self.z_col.x * rhs.x_col.z
749 + self.w_col.x * rhs.x_col.w; let x_col_y = self.x_col.y * rhs.x_col.x
751 + self.y_col.y * rhs.x_col.y
752 + self.z_col.y * rhs.x_col.z
753 + self.w_col.y * rhs.x_col.w; let x_col_z = self.x_col.z * rhs.x_col.x
755 + self.y_col.z * rhs.x_col.y
756 + self.z_col.z * rhs.x_col.z
757 + self.w_col.z * rhs.x_col.w; let x_col_w = self.x_col.w * rhs.x_col.x
759 + self.y_col.w * rhs.x_col.y
760 + self.z_col.w * rhs.x_col.z
761 + self.w_col.w * rhs.x_col.w; let y_col_x = self.x_col.x * rhs.y_col.x
765 + self.y_col.x * rhs.y_col.y
766 + self.z_col.x * rhs.y_col.z
767 + self.w_col.x * rhs.y_col.w; let y_col_y = self.x_col.y * rhs.y_col.x
769 + self.y_col.y * rhs.y_col.y
770 + self.z_col.y * rhs.y_col.z
771 + self.w_col.y * rhs.y_col.w; let y_col_z = self.x_col.z * rhs.y_col.x
773 + self.y_col.z * rhs.y_col.y
774 + self.z_col.z * rhs.y_col.z
775 + self.w_col.z * rhs.y_col.w; let y_col_w = self.x_col.w * rhs.y_col.x
777 + self.y_col.w * rhs.y_col.y
778 + self.z_col.w * rhs.y_col.z
779 + self.w_col.w * rhs.y_col.w; let z_col_x = self.x_col.x * rhs.z_col.x
783 + self.y_col.x * rhs.z_col.y
784 + self.z_col.x * rhs.z_col.z
785 + self.w_col.x * rhs.z_col.w; let z_col_y = self.x_col.y * rhs.z_col.x
787 + self.y_col.y * rhs.z_col.y
788 + self.z_col.y * rhs.z_col.z
789 + self.w_col.y * rhs.z_col.w; let z_col_z = self.x_col.z * rhs.z_col.x
791 + self.y_col.z * rhs.z_col.y
792 + self.z_col.z * rhs.z_col.z
793 + self.w_col.z * rhs.z_col.w; let z_col_w = self.x_col.w * rhs.z_col.x
795 + self.y_col.w * rhs.z_col.y
796 + self.z_col.w * rhs.z_col.z
797 + self.w_col.w * rhs.z_col.w; let w_col_x = self.x_col.x * rhs.w_col.x
801 + self.y_col.x * rhs.w_col.y
802 + self.z_col.x * rhs.w_col.z
803 + self.w_col.x * rhs.w_col.w; let w_col_y = self.x_col.y * rhs.w_col.x
805 + self.y_col.y * rhs.w_col.y
806 + self.z_col.y * rhs.w_col.z
807 + self.w_col.y * rhs.w_col.w; let w_col_z = self.x_col.z * rhs.w_col.x
809 + self.y_col.z * rhs.w_col.y
810 + self.z_col.z * rhs.w_col.z
811 + self.w_col.z * rhs.w_col.w; let w_col_w = self.x_col.w * rhs.w_col.x
813 + self.y_col.w * rhs.w_col.y
814 + self.z_col.w * rhs.w_col.z
815 + self.w_col.w * rhs.w_col.w; Self {
818 x_col: Vec4::new(x_col_x, x_col_y, x_col_z, x_col_w),
819 y_col: Vec4::new(y_col_x, y_col_y, y_col_z, y_col_w),
820 z_col: Vec4::new(z_col_x, z_col_y, z_col_z, z_col_w),
821 w_col: Vec4::new(w_col_x, w_col_y, w_col_z, w_col_w),
822 _unit: PhantomData,
823 _space: PhantomData,
824 }
825 }
826}
827
828impl<Unit: Copy, Space: Copy> Mul<Vec4<Unit, Space>> for Mat4<Unit, Space> {
829 type Output = Vec4<Unit, Space>;
830 #[inline]
831 fn mul(self, rhs: Vec4<Unit, Space>) -> Self::Output {
832 let x = self.x_col.x * rhs.x
841 + self.y_col.x * rhs.y
842 + self.z_col.x * rhs.z
843 + self.w_col.x * rhs.w;
844 let y = self.x_col.y * rhs.x
845 + self.y_col.y * rhs.y
846 + self.z_col.y * rhs.z
847 + self.w_col.y * rhs.w;
848 let z = self.x_col.z * rhs.x
849 + self.y_col.z * rhs.y
850 + self.z_col.z * rhs.z
851 + self.w_col.z * rhs.w;
852 let w = self.x_col.w * rhs.x
853 + self.y_col.w * rhs.y
854 + self.z_col.w * rhs.z
855 + self.w_col.w * rhs.w;
856 Vec4::new(x, y, z, w)
857 }
858}
859
860impl<Unit: Copy, Space: Copy> Mul<f32> for Mat4<Unit, Space> {
861 type Output = Self;
862 #[inline]
863 fn mul(self, rhs: f32) -> Self::Output {
864 Self {
865 x_col: self.x_col * rhs,
866 y_col: self.y_col * rhs,
867 z_col: self.z_col * rhs,
868 w_col: self.w_col * rhs,
869 _unit: PhantomData,
870 _space: PhantomData,
871 }
872 }
873}
874
875impl<Unit: Copy, Space: Copy> Mul<Mat4<Unit, Space>> for f32 {
876 type Output = Mat4<Unit, Space>;
877 #[inline]
878 fn mul(self, rhs: Mat4<Unit, Space>) -> Self::Output {
879 rhs * self }
881}
882
883