|
|
@@ -0,0 +1,508 @@ |
|
|
|
#![allow(dead_code)] |
|
|
|
|
|
|
|
use std::convert::{AsMut, AsRef}; |
|
|
|
use std::fmt::{Debug, Formatter, Result as FmtResult}; |
|
|
|
use std::ops::{Deref, DerefMut, Mul}; |
|
|
|
|
|
|
|
use super::vector::{Element, Vector2, Vector3, Vector4}; |
|
|
|
|
|
|
|
macro_rules! define_mat { |
|
|
|
($Name:ident, $Vector:ident, $size:tt, $($T:ident => $i:tt => $f:ident),*) => { |
|
|
|
#[repr(C, packed)] |
|
|
|
pub struct $Name<T> { |
|
|
|
$(pub $f: $Vector<T>,)+ |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> $Name<T> { |
|
|
|
#[inline] |
|
|
|
pub fn new($($f: $Vector<T>,)+) -> Self { |
|
|
|
Self { $($f,)+ } |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> Default for $Name<T> |
|
|
|
where |
|
|
|
T: Element |
|
|
|
{ |
|
|
|
#[inline] |
|
|
|
fn default() -> Self { |
|
|
|
Self::identity() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> Debug for $Name<T> |
|
|
|
where |
|
|
|
T: Debug |
|
|
|
{ |
|
|
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult { |
|
|
|
fmt.debug_list().entries(self.as_ref().iter()).finish() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T, S> PartialEq<$Name<S>> for $Name<T> |
|
|
|
where |
|
|
|
$Vector<S>: PartialEq<$Vector<T>>, |
|
|
|
{ |
|
|
|
fn eq(&self, other: &$Name<S>) -> bool { |
|
|
|
unsafe { true $(&& other.$f.eq(&self.$f))+ } |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> Eq for $Name<T> |
|
|
|
where |
|
|
|
T: Eq |
|
|
|
{ } |
|
|
|
|
|
|
|
impl<T> Deref for $Name<T> { |
|
|
|
type Target = [$Vector<T>; $size]; |
|
|
|
|
|
|
|
#[inline] |
|
|
|
fn deref(&self) -> &Self::Target { |
|
|
|
self.as_ref() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> DerefMut for $Name<T> { |
|
|
|
#[inline] |
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target { |
|
|
|
self.as_mut() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> AsRef<[$Vector<T>; $size]> for $Name<T> { |
|
|
|
#[inline] |
|
|
|
fn as_ref(&self) -> &[$Vector<T>; $size] { |
|
|
|
unsafe { |
|
|
|
let raw: * const _ = self; |
|
|
|
let raw = raw as * const [$Vector<T>; $size]; |
|
|
|
|
|
|
|
&*raw |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> AsMut<[$Vector<T>; $size]> for $Name<T> { |
|
|
|
#[inline] |
|
|
|
fn as_mut(&mut self) -> &mut [$Vector<T>; $size] { |
|
|
|
unsafe { |
|
|
|
let raw: * mut _ = self; |
|
|
|
let raw = raw as * mut [$Vector<T>; $size]; |
|
|
|
|
|
|
|
&mut *raw |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> Clone for $Name<T> |
|
|
|
where |
|
|
|
T: Clone |
|
|
|
{ |
|
|
|
#[inline] |
|
|
|
fn clone(&self) -> Self { |
|
|
|
unsafe { |
|
|
|
Self { |
|
|
|
$($f: self.$f.clone(),)+ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> Copy for $Name<T> |
|
|
|
where |
|
|
|
T: Copy |
|
|
|
{ } |
|
|
|
|
|
|
|
impl<T> From<[$Vector<T>; $size]> for $Name<T> |
|
|
|
where |
|
|
|
T: Copy, |
|
|
|
{ |
|
|
|
#[inline] |
|
|
|
fn from(arr: [$Vector<T>; $size]) -> Self { |
|
|
|
Self { |
|
|
|
$($f: arr[$i],)+ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> From<($($Vector<$T>,)+)> for $Name<T> { |
|
|
|
#[inline] |
|
|
|
fn from(($($f,)+): ($($Vector<$T>,)+)) -> Self { |
|
|
|
Self { |
|
|
|
$($f,)+ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
type Matrix2f = Matrix2<gl::GLfloat>; |
|
|
|
type Matrix3f = Matrix3<gl::GLfloat>; |
|
|
|
type Matrix4f = Matrix4<gl::GLfloat>; |
|
|
|
|
|
|
|
type Matrix2d = Matrix2<gl::GLdouble>; |
|
|
|
type Matrix3d = Matrix3<gl::GLdouble>; |
|
|
|
type Matrix4d = Matrix4<gl::GLdouble>; |
|
|
|
|
|
|
|
type Matrix2i = Matrix2<gl::GLint>; |
|
|
|
type Matrix3i = Matrix3<gl::GLint>; |
|
|
|
type Matrix4i = Matrix4<gl::GLint>; |
|
|
|
|
|
|
|
/* Matrix2 */ |
|
|
|
|
|
|
|
impl<T> Matrix2<T> |
|
|
|
where |
|
|
|
T: Element, |
|
|
|
{ |
|
|
|
#[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<T> Matrix3<T> |
|
|
|
where |
|
|
|
T: Element, |
|
|
|
{ |
|
|
|
#[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 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] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Matrix4 */ |
|
|
|
|
|
|
|
impl<T> Matrix4<T> |
|
|
|
where |
|
|
|
T: Element, |
|
|
|
{ |
|
|
|
#[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), |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
#[inline] |
|
|
|
pub fn translate(v: Vector3<T>) -> 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<T>) -> 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<T>, angle: Angle<T>) -> 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<T>) -> Vector4<T> { |
|
|
|
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<T> { |
|
|
|
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<T> Mul<Matrix4<T>> for Matrix4<T> |
|
|
|
where |
|
|
|
T: Element, |
|
|
|
{ |
|
|
|
type Output = Self; |
|
|
|
|
|
|
|
fn mul(self, rhs: Self) -> Self::Output { |
|
|
|
self.multiply(&rhs) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> Mul<Vector4<T>> for Matrix4<T> |
|
|
|
where |
|
|
|
T: Element, |
|
|
|
{ |
|
|
|
type Output = Vector4<T>; |
|
|
|
|
|
|
|
fn mul(self, rhs: Vector4<T>) -> Self::Output { |
|
|
|
self.transform(&rhs) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Angle */ |
|
|
|
|
|
|
|
pub enum Angle<T> { |
|
|
|
Deg(T), |
|
|
|
Rad(T), |
|
|
|
} |
|
|
|
|
|
|
|
impl<T> Angle<T> |
|
|
|
where |
|
|
|
T: Element, |
|
|
|
{ |
|
|
|
pub fn into_inner(self) -> T { |
|
|
|
match self { |
|
|
|
Self::Deg(v) => v, |
|
|
|
Self::Rad(v) => v, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
pub fn into_deg(self) -> Self { |
|
|
|
match self { |
|
|
|
Self::Deg(v) => Self::Deg(v), |
|
|
|
Self::Rad(v) => Self::Rad(T::to_degrees(v)), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
pub fn into_rad(self) -> Self { |
|
|
|
match self { |
|
|
|
Self::Deg(v) => Self::Deg(T::to_radians(v)), |
|
|
|
Self::Rad(v) => Self::Rad(v), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#[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); |
|
|
|
} |
|
|
|
} |