use super::*;
mod extra;
mod ops;
mod projection;
mod transform;
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct mat4<T>(pub(crate) [[T; 4]; 4]);
impl<T> mat4<T> {
pub fn map<U, F: Fn(T) -> U>(self, f: F) -> mat4<U> {
mat4(self.0.map(|row| row.map(&f)))
}
}
impl<T: Copy> mat4<T> {
pub fn new(values: [[T; 4]; 4]) -> Self {
Self(values).transpose()
}
pub fn row(&self, row_index: usize) -> vec4<T> {
vec4(
self[(row_index, 0)],
self[(row_index, 1)],
self[(row_index, 2)],
self[(row_index, 3)],
)
}
pub fn col(&self, col_index: usize) -> vec4<T> {
vec4(
self[(0, col_index)],
self[(1, col_index)],
self[(2, col_index)],
self[(3, col_index)],
)
}
}
impl<T> Index<(usize, usize)> for mat4<T> {
type Output = T;
fn index(&self, (row, col): (usize, usize)) -> &T {
&self.0[col][row]
}
}
impl<T> IndexMut<(usize, usize)> for mat4<T> {
fn index_mut(&mut self, (row, col): (usize, usize)) -> &mut T {
&mut self.0[col][row]
}
}
impl<T> mat4<T> {
pub fn as_flat_array(&self) -> &[T; 16] {
unsafe { std::mem::transmute(self) }
}
pub fn as_flat_array_mut(&mut self) -> &mut [T; 16] {
unsafe { std::mem::transmute(self) }
}
}
impl<T: Num + Copy> mat4<T> {
pub fn zero() -> Self {
mat4([[T::ZERO; 4]; 4])
}
pub fn identity() -> Self {
let mut result = Self::zero();
for i in 0..4 {
result[(i, i)] = T::ONE;
}
result
}
}
impl<T: Float> Approx for mat4<T> {
fn approx_distance_to(&self, other: &Self) -> f32 {
let mut dist = 0.0;
for i in 0..4 {
for j in 0..4 {
dist = partial_max(dist, (other[(i, j)] - self[(i, j)]).abs().as_f32());
}
}
dist
}
}