1use num_traits::{
2 NumAssign, Float
3};
4
5use std::slice::{
6 Iter,
7 IterMut
8};
9
10use std::ops::{
11 Neg, Add, Sub, Mul, Div,
12 Index, IndexMut
13};
14
15use crate::vec4::Vec4;
16use crate::vec3::Vec3;
17
18use std::fmt;
19
20#[derive(Debug, Default, Copy, Clone, PartialEq)]
21pub struct Mat4<T> (
22 pub Vec4<T>,
23 pub Vec4<T>,
24 pub Vec4<T>,
25 pub Vec4<T>
26);
27
28impl<T> Mat4<T>
29where
30 T: NumAssign + Copy,
31{
32 #[inline]
52 pub fn new(col0: &Vec4<T>, col1: &Vec4<T>, col2: &Vec4<T>, col3: &Vec4<T>) -> Self {
53 Self (col0.clone(), col1.clone(), col2.clone(), col3.clone())
54 }
55
56 #[inline]
66 pub fn zero() -> Self {
67 Self (
68 Vec4::zero(),
69 Vec4::zero(),
70 Vec4::zero(),
71 Vec4::zero(),
72 )
73 }
74
75 #[inline]
85 pub fn identity() -> Self {
86 Self (
87 Vec4::new(T::one(), T::zero(), T::zero(), T::zero()),
88 Vec4::new(T::zero(), T::one(), T::zero(), T::zero()),
89 Vec4::new(T::zero(), T::zero(), T::one(), T::zero()),
90 Vec4::new(T::zero(), T::zero(), T::zero(), T::one()),
91 )
92 }
93
94 #[inline]
108 pub fn transpose(&self) -> Self {
109 Self (
110 Vec4::new(self.0.x, self.1.x, self.2.x, self.3.x),
111 Vec4::new(self.0.y, self.1.y, self.2.y, self.3.y),
112 Vec4::new(self.0.z, self.1.z, self.2.z, self.3.z),
113 Vec4::new(self.0.w, self.1.w, self.2.w, self.3.w),
114 )
115 }
116
117 pub fn determinant(&self) -> T {
131 let a00 = self.0.x;
132 let a01 = self.0.y;
133 let a02 = self.0.z;
134 let a03 = self.0.w;
135 let a10 = self.1.x;
136 let a11 = self.1.y;
137 let a12 = self.1.z;
138 let a13 = self.1.w;
139 let a20 = self.2.x;
140 let a21 = self.2.y;
141 let a22 = self.2.z;
142 let a23 = self.2.w;
143 let a30 = self.3.x;
144 let a31 = self.3.y;
145 let a32 = self.3.z;
146 let a33 = self.3.w;
147
148 let term1 = a30 * a21 * a12 * a03;
149 let term2 = a20 * a31 * a12 * a03;
150 let term3 = a30 * a11 * a22 * a03;
151 let term4 = a10 * a31 * a22 * a03;
152 let term5 = a20 * a11 * a32 * a03;
153 let term6 = a10 * a21 * a32 * a03;
154 let term7 = a30 * a21 * a02 * a13;
155 let term8 = a20 * a31 * a02 * a13;
156 let term9 = a30 * a01 * a22 * a13;
157 let term10 = a00 * a31 * a22 * a13;
158 let term11 = a20 * a01 * a32 * a13;
159 let term12 = a00 * a21 * a32 * a13;
160 let term13 = a30 * a11 * a02 * a23;
161 let term14 = a10 * a31 * a02 * a23;
162 let term15 = a30 * a01 * a12 * a23;
163 let term16 = a00 * a31 * a12 * a23;
164 let term17 = a10 * a01 * a32 * a23;
165 let term18 = a00 * a11 * a32 * a23;
166 let term19 = a20 * a11 * a02 * a33;
167 let term20 = a10 * a21 * a02 * a33;
168 let term21 = a20 * a01 * a12 * a33;
169 let term22 = a00 * a21 * a12 * a33;
170 let term23 = a10 * a01 * a22 * a33;
171 let term24 = a00 * a11 * a22 * a33;
172
173 let determinant = term1 - term2 - term3 + term4 +
174 term5 - term6 - term7 + term8 +
175 term9 - term10 - term11 + term12 +
176 term13 - term14 - term15 + term16 +
177 term17 - term18 - term19 + term20 +
178 term21 - term22 - term23 + term24;
179
180 determinant
181 }
182
183 pub fn trace(&self) -> T {
197 self.0.x + self.1.y + self.2.z + self.3.w
198 }
199
200 pub fn mul(&self, other: &Self) -> Self {
216 let col0 = Vec4::new(
217 self.0.dot(&Vec4::new(other.0.x, other.1.x, other.2.x, other.3.x)),
218 self.1.dot(&Vec4::new(other.0.x, other.1.x, other.2.x, other.3.x)),
219 self.2.dot(&Vec4::new(other.0.x, other.1.x, other.2.x, other.3.x)),
220 self.3.dot(&Vec4::new(other.0.x, other.1.x, other.2.x, other.3.x)),
221 );
222 let col1 = Vec4::new(
223 self.0.dot(&Vec4::new(other.0.y, other.1.y, other.2.y, other.3.y)),
224 self.1.dot(&Vec4::new(other.0.y, other.1.y, other.2.y, other.3.y)),
225 self.2.dot(&Vec4::new(other.0.y, other.1.y, other.2.y, other.3.y)),
226 self.3.dot(&Vec4::new(other.0.y, other.1.y, other.2.y, other.3.y)),
227 );
228 let col2 = Vec4::new(
229 self.0.dot(&Vec4::new(other.0.z, other.1.z, other.2.z, other.3.z)),
230 self.1.dot(&Vec4::new(other.0.z, other.1.z, other.2.z, other.3.z)),
231 self.2.dot(&Vec4::new(other.0.z, other.1.z, other.2.z, other.3.z)),
232 self.3.dot(&Vec4::new(other.0.z, other.1.z, other.2.z, other.3.z)),
233 );
234 let col3 = Vec4::new(
235 self.0.dot(&Vec4::new(other.0.w, other.1.w, other.2.w, other.3.w)),
236 self.1.dot(&Vec4::new(other.0.w, other.1.w, other.2.w, other.3.w)),
237 self.2.dot(&Vec4::new(other.0.w, other.1.w, other.2.w, other.3.w)),
238 self.3.dot(&Vec4::new(other.0.w, other.1.w, other.2.w, other.3.w)),
239 );
240 Self::new(&col0, &col1, &col2, &col3)
241 }
242
243 #[inline]
257 pub fn translate(&mut self, translate: &Vec3<T>) {
258 self.3.x += translate.x;
259 self.3.y += translate.y;
260 self.3.z += translate.z;
261 }
262
263 #[inline]
277 pub fn scale(&mut self, scale: &Vec3<T>) {
278 self.0.x *= scale.x;
279 self.1.y *= scale.y;
280 self.2.z *= scale.z;
281 }
282}
283
284impl<T> Mat4<T>
285where
286 T: NumAssign + Float,
287{
288 pub fn invert(&self) -> Option<Self> {
301 let a00 = self.0.x;
302 let a01 = self.0.y;
303 let a02 = self.0.z;
304 let a03 = self.0.w;
305 let a10 = self.1.x;
306 let a11 = self.1.y;
307 let a12 = self.1.z;
308 let a13 = self.1.w;
309 let a20 = self.2.x;
310 let a21 = self.2.y;
311 let a22 = self.2.z;
312 let a23 = self.2.w;
313 let a30 = self.3.x;
314 let a31 = self.3.y;
315 let a32 = self.3.z;
316 let a33 = self.3.w;
317
318 let b00 = a00 * a11 - a01 * a10;
319 let b01 = a00 * a12 - a02 * a10;
320 let b02 = a00 * a13 - a03 * a10;
321 let b03 = a01 * a12 - a02 * a11;
322 let b04 = a01 * a13 - a03 * a11;
323 let b05 = a02 * a13 - a03 * a12;
324 let b06 = a20 * a31 - a21 * a30;
325 let b07 = a20 * a32 - a22 * a30;
326 let b08 = a20 * a33 - a23 * a30;
327 let b09 = a21 * a32 - a22 * a31;
328 let b10 = a21 * a33 - a23 * a31;
329 let b11 = a22 * a33 - a23 * a32;
330
331 let det = b00 * b11 - b01 * b10 + b02 * b09
332 - b03 * b08 - b04 * b07 + b05 * b06;
333
334 if det.is_zero() {
335 return None;
336 }
337
338 let inv_det = T::one() / det;
339
340 Some(Self(
341 Vec4::new(
342 (a11 * b11 - a12 * b10 + a13 * b09) * inv_det,
343 (-a01 * b11 + a02 * b10 - a03 * b09) * inv_det,
344 (a31 * b05 - a32 * b04 + a33 * b03) * inv_det,
345 (-a21 * b05 + a22 * b04 - a23 * b03) * inv_det,
346 ),
347 Vec4::new(
348 (-a10 * b11 + a12 * b08 - a13 * b07) * inv_det,
349 (a00 * b11 - a02 * b08 + a03 * b07) * inv_det,
350 (-a30 * b05 + a32 * b02 - a33 * b01) * inv_det,
351 (a20 * b05 - a22 * b02 + a23 * b01) * inv_det,
352 ),
353 Vec4::new(
354 (a10 * b10 - a11 * b08 + a13 * b06) * inv_det,
355 (-a00 * b10 + a01 * b08 - a03 * b06) * inv_det,
356 (a30 * b04 - a31 * b02 + a33 * b00) * inv_det,
357 (-a20 * b04 + a21 * b02 - a23 * b00) * inv_det,
358 ),
359 Vec4::new(
360 (-a10 * b09 + a11 * b07 - a12 * b06) * inv_det,
361 (a00 * b09 - a01 * b07 + a02 * b06) * inv_det,
362 (-a30 * b03 + a31 * b01 - a32 * b00) * inv_det,
363 (a20 * b03 - a21 * b01 + a22 * b00) * inv_det,
364 ),
365 ))
366 }
367
368 pub fn rotate(&mut self, axis: Vec3<T>, angle: T) {
383 let len_sq = axis.length_squared();
384 let inv_len = if len_sq.is_zero() {
385 T::zero()
386 } else {
387 len_sq.sqrt().recip()
388 };
389
390 let axis = axis * inv_len;
391 let s = angle.sin();
392 let c = angle.cos();
393 let t = T::one() - c;
394
395 let m00 = axis.x * axis.x * t + c;
396 let m01 = axis.y * axis.x * t + axis.z * s;
397 let m02 = axis.z * axis.x * t - axis.y * s;
398
399 let m10 = axis.x * axis.y * t - axis.z * s;
400 let m11 = axis.y * axis.y * t + c;
401 let m12 = axis.z * axis.y * t + axis.x * s;
402
403 let m20 = axis.x * axis.z * t + axis.y * s;
404 let m21 = axis.y * axis.z * t - axis.x * s;
405 let m22 = axis.z * axis.z * t + c;
406
407 for i in 0..3 {
408 let x = self[i][0];
409 let y = self[i][1];
410 let z = self[i][2];
411 self[i][0] = x * m00 + y * m10 + z * m20;
412 self[i][1] = x * m01 + y * m11 + z * m21;
413 self[i][2] = x * m02 + y * m12 + z * m22;
414 }
415 }
416
417 pub fn rotate_x(&mut self, angle: T) {
430 let c = angle.cos();
431 let s = angle.sin();
432 for i in 0..3 {
433 let y = self[i][1];
434 let z = self[i][2];
435 self[i][1] = y * c - z * s;
436 self[i][2] = y * s + z * c;
437 }
438 }
439
440 pub fn rotate_y(&mut self, angle: T) {
453 let c = angle.cos();
454 let s = angle.sin();
455 for i in 0..3 {
456 let x = self[i][0];
457 let z = self[i][2];
458 self[i][0] = x * c + z * s;
459 self[i][2] = -x * s + z * c;
460 }
461 }
462
463 pub fn rotate_z(&mut self, angle: T) {
476 let c = angle.cos();
477 let s = angle.sin();
478 for i in 0..3 {
479 let x = self[i][0];
480 let y = self[i][1];
481 self[i][0] = x * c - y * s;
482 self[i][1] = x * s + y * c;
483 }
484 }
485
486 pub fn rotate_xyz(&mut self, angles: Vec3<T>) {
504 let cx = angles.x.cos();
505 let sx = angles.x.sin();
506 for i in 0..3 {
507 let y = self[i][1];
508 let z = self[i][2];
509 self[i][1] = y * cx - z * sx;
510 self[i][2] = y * sx + z * cx;
511 }
512 let cy = angles.y.cos();
513 let sy = angles.y.sin();
514 for i in 0..3 {
515 let x = self[i][0];
516 let z = self[i][2];
517 self[i][0] = x * cy + z * sy;
518 self[i][2] = -x * sy + z * cy;
519 }
520 let cz = angles.z.cos();
521 let sz = angles.z.sin();
522 for i in 0..3 {
523 let x = self[i][0];
524 let y = self[i][1];
525 self[i][0] = x * cz - y * sz;
526 self[i][1] = x * sz + y * cz;
527 }
528 }
529
530 pub fn rotate_zyx(&mut self, angles: Vec3<T>) {
548 let cz = angles.z.cos();
549 let sz = angles.z.sin();
550 for i in 0..3 {
551 let x = self[i][0];
552 let y = self[i][1];
553 self[i][0] = x * cz - y * sz;
554 self[i][1] = x * sz + y * cz;
555 }
556 let cy = angles.y.cos();
557 let sy = angles.y.sin();
558 for i in 0..3 {
559 let x = self[i][0];
560 let z = self[i][2];
561 self[i][0] = x * cy + z * sy;
562 self[i][2] = -x * sy + z * cy;
563 }
564 let cx = angles.x.cos();
565 let sx = angles.x.sin();
566 for i in 0..3 {
567 let y = self[i][1];
568 let z = self[i][2];
569 self[i][1] = y * cx - z * sx;
570 self[i][2] = y * sx + z * cx;
571 }
572 }
573
574 pub fn frustum(left: T, right: T, bottom: T, top: T, near_plane: T, far_plane: T) -> Self {
591 let two = T::from(2.0).unwrap();
592
593 let rl = right - left;
594 let tb = top - bottom;
595 let fn_ = far_plane - near_plane;
596
597 Self (
598 Vec4::new(
599 (near_plane * two) / rl,
600 T::zero(),
601 T::zero(),
602 T::zero(),
603 ),
604 Vec4::new(
605 T::zero(),
606 (near_plane * two) / tb,
607 T::zero(),
608 T::zero(),
609 ),
610 Vec4::new(
611 (right + left) / rl,
612 (top + bottom) / tb,
613 -((far_plane + near_plane) / fn_),
614 -T::one(),
615 ),
616 Vec4::new(
617 T::zero(),
618 T::zero(),
619 -((far_plane * near_plane * two) / fn_),
620 T::zero(),
621 )
622 )
623 }
624
625 pub fn perspective(fov_y: T, aspect: T, near_plane: T, far_plane: T) -> Self {
643 let two = T::from(2.0).unwrap();
644
645 let top = near_plane * (fov_y * T::from(0.5).unwrap()).tan();
646 let bottom = -top;
647 let right = top * aspect;
648 let left = -right;
649
650 let rl = right - left;
651 let tb = top - bottom;
652 let fn_ = far_plane - near_plane;
653
654 Self (
655 Vec4::new(
656 (near_plane * two) / rl,
657 T::zero(),
658 T::zero(),
659 T::zero(),
660 ),
661 Vec4::new(
662 T::zero(),
663 (near_plane * two) / tb,
664 T::zero(),
665 T::zero(),
666 ),
667 Vec4::new(
668 (right + left) / rl,
669 (top + bottom) / tb,
670 -((far_plane + near_plane) / fn_),
671 -T::one(),
672 ),
673 Vec4::new(
674 T::zero(),
675 T::zero(),
676 -((far_plane * near_plane * two) / fn_),
677 T::zero(),
678 )
679 )
680 }
681
682 pub fn orthographic(left: T, right: T, bottom: T, top: T, near_plane: T, far_plane: T) -> Self {
699 let two = T::from(2.0).unwrap();
700
701 let rl = right - left;
702 let tb = top - bottom;
703 let fn_ = far_plane - near_plane;
704
705 Self (
706 Vec4::new(
707 two / rl,
708 T::zero(),
709 T::zero(),
710 T::zero(),
711 ),
712 Vec4::new(
713 T::zero(),
714 two / tb,
715 T::zero(),
716 T::zero(),
717 ),
718 Vec4::new(
719 T::zero(),
720 T::zero(),
721 -two / fn_,
722 T::zero(),
723 ),
724 Vec4::new(
725 -((left + right) / rl),
726 -((top + bottom) / tb),
727 -((far_plane + near_plane) / fn_),
728 T::from(1.0).unwrap(),
729 )
730 )
731 }
732
733 pub fn look_at(eye: Vec3<T>, target: Vec3<T>, up: Vec3<T>) -> Self {
753 let vz = Vec3 {
754 x: eye.x - target.x,
755 y: eye.y - target.y,
756 z: eye.z - target.z,
757 };
758
759 let len = (vz.x * vz.x + vz.y * vz.y + vz.z * vz.z).sqrt();
760 let vz = if len != T::zero() {
761 Vec3 {
762 x: vz.x / len,
763 y: vz.y / len,
764 z: vz.z / len,
765 }
766 } else {
767 Vec3 {
768 x: T::zero(),
769 y: T::zero(),
770 z: T::zero(),
771 }
772 };
773
774 let vx = Vec3 {
775 x: up.y * vz.z - up.z * vz.y,
776 y: up.z * vz.x - up.x * vz.z,
777 z: up.x * vz.y - up.y * vz.x,
778 };
779
780 let len = (vx.x * vx.x + vx.y * vx.y + vx.z * vx.z).sqrt();
781 let vx = if len != T::zero() {
782 Vec3 {
783 x: vx.x / len,
784 y: vx.y / len,
785 z: vx.z / len,
786 }
787 } else {
788 Vec3 {
789 x: T::zero(),
790 y: T::zero(),
791 z: T::zero(),
792 }
793 };
794
795 let vy = Vec3 {
796 x: vz.y * vx.z - vz.z * vx.y,
797 y: vz.z * vx.x - vz.x * vx.z,
798 z: vz.x * vx.y - vz.y * vx.x,
799 };
800
801 Self (
802 Vec4::new(
803 vx.x,
804 vy.x,
805 vz.x,
806 T::zero(),
807 ),
808 Vec4::new(
809 vx.y,
810 vy.y,
811 vz.y,
812 T::zero(),
813 ),
814 Vec4::new(
815 vx.z,
816 vy.z,
817 vz.z,
818 T::zero(),
819 ),
820 Vec4::new(
821 -(vx.x * eye.x + vx.y * eye.y + vx.z * eye.z),
822 -(vy.x * eye.x + vy.y * eye.y + vy.z * eye.z),
823 -(vz.x * eye.x + vz.y * eye.y + vz.z * eye.z),
824 T::one(),
825 )
826 )
827 }
828}
829
830impl<T> fmt::Display for Mat4<T>
831where
832 T: fmt::Display,
833{
834 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
835 writeln!(f, "[{}, {}, {}, {}]", self.0, self.1, self.2, self.3)
836 }
837}
838
839impl<T> Index<usize> for Mat4<T> {
840 type Output = Vec4<T>;
841
842 fn index(&self, index: usize) -> &Self::Output {
843 match index {
844 0 => &self.0,
845 1 => &self.1,
846 2 => &self.2,
847 3 => &self.3,
848 _ => panic!("Index out of bounds for Mat4"),
849 }
850 }
851}
852
853impl<T> IndexMut<usize> for Mat4<T> {
854 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
855 match index {
856 0 => &mut self.0,
857 1 => &mut self.1,
858 2 => &mut self.2,
859 3 => &mut self.3,
860 _ => panic!("Index out of bounds for Mat4"),
861 }
862 }
863}
864
865impl<'a, T> IntoIterator for &'a Mat4<T>
866where
867 T: NumAssign + Copy
868{
869 type Item = &'a Vec4<T>;
870 type IntoIter = Iter<'a, Vec4<T>>;
871
872 #[inline]
873 fn into_iter(self) -> Self::IntoIter {
874 let slice: &[Vec4<T>; 4] = unsafe { std::mem::transmute(self) };
875 slice.iter()
876 }
877}
878
879impl<'a, T> IntoIterator for &'a mut Mat4<T>
880where
881 T: NumAssign + Copy
882{
883 type Item = &'a mut Vec4<T>;
884 type IntoIter = IterMut<'a, Vec4<T>>;
885
886 #[inline]
887 fn into_iter(self) -> Self::IntoIter {
888 let slice: &mut [Vec4<T>; 4] = unsafe { std::mem::transmute(self) };
889 slice.iter_mut()
890 }
891}
892
893impl<T> Neg for Mat4<T>
894where
895 T: NumAssign + Copy + Neg<Output = T>,
896{
897 type Output = Self;
898
899 fn neg(self) -> Self::Output {
900 Self (
901 -self.0,
902 -self.1,
903 -self.2,
904 -self.3,
905 )
906 }
907}
908
909impl<T> Add<Mat4<T>> for Mat4<T>
910where
911 T: NumAssign + Copy,
912{
913 type Output = Self;
914
915 fn add(self, other: Self) -> Self {
916 Self (
917 self.0 + other.0,
918 self.1 + other.1,
919 self.2 + other.2,
920 self.3 + other.3,
921 )
922 }
923}
924
925impl<T> Sub<Mat4<T>> for Mat4<T>
926where
927 T: NumAssign + Copy,
928{
929 type Output = Self;
930
931 fn sub(self, other: Self) -> Self {
932 Self (
933 self.0 - other.0,
934 self.1 - other.1,
935 self.2 - other.2,
936 self.3 - other.3,
937 )
938 }
939}
940
941impl<T> Mul<Mat4<T>> for Mat4<T>
942where
943 T: NumAssign + Copy,
944{
945 type Output = Mat4<T>;
946
947 #[inline]
948 fn mul(self, other: Mat4<T>) -> Mat4<T> {
949 Self::mul(&self, &other)
950 }
951}
952
953impl<T> Mul<T> for Mat4<T>
954where
955 T: NumAssign + Copy,
956{
957 type Output = Self;
958
959 fn mul(self, scalar: T) -> Self {
960 Self (
961 self.0 * scalar,
962 self.1 * scalar,
963 self.2 * scalar,
964 self.3 * scalar,
965 )
966 }
967}
968
969impl<T> Div<T> for Mat4<T>
970where
971 T: NumAssign + Copy,
972{
973 type Output = Self;
974
975 fn div(self, scalar: T) -> Self {
976 Self (
977 self.0 / scalar,
978 self.1 / scalar,
979 self.2 / scalar,
980 self.3 / scalar,
981 )
982 }
983}