use std::ops::*;
use super::Vec3;
use super::real::Real;
pub type Elements<R> = [[R; 4]; 4];
#[derive(Copy, Clone, Debug)]
pub struct Mat4<R: Real = f32> {
elements: Elements<R>,
}
impl<R: Real> Mat4<R> {
pub fn zero() -> Self {
Self::from([[R::zero(); 4]; 4])
}
pub fn identity() -> Self {
let zero = R::zero();
let one = R::one();
Self::from([
[one, zero, zero, zero],
[zero, one, zero, zero],
[zero, zero, one, zero],
[zero, zero, zero, one],
])
}
pub fn ortho(left: R, right: R, top: R, bottom: R, near: R, far: R) -> Self {
let zero = R::zero();
let one = R::one();
let two = R::two();
Self::from([
[two / (right - left), zero, zero, zero],
[zero, two / (top - bottom), zero, zero],
[zero, zero, two / (near - far), zero],
[(left + right) / (left - right), (bottom + top) / (bottom - top), (near + far) / (near - far), one],
])
}
pub fn model(position: Vec3<R>, scale: Vec3<R>) -> Self {
Self::translation(position) * Self::scale(scale)
}
pub fn translation(position: Vec3<R>) -> Self {
let zero = R::zero();
let one = R::one();
Self::from([
[one, zero, zero, zero],
[zero, one, zero, zero],
[zero, zero, one, zero],
[position.x, position.y, position.z, one],
])
}
pub fn scale(scale: Vec3<R>) -> Mat4<R> {
let zero = R::zero();
let one = R::one();
Self::from([
[scale.x, zero, zero, zero],
[zero, scale.y, zero, zero],
[zero, zero, scale.z, zero],
[zero, zero, zero, one],
])
}
pub fn elements(&self) -> Elements<R> {
self.elements
}
}
impl<R: Real> Index<(usize, usize)> for Mat4<R> {
type Output = R;
fn index(&self, index: (usize, usize)) -> &Self::Output {
&self.elements[index.1][index.0]
}
}
impl<R: Real> IndexMut<(usize, usize)> for Mat4<R> {
fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
&mut self.elements[index.1][index.0]
}
}
impl<R: Real> Add<Self> for Mat4<R> {
type Output = Self;
fn add(self, other: Self) -> Self {
let mut result = Self::zero();
for i in 0 .. 4 {
for j in 0 .. 4 {
result[(i, j)] = self[(i, j)] + other[(i, j)];
}
}
return result
}
}
impl<R: Real> AddAssign<Self> for Mat4<R> {
fn add_assign(&mut self, other: Self) {
for i in 0 .. 4 {
for j in 0 .. 4 {
self[(i, j)] += other[(i, j)];
}
}
}
}
impl<R: Real> Sub<Self> for Mat4<R> {
type Output = Self;
fn sub(self, other: Self) -> Self {
let mut result = Self::zero();
for i in 0 .. 4 {
for j in 0 .. 4 {
result[(i, j)] = self[(i, j)] - other[(i, j)];
}
}
return result
}
}
impl<R: Real> SubAssign<Self> for Mat4<R> {
fn sub_assign(&mut self, other: Self) {
for i in 0 .. 4 {
for j in 0 .. 4 {
self[(i, j)] -= other[(i, j)];
}
}
}
}
impl<R: Real> Mul<Self> for Mat4<R> {
type Output = Self;
fn mul(self, right: Self) -> Self {
let mut result = Self::zero();
for i in 0 .. 4 {
for j in 0 .. 4 {
for k in 0 .. 4 {
result[(i, j)] += self[(i, k)] * right[(k, j)];
}
}
}
result
}
}
impl<R: Real> From<Elements<R>> for Mat4<R> {
fn from(elements: Elements<R>) -> Self {
Self { elements }
}
}