#![allow(dead_code)] use std::borrow::Borrow; use std::convert::{AsMut, AsRef}; use std::fmt::{Debug, Formatter, Result as FmtResult}; use std::ops::{Deref, DerefMut, Mul}; #[cfg(feature = "serde")] use serde::{ de::{Deserializer, Error, MapAccess, SeqAccess, Visitor}, ser::{SerializeStruct, Serializer}, Deserialize, Serialize, }; use super::vector::{Vector2, Vector3, Vector4}; pub use super::{ angle::Angle, numeric::{Float, Numeric}, }; macro_rules! first_ptr { ($this:ident, $first:ident $(, $other:ident)*) => { unsafe { $this.$first.as_ptr() } }; } macro_rules! define_mat { ($Name:ident, $Vector:ident, $size:tt, $($T:ident => $i:tt => $f:ident),*) => { #[repr(C, packed)] pub struct $Name { $(pub $f: $Vector,)+ } impl $Name { #[inline] pub fn new($($f: $Vector,)+) -> Self { Self { $($f,)+ } } pub fn as_ptr(&self) -> * const T { first_ptr!(self $(,$f)+) } } impl Default for $Name where T: Numeric { #[inline] fn default() -> Self { Self::identity() } } impl Debug for $Name where T: Debug { fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult { fmt.debug_list().entries(self.as_ref().iter()).finish() } } impl PartialEq<$Name> for $Name where $Vector: PartialEq<$Vector>, { fn eq(&self, other: &$Name) -> bool { unsafe { true $(&& other.$f.eq(&self.$f))+ } } } impl Eq for $Name where T: Eq { } impl Deref for $Name { type Target = [$Vector; $size]; #[inline] fn deref(&self) -> &Self::Target { self.as_ref() } } impl DerefMut for $Name { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut() } } impl AsRef<[$Vector; $size]> for $Name { #[inline] fn as_ref(&self) -> &[$Vector; $size] { unsafe { let raw: * const _ = self; let raw = raw as * const [$Vector; $size]; &*raw } } } impl AsMut<[$Vector; $size]> for $Name { #[inline] fn as_mut(&mut self) -> &mut [$Vector; $size] { unsafe { let raw: * mut _ = self; let raw = raw as * mut [$Vector; $size]; &mut *raw } } } impl Clone for $Name where T: Clone { #[inline] fn clone(&self) -> Self { unsafe { Self { $($f: self.$f.clone(),)+ } } } } impl Copy for $Name where T: Copy { } impl From<[$Vector; $size]> for $Name where T: Copy, { #[inline] fn from(arr: [$Vector; $size]) -> Self { Self { $($f: arr[$i],)+ } } } impl From<($($Vector<$T>,)+)> for $Name { #[inline] fn from(($($f,)+): ($($Vector<$T>,)+)) -> Self { Self { $($f,)+ } } } #[cfg(feature = "serde")] impl Serialize for $Name where T: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer { let mut s = serializer.serialize_struct(stringify!($Name), $size)?; unsafe { $(s.serialize_field(stringify!($f), &self.$f)?;)+ } s.end() } } #[cfg(feature = "serde")] impl<'de, T> Deserialize<'de> for $Name where T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { struct MatrixVisitor(std::marker::PhantomData); impl<'de, X> Visitor<'de> for MatrixVisitor where X: Deserialize<'de>, { type Value = $Name; fn expecting(&self, formatter: &mut Formatter) -> FmtResult { formatter.write_fmt(format_args!("struct {}", stringify!($Name))) } fn visit_seq(self, mut seq: V) -> Result<$Name, V::Error> where V: SeqAccess<'de>, { Ok($Name { $($f: seq.next_element()?.ok_or_else(|| Error::invalid_length($i, &self))?,)+ }) } fn visit_map(self, mut map: V) -> Result<$Name, V::Error> where V: MapAccess<'de>, { $(let mut $f = None;)+ while let Some(key) = map.next_key()? { match key { $( stringify!($f) => { if $f.is_some() { return Err(Error::duplicate_field(stringify!($f))); } $f = Some(map.next_value()?); } )+ value => return Err(Error::unknown_field(value, FIELDS)), } } Ok($Name { $($f: $f.ok_or_else(|| Error::missing_field(stringify!($f)))?,)+ }) } } const FIELDS: &'static [&'static str] = &[$(stringify!($f),)+]; deserializer.deserialize_struct(stringify!($Name), FIELDS, MatrixVisitor::(std::marker::PhantomData)) } } }; } define_mat!(Matrix2, Vector2, 2, T => 0 => axis_x, T => 1 => axis_y); define_mat!(Matrix3, Vector3, 3, T => 0 => axis_x, T => 1 => axis_y, T => 2 => axis_z); define_mat!(Matrix4, Vector4, 4, T => 0 => axis_x, T => 1 => axis_y, T => 2 => axis_z, T => 3 => position); pub type Matrix2f = Matrix2; pub type Matrix3f = Matrix3; pub type Matrix4f = Matrix4; pub type Matrix2d = Matrix2; pub type Matrix3d = Matrix3; pub type Matrix4d = Matrix4; pub type Matrix2i = Matrix2; pub type Matrix3i = Matrix3; pub type Matrix4i = Matrix4; /* Matrix2 */ impl Matrix2 where T: Numeric, { #[inline] pub fn identity() -> Self { let one = T::one(); let zero = T::zero(); Self::new(Vector2::new(one, zero), Vector2::new(zero, one)) } } /* Matrix3 */ impl Matrix3 where T: Numeric, { #[inline] pub fn identity() -> Self { let one = T::one(); let zero = T::zero(); Self::new( Vector3::new(one, zero, zero), Vector3::new(zero, one, zero), Vector3::new(zero, zero, one), ) } #[inline] pub fn translate(v: Vector2) -> Self { let one = T::one(); let zro = T::zero(); Self::new( Vector3::new(one, zro, zro), Vector3::new(zro, one, zro), Vector3::new(v.x, v.y, one), ) } #[inline] pub fn determinant(&self) -> T { let m = self; m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * m[0][1] * m[1][2] - m[2][0] * m[1][1] * m[0][2] - m[1][0] * m[0][1] * m[2][2] - m[0][0] * m[2][1] * m[1][2] } #[inline] pub fn multiply(&self, other: &Self) -> Self { let m1 = self; let m2 = other; macro_rules! mul { ($x:tt, $y:tt) => { m1[0][$y] * m2[$x][0] + m1[1][$y] * m2[$x][1] + m1[2][$y] * m2[$x][2] }; } Self::new( Vector3::new(mul!(0, 0), mul!(0, 1), mul!(0, 2)), Vector3::new(mul!(1, 0), mul!(1, 1), mul!(1, 2)), Vector3::new(mul!(2, 0), mul!(2, 1), mul!(2, 2)), ) } } impl Matrix3 where T: Float, { #[inline] pub fn rotate(a: Angle) -> Self { let one = T::one(); let zro = T::zero(); Self::new( Vector3::new(a.cos(), -a.sin(), zro), Vector3::new(a.sin(), a.cos(), zro), Vector3::new(zro, zro, one), ) } } impl Mul for Matrix3 where T: Float, M: Borrow>, { type Output = Self; fn mul(self, rhs: M) -> Self::Output { self.multiply(rhs.borrow()) } } /* Matrix4 */ impl Matrix4 where T: Numeric, { #[inline] pub fn identity() -> Self { let one = T::one(); let zero = T::zero(); Self::new( Vector4::new(one, zero, zero, zero), Vector4::new(zero, one, zero, zero), Vector4::new(zero, zero, one, zero), Vector4::new(zero, zero, zero, one), ) } } impl Matrix4 where T: Float, { #[inline] pub fn translate(v: Vector3) -> Self { let one = T::one(); let zero = T::zero(); Self::new( Vector4::new(one, zero, zero, zero), Vector4::new(zero, one, zero, zero), Vector4::new(zero, zero, one, zero), Vector4::new(v.x, v.y, v.z, one), ) } #[inline] pub fn scale(v: Vector3) -> Self { let one = T::one(); let zero = T::zero(); Self::new( Vector4::new(v.x, zero, zero, zero), Vector4::new(zero, v.y, zero, zero), Vector4::new(zero, zero, v.z, zero), Vector4::new(zero, zero, zero, one), ) } #[inline] #[allow(clippy::many_single_char_names)] pub fn rotate(axis: Vector3, angle: Angle) -> Self { let axis = axis.normalize(); let x = axis.x; let y = axis.y; let z = axis.z; let angle = angle.into_rad().into_inner(); let s = T::sin(angle); let c = T::cos(angle); let one = T::one(); let zero = T::zero(); Self::new( Vector4::new( x * x + (one - y * y) * c, x * y * (one - c) + z * s, x * z * (one - c) - y * s, zero, ), Vector4::new( x * y * (one - c) - z * s, y * y + (one - y * y) * c, y * z * (one - c) + x * s, zero, ), Vector4::new( x * z * (one - c) + y * s, y * z * (one - c) - x * s, z * z + (one - z * z) * c, zero, ), Vector4::new(zero, zero, zero, one), ) } #[inline] pub fn multiply(&self, other: &Self) -> Self { let m1 = self; let m2 = other; macro_rules! mul { ($x:tt, $y:tt) => { m1[0][$y] * m2[$x][0] + m1[1][$y] * m2[$x][1] + m1[2][$y] * m2[$x][2] + m1[3][$y] * m2[$x][3] }; } Self::new( Vector4::new(mul!(0, 0), mul!(0, 1), mul!(0, 2), mul!(0, 3)), Vector4::new(mul!(1, 0), mul!(1, 1), mul!(1, 2), mul!(1, 3)), Vector4::new(mul!(2, 0), mul!(2, 1), mul!(2, 2), mul!(2, 3)), Vector4::new(mul!(3, 0), mul!(3, 1), mul!(3, 2), mul!(3, 3)), ) } #[inline] pub fn transform(&self, v: &Vector4) -> Vector4 { let m = self; macro_rules! mul { ($i:tt) => { m[0][$i] * v[0] + m[1][$i] * v[1] + m[2][$i] * v[2] + m[3][$i] * v[3] }; } Vector4::new(mul!(0), mul!(1), mul!(2), mul!(3)) } #[inline] pub fn transpose(&self) -> Self { let m = self; Self::new( Vector4::new(m[0][0], m[1][0], m[2][0], m[3][0]), Vector4::new(m[0][1], m[1][1], m[2][1], m[3][1]), Vector4::new(m[0][2], m[1][2], m[2][2], m[3][2]), Vector4::new(m[0][3], m[1][3], m[2][3], m[3][3]), ) } #[inline] pub fn submatrix(&self, s: usize, z: usize) -> Matrix3 { let mut ret = Matrix3::identity(); for i in 0..=2 { for j in 0..=2 { let x = if i >= s { i + 1 } else { i }; let y = if j >= z { j + 1 } else { j }; ret[i][j] = self[x][y]; } } ret } #[inline] pub fn determinant(&self) -> T { let m = self; m[0][0] * m.submatrix(0, 0).determinant() - m[1][0] * m.submatrix(1, 0).determinant() + m[2][0] * m.submatrix(2, 0).determinant() + m[3][0] * m.submatrix(3, 0).determinant() } #[inline] pub fn adjoint(&self) -> Self { let m = self; Self::new( Vector4::new( m.submatrix(0, 0).determinant(), -m.submatrix(1, 0).determinant(), m.submatrix(2, 0).determinant(), -m.submatrix(3, 0).determinant(), ), Vector4::new( -m.submatrix(0, 1).determinant(), m.submatrix(1, 1).determinant(), -m.submatrix(2, 1).determinant(), m.submatrix(3, 1).determinant(), ), Vector4::new( m.submatrix(0, 2).determinant(), -m.submatrix(1, 2).determinant(), m.submatrix(2, 2).determinant(), -m.submatrix(3, 2).determinant(), ), Vector4::new( -m.submatrix(0, 3).determinant(), m.submatrix(1, 3).determinant(), -m.submatrix(2, 3).determinant(), m.submatrix(3, 3).determinant(), ), ) } #[inline] pub fn invert(&self) -> Self { let d = self.determinant(); let mut ret = self.adjoint(); ret[0][0] = ret[0][0] / d; ret[0][1] = ret[0][1] / d; ret[0][2] = ret[0][2] / d; ret[0][3] = ret[0][3] / d; ret[1][0] = ret[1][0] / d; ret[1][1] = ret[1][1] / d; ret[1][2] = ret[1][2] / d; ret[1][3] = ret[1][3] / d; ret[2][0] = ret[2][0] / d; ret[2][1] = ret[2][1] / d; ret[2][2] = ret[2][2] / d; ret[2][3] = ret[2][3] / d; ret[3][0] = ret[3][0] / d; ret[3][1] = ret[3][1] / d; ret[3][2] = ret[3][2] / d; ret[3][3] = ret[3][3] / d; ret } } impl Matrix4 where T: Float, { #[inline] pub fn ortho(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Self { let one = T::one(); let two = one + one; let zero = T::zero(); Matrix4::new( Vector4::new(two / (right - left), zero, zero, zero), Vector4::new(zero, two / (top - bottom), zero, zero), Vector4::new(zero, zero, -two / (far - near), zero), Vector4::new( -(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), one, ), ) } #[inline] pub fn perspective(fov: Angle, ratio: T, near: T, far: T) -> Self { let one = T::one(); let two = one + one; let zero = T::zero(); let top = near * fov.into_rad().into_inner().tan(); let bottom = -top; let right = ratio * top; let left = -right; Matrix4::new( Vector4::new(two * near / (right - left), zero, zero, zero), Vector4::new(zero, two * near / (top - bottom), zero, zero), Vector4::new( (right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -one, ), Vector4::new(zero, zero, -two * far * near / (far - near), zero), ) } } impl Mul for Matrix4 where T: Float, M: Borrow>, { type Output = Self; fn mul(self, rhs: M) -> Self::Output { self.multiply(rhs.borrow()) } } #[cfg(test)] mod tests { use super::*; #[test] fn invert() { let m = Matrix4d::identity() * Matrix4::translate(Vector3::new(1.0, 2.0, 3.0)) * Matrix4::scale(Vector3::new(30.0, 20.0, 10.0)) * Matrix4::rotate(Vector3::new(1.0, 0.0, 0.0), Angle::Deg(45.0)); let m = m.invert(); let e = Matrix4d::new( Vector4::new( 0.019526214587563498, -0.000000000000000000, 0.000000000000000000, -0.000000000000000000, ), Vector4::new( -0.000000000000000000, 0.035355339059327376, -0.035355339059327376, 0.000000000000000000, ), Vector4::new( 0.00000000000000000, 0.07071067811865475, 0.07071067811865475, -0.00000000000000000, ), Vector4::new( -0.019526214587563498, -0.282842712474619000, -0.141421356237309560, 1.000000000000000000, ), ); assert_eq!(e, m); } }