batbox_la/mat/_4x4/
mod.rs

1use super::*;
2
3mod extra;
4mod ops;
5mod projection;
6mod transform;
7
8/// 4x4 matrix
9#[allow(non_camel_case_types)]
10#[repr(C)]
11#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
12pub struct mat4<T>(pub(crate) [[T; 4]; 4]);
13
14impl<T> mat4<T> {
15    /// Map every element
16    pub fn map<U, F: Fn(T) -> U>(self, f: F) -> mat4<U> {
17        mat4(self.0.map(|row| row.map(&f)))
18    }
19}
20
21impl<T: Copy> mat4<T> {
22    /// Construct a matrix.
23    ///
24    /// # Examples
25    /// ```
26    /// # use batbox_la::*;
27    /// let matrix = mat4::new([
28    ///     [1, 2, 3, 4],
29    ///     [3, 4, 5, 6],
30    ///     [5, 6, 7, 8],
31    ///     [0, 5, 2, 9],
32    /// ]);
33    /// ```
34    pub fn new(values: [[T; 4]; 4]) -> Self {
35        Self(values).transpose()
36    }
37
38    /// Get a row as a [vec4]
39    pub fn row(&self, row_index: usize) -> vec4<T> {
40        vec4(
41            self[(row_index, 0)],
42            self[(row_index, 1)],
43            self[(row_index, 2)],
44            self[(row_index, 3)],
45        )
46    }
47
48    /// Get a column as a [vec4]
49    pub fn col(&self, col_index: usize) -> vec4<T> {
50        vec4(
51            self[(0, col_index)],
52            self[(1, col_index)],
53            self[(2, col_index)],
54            self[(3, col_index)],
55        )
56    }
57}
58
59impl<T> Index<(usize, usize)> for mat4<T> {
60    type Output = T;
61    fn index(&self, (row, col): (usize, usize)) -> &T {
62        &self.0[col][row]
63    }
64}
65
66impl<T> IndexMut<(usize, usize)> for mat4<T> {
67    fn index_mut(&mut self, (row, col): (usize, usize)) -> &mut T {
68        &mut self.0[col][row]
69    }
70}
71
72impl<T> mat4<T> {
73    /// Get self as a flat array
74    pub fn as_flat_array(&self) -> &[T; 16] {
75        unsafe { std::mem::transmute(self) }
76    }
77    /// Get self as a mutable flat array
78    pub fn as_flat_array_mut(&mut self) -> &mut [T; 16] {
79        unsafe { std::mem::transmute(self) }
80    }
81}
82
83impl<T: Num + Copy> mat4<T> {
84    /// Construct zero matrix.
85    ///
86    /// # Examples
87    /// ```
88    /// # use batbox_la::*;
89    /// let matrix = mat4::<i32>::zero();
90    /// for i in 0..4 {
91    ///     for j in 0..4 {
92    ///         assert_eq!(matrix[(i, j)], 0);
93    ///     }
94    /// }
95    /// ```
96    pub fn zero() -> Self {
97        mat4([[T::ZERO; 4]; 4])
98    }
99
100    /// Construct identity matrix.
101    ///
102    /// # Examples
103    /// ```
104    /// # use batbox_la::*;
105    /// let matrix = mat4::<i32>::identity();
106    /// for i in 0..4 {
107    ///     for j in 0..4 {
108    ///         assert_eq!(matrix[(i, j)], if i == j { 1 } else { 0 });
109    ///     }
110    /// }
111    /// ```
112    pub fn identity() -> Self {
113        let mut result = Self::zero();
114        for i in 0..4 {
115            result[(i, i)] = T::ONE;
116        }
117        result
118    }
119}
120
121impl<T: Float> Approx for mat4<T> {
122    fn approx_distance_to(&self, other: &Self) -> f32 {
123        let mut dist = 0.0;
124        for i in 0..4 {
125            for j in 0..4 {
126                dist = partial_max(dist, (other[(i, j)] - self[(i, j)]).abs().as_f32());
127            }
128        }
129        dist
130    }
131}