use crate::vec::*;
use crate::num::*;
use crate::quat::*;
use std::ops::Index;
use std::ops::IndexMut;
use std::ops::Mul;
use std::ops::MulAssign;
use std::ops::Deref;
use std::ops::DerefMut;
use std::cmp::PartialEq;
use std::fmt::Display;
use std::fmt::Formatter;
macro_rules! mat_impl {
($MatN:ident, $rows:expr, $cols:expr, $elems:expr,
$RowVecN:ident { $($row_field:ident, $row_field_index:expr),* },
$ColVecN:ident { $($col_field:ident, $col_field_index:expr),* } ) => {
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct $MatN<T> {
pub m: [T; $elems]
}
impl<T> Index<(usize, usize)> for $MatN<T> {
type Output = T;
fn index(&self, rc: (usize, usize)) -> &Self::Output {
&self.m[rc.0 * $cols + rc.1]
}
}
impl<T> IndexMut<(usize, usize)> for $MatN<T> {
fn index_mut(&mut self, rc: (usize, usize)) -> &mut Self::Output {
&mut self.m[rc.0 * $cols + rc.1]
}
}
impl<T> Index<usize> for $MatN<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
&self.m[index]
}
}
impl<T> IndexMut<usize> for $MatN<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.m[index]
}
}
impl<T> Deref for $MatN<T> where T: Number {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T> DerefMut for $MatN<T> where T: Number {
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<T> Display for $MatN<T> where T: Display {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut output = String::from("");
for r in 0..$rows {
output += &String::from("[");
for c in 0..$cols {
output += &self[(r, c)].to_string();
if c < $cols-1 {
output += &String::from(", ");
}
}
output += "]";
if r < $rows-1 {
output += "\n";
}
}
write!(f, "{}", output)
}
}
impl<T> Eq for $MatN<T> where T: Eq {}
impl<T> PartialEq for $MatN<T> where T: PartialEq {
fn eq(&self, other: &Self) -> bool {
for i in 0..$elems {
if self.m[i] != other.m[i] {
return false;
}
}
true
}
}
impl<T> $MatN<T> where T: Float + FloatOps<T> {
pub fn approx(lhs: Self, rhs: Self, eps: T) -> bool {
for i in 0..$elems {
if !T::approx(lhs.m[i], rhs.m[i], eps) {
return false;
}
}
true
}
}
impl<T> $MatN<T> where T: Number {
pub fn zero() -> $MatN<T> {
$MatN {
m: [T::zero(); $elems]
}
}
pub fn identity() -> $MatN<T> {
unsafe {
let mut mat : $MatN<T> = std::mem::zeroed();
for r in 0..$rows {
for c in 0..$cols {
if c == r {
mat.set(r, c, T::one());
}
}
}
mat
}
}
pub fn at(self, row: u32, column: u32) -> T {
let urow = row as usize;
let ucol = column as usize;
self.m[urow * $cols + ucol]
}
pub fn set(&mut self, row: u32, column: u32, value: T) {
let urow = row as usize;
let ucol = column as usize;
self.m[urow * $cols + ucol] = value
}
pub fn get_row(self, row: u32) -> $RowVecN<T> {
let urow = row as usize;
$RowVecN {
$($row_field: self.m[urow * $cols + $row_field_index],)+
}
}
pub fn set_row(&mut self, row: u32, value: $RowVecN<T>) {
let urow = row as usize;
$(self.m[urow * $cols + $row_field_index] = value.$row_field;)+
}
pub fn get_column(self, column: u32) -> $ColVecN<T> {
let ucol = column as usize;
$ColVecN {
$($col_field: self.m[$col_field_index * $cols + ucol],)+
}
}
pub fn set_column(&mut self, column: u32, value: $ColVecN<T>) {
let ucol = column as usize;
$(self.m[$col_field_index * $cols + ucol] = value.$col_field;)+
}
pub fn as_slice(&self) -> &[T] {
unsafe {
std::slice::from_raw_parts(&self.m[0], $elems)
}
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe {
std::slice::from_raw_parts_mut(&mut self.m[0], $elems)
}
}
pub fn as_u8_slice(&self) -> &[u8] {
unsafe {
std::slice::from_raw_parts((&self.m[0] as *const T) as *const u8, std::mem::size_of::<$MatN<T>>())
}
}
pub fn transpose(&self) -> $MatN<T> {
let mut t = *self;
for r in 0..$rows {
for c in 0..$cols {
t.set(c, r, self.at(r, c));
}
}
t
}
}
}
}
macro_rules! mat_cast {
($MatN:ident, $count:expr, $t:ident, $u:ident) => {
impl From<$MatN<$u>> for $MatN<$t> {
fn from(other: $MatN<$u>) -> $MatN<$t> {
unsafe {
let mut mm : $MatN<$t> = std::mem::zeroed();
for i in 0..$count {
mm.m[i] = other.m[i] as $t;
}
mm
}
}
}
impl From<$MatN<$t>> for $MatN<$u> {
fn from(other: $MatN<$t>) -> $MatN<$u> {
unsafe {
let mut mm : $MatN<$u> = std::mem::zeroed();
for i in 0..$count {
mm.m[i] = other.m[i] as $u;
}
mm
}
}
}
}
}
#[cfg(feature = "casts")]
mat_cast!(Mat2, 4, f32, f64);
mat_cast!(Mat3, 9, f32, f64);
mat_cast!(Mat34, 12, f32, f64);
mat_cast!(Mat4, 16, f32, f64);
impl<T> From<(T, T, T, T)> for Mat2<T> where T: Number {
fn from(other: (T, T, T, T)) -> Mat2<T> {
Mat2 {
m: [
other.0, other.1,
other.2, other.3
]
}
}
}
impl<T> From<(Vec2<T>, Vec2<T>)> for Mat2<T> where T: Number {
fn from(other: (Vec2<T>, Vec2<T>)) -> Mat2<T> {
Mat2 {
m: [
other.0.x, other.0.y,
other.1.x, other.1.y
]
}
}
}
impl<T> From<Mat3<T>> for Mat2<T> where T: Number {
fn from(other: Mat3<T>) -> Mat2<T> {
Mat2 {
m: [
other.m[0], other.m[1],
other.m[3], other.m[4],
]
}
}
}
impl<T> From<Mat34<T>> for Mat2<T> where T: Number {
fn from(other: Mat34<T>) -> Mat2<T> {
Mat2 {
m: [
other.m[0], other.m[1],
other.m[4], other.m[5],
]
}
}
}
impl<T> From<Mat4<T>> for Mat2<T> where T: Number {
fn from(other: Mat4<T>) -> Mat2<T> {
Mat2 {
m: [
other.m[0], other.m[1],
other.m[4], other.m[5],
]
}
}
}
impl<T> From<Mat2<T>> for Mat3<T> where T: Number {
fn from(other: Mat2<T>) -> Mat3<T> {
Mat3 {
m: [
other.m[0], other.m[1], T::zero(),
other.m[2], other.m[3], T::zero(),
T::zero(), T::zero(), T::one()
]
}
}
}
impl<T> From<Mat34<T>> for Mat3<T> where T: Number {
fn from(other: Mat34<T>) -> Mat3<T> {
Mat3 {
m: [
other.m[0], other.m[1], other.m[2],
other.m[4], other.m[5], other.m[6],
other.m[8], other.m[9], other.m[10],
]
}
}
}
impl<T> From<Mat4<T>> for Mat3<T> where T: Number {
fn from(other: Mat4<T>) -> Mat3<T> {
Mat3 {
m: [
other.m[0], other.m[1], other.m[2],
other.m[4], other.m[5], other.m[6],
other.m[8], other.m[9], other.m[10],
]
}
}
}
impl<T> From<(T, T, T, T, T, T, T, T, T)> for Mat3<T> where T: Number {
fn from(other: (T, T, T, T, T, T, T, T, T)) -> Mat3<T> {
Mat3 {
m: [
other.0, other.1, other.2,
other.3, other.4, other.5,
other.6, other.7, other.8,
]
}
}
}
impl<T> From<(Vec3<T>, Vec3<T>, Vec3<T>)> for Mat3<T> where T: Number {
fn from(other: (Vec3<T>, Vec3<T>, Vec3<T>)) -> Mat3<T> {
Mat3 {
m: [
other.0.x, other.0.y, other.0.z,
other.1.x, other.1.y, other.1.z,
other.2.x, other.2.y, other.2.z,
]
}
}
}
impl<T> From<Quat<T>> for Mat3<T> where T: Float + SignedNumber + FloatOps<T> + NumberOps<T> + SignedNumberOps<T> {
fn from(other: Quat<T>) -> Mat3<T> {
other.get_matrix()
}
}
impl<T> From<Mat2<T>> for Mat34<T> where T: Number {
fn from(other: Mat2<T>) -> Mat34<T> {
Mat34 {
m: [
other.m[0], other.m[1], T::zero(), T::zero(),
other.m[2], other.m[3], T::zero(), T::zero(),
T::zero(), T::zero(), T::one(), T::zero(),
]
}
}
}
impl<T> From<Mat3<T>> for Mat34<T> where T: Number {
fn from(other: Mat3<T>) -> Mat34<T> {
Mat34 {
m: [
other.m[0], other.m[1], other.m[2], T::zero(),
other.m[3], other.m[4], other.m[5], T::zero(),
other.m[6], other.m[7], other.m[8], T::zero(),
]
}
}
}
impl<T> From<Quat<T>> for Mat34<T> where T: Float + SignedNumber + FloatOps<T> + NumberOps<T> + SignedNumberOps<T> {
fn from(other: Quat<T>) -> Mat34<T> {
Mat34::from(other.get_matrix())
}
}
impl<T> From<Mat4<T>> for Mat34<T> where T: Number {
fn from(other: Mat4<T>) -> Mat34<T> {
Mat34 {
m: [
other.m[0], other.m[1], other.m[2], other.m[3],
other.m[4], other.m[5], other.m[6], other.m[7],
other.m[8], other.m[9], other.m[10], other.m[11],
]
}
}
}
impl<T> From<(T, T, T, T, T, T, T, T, T, T, T, T)> for Mat34<T> where T: Number {
fn from(other: (T, T, T, T, T, T, T, T, T, T, T, T)) -> Mat34<T> {
Mat34 {
m: [
other.0, other.1, other.2, other.3,
other.4, other.5, other.6, other.7,
other.8, other.9, other.10, other.11
]
}
}
}
impl<T> From<(Vec4<T>, Vec4<T>, Vec4<T>)> for Mat34<T> where T: Number {
fn from(other: (Vec4<T>, Vec4<T>, Vec4<T>)) -> Mat34<T> {
Mat34 {
m: [
other.0.x, other.0.y, other.0.z, other.0.w,
other.1.x, other.1.y, other.1.z, other.1.w,
other.2.x, other.2.y, other.2.z, other.2.w,
]
}
}
}
impl<T> From<Mat2<T>> for Mat4<T> where T: Number {
fn from(other: Mat2<T>) -> Mat4<T> {
Mat4 {
m: [
other.m[0], other.m[1], T::zero(), T::zero(),
other.m[2], other.m[3], T::zero(), T::zero(),
T::zero(), T::zero(), T::one(), T::zero(),
T::zero(), T::zero(), T::zero(), T::one()
]
}
}
}
impl<T> From<Mat3<T>> for Mat4<T> where T: Number {
fn from(other: Mat3<T>) -> Mat4<T> {
Mat4 {
m: [
other.m[0], other.m[1], other.m[2], T::zero(),
other.m[3], other.m[4], other.m[5], T::zero(),
other.m[6], other.m[7], other.m[8], T::zero(),
T::zero(), T::zero(), T::zero(), T::one()
]
}
}
}
impl<T> From<Mat34<T>> for Mat4<T> where T: Number {
fn from(other: Mat34<T>) -> Mat4<T> {
Mat4 {
m: [
other.m[0], other.m[1], other.m[2], other.m[3],
other.m[4], other.m[5], other.m[6], other.m[7],
other.m[8], other.m[9], other.m[10], other.m[11],
T::zero(), T::zero(), T::zero(), T::one()
]
}
}
}
impl<T> From<(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T)> for Mat4<T> where T: Number {
fn from(other: (T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T)) -> Mat4<T> {
Mat4 {
m: [
other.0, other.1, other.2, other.3,
other.4, other.5, other.6, other.7,
other.8, other.9, other.10, other.11,
other.12, other.13, other.14, other.15
]
}
}
}
impl<T> From<(Vec4<T>, Vec4<T>, Vec4<T>, Vec4<T>)> for Mat4<T> where T: Number {
fn from(other: (Vec4<T>, Vec4<T>, Vec4<T>, Vec4<T>)) -> Mat4<T> {
Mat4 {
m: [
other.0.x, other.0.y, other.0.z, other.0.w,
other.1.x, other.1.y, other.1.z, other.1.w,
other.2.x, other.2.y, other.2.z, other.2.w,
other.3.x, other.3.y, other.3.z, other.3.w,
]
}
}
}
impl<T> From<Quat<T>> for Mat4<T> where T: Float + SignedNumber + FloatOps<T> + NumberOps<T> + SignedNumberOps<T> {
fn from(other: Quat<T>) -> Mat4<T> {
Mat4::from(other.get_matrix())
}
}
fn mul2x2<T: Number>(lhs: Mat2<T>, rhs: Mat2<T>) -> Mat2<T> {
Mat2 {
m: [
lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[2],
lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[3],
lhs.m[2] * rhs.m[0] + lhs.m[3] * rhs.m[2],
lhs.m[2] * rhs.m[1] + lhs.m[3] * rhs.m[3],
]
}
}
impl<T> Mul<Self> for Mat2<T> where T: Number {
type Output = Self;
fn mul(self, rhs: Mat2<T>) -> Self::Output {
mul2x2(self, rhs)
}
}
impl<T> MulAssign<Self> for Mat2<T> where T: Number {
fn mul_assign(&mut self, rhs: Mat2<T>) {
*self = mul2x2(*self, rhs);
}
}
impl<T> Mul<Vec2<T>> for Mat2<T> where T: Number {
type Output = Vec2<T>;
fn mul(self, rhs: Vec2<T>) -> Self::Output {
Vec2 {
x: self.m[0] * rhs.x + self.m[1] * rhs.y,
y: self.m[2] * rhs.x + self.m[3] * rhs.y
}
}
}
fn mul3x3<T: Number>(lhs: Mat3<T>, rhs: Mat3<T>) -> Mat3<T> {
Mat3 {
m: [
lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[3] + lhs.m[2] * rhs.m[6],
lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[4] + lhs.m[2] * rhs.m[7],
lhs.m[0] * rhs.m[2] + lhs.m[1] * rhs.m[5] + lhs.m[2] * rhs.m[8],
lhs.m[3] * rhs.m[0] + lhs.m[4] * rhs.m[3] + lhs.m[5] * rhs.m[6],
lhs.m[3] * rhs.m[1] + lhs.m[4] * rhs.m[4] + lhs.m[5] * rhs.m[7],
lhs.m[3] * rhs.m[2] + lhs.m[4] * rhs.m[5] + lhs.m[5] * rhs.m[8],
lhs.m[6] * rhs.m[0] + lhs.m[7] * rhs.m[3] + lhs.m[8] * rhs.m[6],
lhs.m[6] * rhs.m[1] + lhs.m[7] * rhs.m[4] + lhs.m[8] * rhs.m[7],
lhs.m[6] * rhs.m[2] + lhs.m[7] * rhs.m[5] + lhs.m[8] * rhs.m[8],
]
}
}
impl<T> Mul<Self> for Mat3<T> where T: Number {
type Output = Self;
fn mul(self, rhs: Mat3<T>) -> Self::Output {
mul3x3(self, rhs)
}
}
impl<T> MulAssign<Self> for Mat3<T> where T: Number {
fn mul_assign(&mut self, rhs: Mat3<T>) {
*self = mul3x3(*self, rhs);
}
}
impl<T> Mul<Vec3<T>> for Mat3<T> where T: Number {
type Output = Vec3<T>;
fn mul(self, rhs: Vec3<T>) -> Self::Output {
Vec3 {
x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z,
y: self.m[3] * rhs.x + self.m[4] * rhs.y + self.m[5] * rhs.z,
z: self.m[6] * rhs.x + self.m[7] * rhs.y + self.m[8] * rhs.z,
}
}
}
fn mul3x4<T: Number>(lhs: Mat34<T>, rhs: Mat34<T>) -> Mat34<T> {
Mat34 {
m: [
lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[4] + lhs.m[2] * rhs.m[8],
lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[5] + lhs.m[2] * rhs.m[9],
lhs.m[0] * rhs.m[2] + lhs.m[1] * rhs.m[6] + lhs.m[2] * rhs.m[10],
lhs.m[0] * rhs.m[3] + lhs.m[1] * rhs.m[7] + lhs.m[2] * rhs.m[11] + lhs.m[3],
lhs.m[4] * rhs.m[0] + lhs.m[5] * rhs.m[4] + lhs.m[6] * rhs.m[8],
lhs.m[4] * rhs.m[1] + lhs.m[5] * rhs.m[5] + lhs.m[6] * rhs.m[9],
lhs.m[4] * rhs.m[2] + lhs.m[5] * rhs.m[6] + lhs.m[6] * rhs.m[10],
lhs.m[4] * rhs.m[3] + lhs.m[5] * rhs.m[7] + lhs.m[6] * rhs.m[11] + lhs.m[7],
lhs.m[8] * rhs.m[0] + lhs.m[9] * rhs.m[4] + lhs.m[10] * rhs.m[8],
lhs.m[8] * rhs.m[1] + lhs.m[9] * rhs.m[5] + lhs.m[10] * rhs.m[9],
lhs.m[8] * rhs.m[2] + lhs.m[9] * rhs.m[6] + lhs.m[10] * rhs.m[10],
lhs.m[8] * rhs.m[3] + lhs.m[9] * rhs.m[7] + lhs.m[10] * rhs.m[11] + lhs.m[11],
]
}
}
impl<T> Mul<Self> for Mat34<T> where T: Number {
type Output = Self;
fn mul(self, rhs: Mat34<T>) -> Self::Output {
mul3x4(self, rhs)
}
}
impl<T> MulAssign<Self> for Mat34<T> where T: Number {
fn mul_assign(&mut self, rhs: Mat34<T>) {
*self = mul3x4(*self, rhs)
}
}
impl<T> Mul<Vec3<T>> for Mat34<T> where T: Number {
type Output = Vec3<T>;
fn mul(self, rhs: Vec3<T>) -> Self::Output {
Vec3 {
x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3],
y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7],
z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11]
}
}
}
impl<T> Mul<Vec4<T>> for Mat34<T> where T: Number {
type Output = Vec4<T>;
fn mul(self, rhs: Vec4<T>) -> Self::Output {
Vec4 {
x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3] * rhs.w,
y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7] * rhs.w,
z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] * rhs.w,
w: rhs.w,
}
}
}
fn mul4x4<T: Number>(lhs: Mat4<T>, rhs: Mat4<T>) -> Mat4<T> {
Mat4 {
m: [
lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[4] + lhs.m[2] * rhs.m[8] + lhs.m[3] * rhs.m[12],
lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[5] + lhs.m[2] * rhs.m[9] + lhs.m[3] * rhs.m[13],
lhs.m[0] * rhs.m[2] + lhs.m[1] * rhs.m[6] + lhs.m[2] * rhs.m[10] + lhs.m[3] * rhs.m[14],
lhs.m[0] * rhs.m[3] + lhs.m[1] * rhs.m[7] + lhs.m[2] * rhs.m[11] + lhs.m[3] * rhs.m[15],
lhs.m[4] * rhs.m[0] + lhs.m[5] * rhs.m[4] + lhs.m[6] * rhs.m[8] + lhs.m[7] * rhs.m[12],
lhs.m[4] * rhs.m[1] + lhs.m[5] * rhs.m[5] + lhs.m[6] * rhs.m[9] + lhs.m[7] * rhs.m[13],
lhs.m[4] * rhs.m[2] + lhs.m[5] * rhs.m[6] + lhs.m[6] * rhs.m[10] + lhs.m[7] * rhs.m[14],
lhs.m[4] * rhs.m[3] + lhs.m[5] * rhs.m[7] + lhs.m[6] * rhs.m[11] + lhs.m[7] * rhs.m[15],
lhs.m[8] * rhs.m[0] + lhs.m[9] * rhs.m[4] + lhs.m[10] * rhs.m[8] + lhs.m[11] * rhs.m[12],
lhs.m[8] * rhs.m[1] + lhs.m[9] * rhs.m[5] + lhs.m[10] * rhs.m[9] + lhs.m[11] * rhs.m[13],
lhs.m[8] * rhs.m[2] + lhs.m[9] * rhs.m[6] + lhs.m[10] * rhs.m[10] + lhs.m[11] * rhs.m[14],
lhs.m[8] * rhs.m[3] + lhs.m[9] * rhs.m[7] + lhs.m[10] * rhs.m[11] + lhs.m[11] * rhs.m[15],
lhs.m[12] * rhs.m[0] + lhs.m[13] * rhs.m[4] + lhs.m[14] * rhs.m[8] + lhs.m[15] * rhs.m[12],
lhs.m[12] * rhs.m[1] + lhs.m[13] * rhs.m[5] + lhs.m[14] * rhs.m[9] + lhs.m[15] * rhs.m[13],
lhs.m[12] * rhs.m[2] + lhs.m[13] * rhs.m[6] + lhs.m[14] * rhs.m[10] + lhs.m[15] * rhs.m[14],
lhs.m[12] * rhs.m[3] + lhs.m[13] * rhs.m[7] + lhs.m[14] * rhs.m[11] + lhs.m[15] * rhs.m[15],
]
}
}
impl<T> Mul<Self> for Mat4<T> where T: Number {
type Output = Self;
fn mul(self, rhs: Mat4<T>) -> Self::Output {
mul4x4(self, rhs)
}
}
impl<T> MulAssign<Self> for Mat4<T> where T: Number {
fn mul_assign(&mut self, rhs: Mat4<T>) {
*self = mul4x4(*self, rhs);
}
}
impl<T> Mul<Vec4<T>> for Mat4<T> where T: Number {
type Output = Vec4<T>;
fn mul(self, rhs: Vec4<T>) -> Self::Output {
Vec4 {
x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3] * rhs.w,
y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7] * rhs.w,
z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] * rhs.w,
w: self.m[12] * rhs.x + self.m[13] * rhs.y + self.m[14] * rhs.z + self.m[15] * rhs.w,
}
}
}
impl<T> Mul<Vec3<T>> for Mat4<T> where T: Number {
type Output = Vec3<T>;
fn mul(self, rhs: Vec3<T>) -> Self::Output {
let w = self.m[12] * rhs.x + self.m[13] * rhs.y + self.m[14] * rhs.z + self.m[15];
Vec3 {
x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3],
y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7],
z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11],
} / w
}
}
fn mul3x4_4x4<T: Number>(lhs: Mat34<T>, rhs: Mat4<T>) -> Mat4<T> {
Mat4 {
m: [
lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[4] + lhs.m[2] * rhs.m[8] + lhs.m[3] * rhs.m[12],
lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[5] + lhs.m[2] * rhs.m[9] + lhs.m[3] * rhs.m[13],
lhs.m[0] * rhs.m[2] + lhs.m[1] * rhs.m[6] + lhs.m[2] * rhs.m[10] + lhs.m[3] * rhs.m[14],
lhs.m[0] * rhs.m[3] + lhs.m[1] * rhs.m[7] + lhs.m[2] * rhs.m[11] + lhs.m[3] * rhs.m[15],
lhs.m[4] * rhs.m[0] + lhs.m[5] * rhs.m[4] + lhs.m[6] * rhs.m[8] + lhs.m[7] * rhs.m[12],
lhs.m[4] * rhs.m[1] + lhs.m[5] * rhs.m[5] + lhs.m[6] * rhs.m[9] + lhs.m[7] * rhs.m[13],
lhs.m[4] * rhs.m[2] + lhs.m[5] * rhs.m[6] + lhs.m[6] * rhs.m[10] + lhs.m[7] * rhs.m[14],
lhs.m[4] * rhs.m[3] + lhs.m[5] * rhs.m[7] + lhs.m[6] * rhs.m[11] + lhs.m[7] * rhs.m[15],
lhs.m[8] * rhs.m[0] + lhs.m[9] * rhs.m[4] + lhs.m[10] * rhs.m[8] + lhs.m[11] * rhs.m[12],
lhs.m[8] * rhs.m[1] + lhs.m[9] * rhs.m[5] + lhs.m[10] * rhs.m[9] + lhs.m[11] * rhs.m[13],
lhs.m[8] * rhs.m[2] + lhs.m[9] * rhs.m[6] + lhs.m[10] * rhs.m[10] + lhs.m[11] * rhs.m[14],
lhs.m[8] * rhs.m[3] + lhs.m[9] * rhs.m[7] + lhs.m[10] * rhs.m[11] + lhs.m[11] * rhs.m[15],
rhs.m[12],
rhs.m[13],
rhs.m[14],
rhs.m[15],
]
}
}
impl<T> Mul<Mat4<T>> for Mat34<T> where T: Number {
type Output = Mat4<T>;
fn mul(self, rhs: Mat4<T>) -> Self::Output {
mul3x4_4x4(self, rhs)
}
}
fn mul4x4_3x4<T: Number>(lhs: Mat4<T>, rhs: Mat34<T>) -> Mat4<T> {
Mat4 {
m: [
lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[4] + lhs.m[2] * rhs.m[8],
lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[5] + lhs.m[2] * rhs.m[9],
lhs.m[0] * rhs.m[2] + lhs.m[1] * rhs.m[6] + lhs.m[2] * rhs.m[10],
lhs.m[0] * rhs.m[3] + lhs.m[1] * rhs.m[7] + lhs.m[2] * rhs.m[11] + lhs.m[3],
lhs.m[4] * rhs.m[0] + lhs.m[5] * rhs.m[4] + lhs.m[6] * rhs.m[8],
lhs.m[4] * rhs.m[1] + lhs.m[5] * rhs.m[5] + lhs.m[6] * rhs.m[9],
lhs.m[4] * rhs.m[2] + lhs.m[5] * rhs.m[6] + lhs.m[6] * rhs.m[10],
lhs.m[4] * rhs.m[3] + lhs.m[5] * rhs.m[7] + lhs.m[6] * rhs.m[11] + lhs.m[7],
lhs.m[8] * rhs.m[0] + lhs.m[9] * rhs.m[4] + lhs.m[10] * rhs.m[8],
lhs.m[8] * rhs.m[1] + lhs.m[9] * rhs.m[5] + lhs.m[10] * rhs.m[9],
lhs.m[8] * rhs.m[2] + lhs.m[9] * rhs.m[6] + lhs.m[10] * rhs.m[10],
lhs.m[8] * rhs.m[3] + lhs.m[9] * rhs.m[7] + lhs.m[10] * rhs.m[11] + lhs.m[11],
lhs.m[12] * rhs.m[0] + lhs.m[10] * rhs.m[4] + lhs.m[14] * rhs.m[8],
lhs.m[12] * rhs.m[1] + lhs.m[10] * rhs.m[5] + lhs.m[14] * rhs.m[9],
lhs.m[12] * rhs.m[2] + lhs.m[10] * rhs.m[6] + lhs.m[14] * rhs.m[10],
lhs.m[12] * rhs.m[3] + lhs.m[10] * rhs.m[7] + lhs.m[14] * rhs.m[11] + lhs.m[15],
]
}
}
impl<T> Mul<Mat34<T>> for Mat4<T> where T: Number {
type Output = Self;
fn mul(self, rhs: Mat34<T>) -> Self::Output {
mul4x4_3x4(self, rhs)
}
}
impl<T> MulAssign<Mat34<T>> for Mat4<T> where T: Number {
fn mul_assign(&mut self, rhs: Mat34<T>) {
*self = mul4x4_3x4(*self, rhs)
}
}
pub trait MatN<T: Number, V: VecN<T>>:
Sized + Display + Copy + Clone +
Mul<V, Output=V> + Mul<Self, Output=Self> + MulAssign<Self> +
{
}
impl<T> MatN<T, Vec2<T>> for Mat2<T> where T: Number {}
impl<T> MatN<T, Vec3<T>> for Mat3<T> where T: Number {}
impl<T> MatN<T, Vec3<T>> for Mat34<T> where T: Number {}
impl<T> MatN<T, Vec4<T>> for Mat4<T> where T: Number {}
impl<T> MatN<T, Vec3<T>> for Mat4<T> where T: Number {}
pub trait MatTranslate<V> {
fn from_translation(t: V) -> Self;
}
impl<T> MatTranslate<Vec3<T>> for Mat4<T> where T: Number {
fn from_translation(t: Vec3<T>) -> Self {
let mut m = Mat4::identity();
m.set_column(3, Vec4::from(t));
m.m[15] = T::one();
m
}
}
impl<T> MatTranslate<Vec3<T>> for Mat34<T> where T: Number {
fn from_translation(t: Vec3<T>) -> Self {
let mut m = Mat34::identity();
m.set_column(3, t);
m
}
}
pub trait MatScale<V> {
fn from_scale(t: V) -> Self;
}
impl<T> MatScale<Vec3<T>> for Mat4<T> where T: Number {
fn from_scale(t: Vec3<T>) -> Self {
let mut m = Mat4::identity();
m.set(0, 0, t.x);
m.set(1, 1, t.y);
m.set(2, 2, t.z);
m
}
}
impl<T> MatScale<Vec3<T>> for Mat34<T> where T: Number {
fn from_scale(t: Vec3<T>) -> Self {
let mut m = Mat34::identity();
m.set(0, 0, t.x);
m.set(1, 1, t.y);
m.set(2, 2, t.z);
m
}
}
impl<T> MatScale<Vec3<T>> for Mat3<T> where T: Number {
fn from_scale(t: Vec3<T>) -> Self {
let mut m = Mat3::identity();
m.set(0, 0, t.x);
m.set(1, 1, t.y);
m.set(2, 2, t.z);
m
}
}
impl<T> MatScale<Vec2<T>> for Mat2<T> where T: Number {
fn from_scale(t: Vec2<T>) -> Self {
let mut m = Mat2::identity();
m.set(0, 0, t.x);
m.set(1, 1, t.y);
m
}
}
pub trait MatRotate2D<T> {
fn from_z_rotation(theta: T) -> Self;
}
impl<T> MatRotate2D<T> for Mat2<T> where T: Float + FloatOps<T> {
fn from_z_rotation(theta: T) -> Self {
let mut m = Mat2::identity();
let cos_theta = T::cos(theta);
let sin_theta = T::sin(theta);
m.set(0, 0, cos_theta);
m.set(0, 1, -sin_theta);
m.set(1, 0, sin_theta);
m.set(1, 1, cos_theta);
m
}
}
impl<T> MatRotate2D<T> for Mat3<T> where T: Float + FloatOps<T> {
fn from_z_rotation(theta: T) -> Self {
let mut m = Mat3::identity();
let cos_theta = T::cos(theta);
let sin_theta = T::sin(theta);
m.set(0, 0, cos_theta);
m.set(0, 1, -sin_theta);
m.set(1, 0, sin_theta);
m.set(1, 1, cos_theta);
m
}
}
impl<T> MatRotate2D<T> for Mat4<T> where T: Float + FloatOps<T> {
fn from_z_rotation(theta: T) -> Self {
let mut m = Mat4::identity();
let cos_theta = T::cos(theta);
let sin_theta = T::sin(theta);
m.set(0, 0, cos_theta);
m.set(0, 1, -sin_theta);
m.set(1, 0, sin_theta);
m.set(1, 1, cos_theta);
m
}
}
impl<T> MatRotate2D<T> for Mat34<T> where T: Float + FloatOps<T> {
fn from_z_rotation(theta: T) -> Self {
let mut m = Mat34::identity();
let cos_theta = T::cos(theta);
let sin_theta = T::sin(theta);
m.set(0, 0, cos_theta);
m.set(0, 1, -sin_theta);
m.set(1, 0, sin_theta);
m.set(1, 1, cos_theta);
m
}
}
pub fn get_orthonormal_basis_hughes_moeller<T: Float + SignedNumberOps<T> + FloatOps<T>>(n: Vec3<T>) -> (Vec3<T>, Vec3<T>) {
let b2 = if T::abs(n.x) > T::abs(n.z) {
Vec3::new(-n.y, n.x, T::zero())
}
else {
Vec3::new(T::zero(), -n.z, n.y)
};
let b2 = b2 * T::rsqrt(Vec3::dot(b2, b2));
let b1 = Vec3::cross(b2, n);
(b1, b2)
}
pub fn get_orthonormal_basis_frisvad<T: Float + SignedNumberOps<T> + FloatOps<T> + From<f64>>(n: Vec3<T>) -> (Vec3<T>, Vec3<T>) {
let epsilon = T::from(-0.99999999);
if n.z < epsilon {
(-Vec3::unit_y(), -Vec3::unit_x())
}
else {
let a = T::one()/(T::one() + n.z);
let b = -n.x * n.y * a;
(Vec3::new(T::one() - n.x * n.x * a, b, -n.x), Vec3::new(b, T::one() - n.y * n.y * a, -n.y))
}
}
pub trait MatRotate3D<T, V> {
fn from_x_rotation(theta: T) -> Self;
fn from_y_rotation(theta: T) -> Self;
fn from_rotation(axis: V, theta: T) -> Self;
fn from_orthonormal_basis(normal: Vec3<T>) -> Self;
}
impl<T> MatRotate3D<T, Vec3<T>> for Mat3<T> where T: Float + FloatOps<T> + SignedNumberOps<T> {
fn from_x_rotation(theta: T) -> Self {
let mut m = Mat3::identity();
let cos_theta = T::cos(theta);
let sin_theta = T::sin(theta);
m.set(1, 1, cos_theta);
m.set(1, 2, -sin_theta);
m.set(2, 1, sin_theta);
m.set(2, 2, cos_theta);
m
}
fn from_y_rotation(theta: T) -> Self {
let mut m = Mat3::identity();
let cos_theta = T::cos(theta);
let sin_theta = T::sin(theta);
m.set(0, 0, cos_theta);
m.set(0, 2, sin_theta);
m.set(2, 0, -sin_theta);
m.set(2, 2, cos_theta);
m
}
fn from_rotation(axis: Vec3<T>, theta: T) -> Self {
let cos_theta = T::cos(theta);
let sin_theta = T::sin(theta);
let inv_cos_theta = T::one() - cos_theta;
Mat3::from((
Vec3::new(
inv_cos_theta * axis.x * axis.x + cos_theta,
inv_cos_theta * axis.x * axis.y - sin_theta * axis.z,
inv_cos_theta * axis.x * axis.z + sin_theta * axis.y
),
Vec3::new(
inv_cos_theta * axis.x * axis.y + sin_theta * axis.z,
inv_cos_theta * axis.y * axis.y + cos_theta,
inv_cos_theta * axis.y * axis.z - sin_theta * axis.x
),
Vec3::new(
inv_cos_theta * axis.x * axis.z - sin_theta * axis.y,
inv_cos_theta * axis.y * axis.z + sin_theta * axis.x,
inv_cos_theta * axis.z * axis.z + cos_theta
)
))
}
fn from_orthonormal_basis(normal: Vec3<T>) -> Self {
let (b1, b2) = get_orthonormal_basis_hughes_moeller(normal);
Mat3::from((
b1,
normal,
b2
))
}
}
impl<T> MatRotate3D<T, Vec3<T>> for Mat34<T> where T: Float + FloatOps<T> + SignedNumberOps<T> {
fn from_x_rotation(theta: T) -> Self {
Mat34::from(Mat3::from_x_rotation(theta))
}
fn from_y_rotation(theta: T) -> Self {
Mat34::from(Mat3::from_y_rotation(theta))
}
fn from_rotation(axis: Vec3<T>, theta: T) -> Self {
Mat34::from(Mat3::from_rotation(axis, theta))
}
fn from_orthonormal_basis(normal: Vec3<T>) -> Self {
Mat34::from(Mat3::from_orthonormal_basis(normal))
}
}
impl<T> MatRotate3D<T, Vec3<T>> for Mat4<T> where T: Float + FloatOps<T> + SignedNumberOps<T> {
fn from_x_rotation(theta: T) -> Self {
Mat4::from(Mat3::from_x_rotation(theta))
}
fn from_y_rotation(theta: T) -> Self {
Mat4::from(Mat3::from_y_rotation(theta))
}
fn from_rotation(axis: Vec3<T>, theta: T) -> Self {
Mat4::from(Mat3::from_rotation(axis, theta))
}
fn from_orthonormal_basis(normal: Vec3<T>) -> Self {
Mat4::from(Mat3::from_orthonormal_basis(normal))
}
}
pub trait MatDeterminant<T> {
fn determinant(&self) -> T;
}
impl<T> MatDeterminant<T> for Mat2<T> where T: Number {
fn determinant(&self) -> T {
self.m[0] * self.m[3] - self.m[1] * self.m[2]
}
}
impl<T> MatDeterminant<T> for Mat3<T> where T: Number {
fn determinant(&self) -> T {
self.m[0] * (self.m[4] * self.m[8] - self.m[5] * self.m[7]) -
self.m[1] * (self.m[3] * self.m[8] - self.m[5] * self.m[6]) +
self.m[2] * (self.m[3] * self.m[7] - self.m[4] * self.m[6])
}
}
#[allow(clippy::zero_prefixed_literal)]
impl<T> MatDeterminant<T> for Mat4<T> where T: Number {
fn determinant(&self) -> T {
let s0 = (self.m[00] * self.m[05]) - (self.m[01] * self.m[04]);
let s1 = (self.m[00] * self.m[06]) - (self.m[02] * self.m[04]);
let s2 = (self.m[00] * self.m[07]) - (self.m[03] * self.m[04]);
let s3 = (self.m[01] * self.m[06]) - (self.m[02] * self.m[05]);
let s4 = (self.m[01] * self.m[07]) - (self.m[03] * self.m[05]);
let s5 = (self.m[02] * self.m[07]) - (self.m[03] * self.m[06]);
let c5 = (self.m[10] * self.m[15]) - (self.m[11] * self.m[14]);
let c4 = (self.m[09] * self.m[15]) - (self.m[11] * self.m[13]);
let c3 = (self.m[09] * self.m[14]) - (self.m[10] * self.m[13]);
let c2 = (self.m[08] * self.m[15]) - (self.m[11] * self.m[12]);
let c1 = (self.m[08] * self.m[14]) - (self.m[10] * self.m[12]);
let c0 = (self.m[08] * self.m[13]) - (self.m[09] * self.m[12]);
(s0 * c5) - (s1 * c4) + (s2 * c3) + (s3 * c2) - (s4 * c1) + (s5 * c0)
}
}
pub trait MatInverse<T> {
fn inverse(&self) -> Self;
}
impl<T> MatInverse<T> for Mat2<T> where T: SignedNumber {
fn inverse(&self) -> Self {
let det = self.determinant();
let inv_det = T::one()/det;
Mat2 {
m: [
inv_det * self.m[3], inv_det * -self.m[1],
inv_det * -self.m[2], inv_det * self.m[0],
]
}
}
}
impl<T> MatInverse<T> for Mat3<T> where T: SignedNumber {
fn inverse(&self) -> Self {
let det = self.determinant();
let inv_det = T::one() / det;
Mat3 {
m: [
(self.m[4] * self.m[8] - self.m[5] * self.m[7]) * inv_det,
-(self.m[1] * self.m[8] - self.m[2] * self.m[7]) * inv_det,
(self.m[1] * self.m[5] - self.m[2] * self.m[4]) * inv_det,
-(self.m[3] * self.m[8] - self.m[5] * self.m[6]) * inv_det,
(self.m[0] * self.m[8] - self.m[2] * self.m[6]) * inv_det,
-(self.m[0] * self.m[5] - self.m[2] * self.m[3]) * inv_det,
(self.m[3] * self.m[7] - self.m[4] * self.m[6]) * inv_det,
-(self.m[0] * self.m[7] - self.m[1] * self.m[6]) * inv_det,
(self.m[0] * self.m[4] - self.m[1] * self.m[3]) * inv_det
]
}
}
}
impl<T> MatInverse<T> for Mat34<T> where T: SignedNumber {
fn inverse(&self) -> Self {
let m3_inv = Mat3::<T>::from(*self).inverse();
let mut m34 = Mat34::<T>::from(m3_inv);
let t = Vec3::<T>::from((-self.m[3], -self.m[7], -self.m[11]));
let inv_t = Vec3::<T> {
x: t.x * m3_inv.m[0] + t.y * m3_inv.m[1] + t.z * m3_inv.m[2],
y: t.x * m3_inv.m[3] + t.y * m3_inv.m[4] + t.z * m3_inv.m[5],
z: t.x * m3_inv.m[6] + t.y * m3_inv.m[7] + t.z * m3_inv.m[8],
};
m34.set_column(3, inv_t);
m34
}
}
#[allow(clippy::zero_prefixed_literal)]
impl<T> MatInverse<T> for Mat4<T> where T: SignedNumber {
fn inverse(&self) -> Self {
let s0 = (self.m[00] * self.m[05]) - (self.m[01] * self.m[04]);
let s1 = (self.m[00] * self.m[06]) - (self.m[02] * self.m[04]);
let s2 = (self.m[00] * self.m[07]) - (self.m[03] * self.m[04]);
let s3 = (self.m[01] * self.m[06]) - (self.m[02] * self.m[05]);
let s4 = (self.m[01] * self.m[07]) - (self.m[03] * self.m[05]);
let s5 = (self.m[02] * self.m[07]) - (self.m[03] * self.m[06]);
let c5 = (self.m[10] * self.m[15]) - (self.m[11] * self.m[14]);
let c4 = (self.m[09] * self.m[15]) - (self.m[11] * self.m[13]);
let c3 = (self.m[09] * self.m[14]) - (self.m[10] * self.m[13]);
let c2 = (self.m[08] * self.m[15]) - (self.m[11] * self.m[12]);
let c1 = (self.m[08] * self.m[14]) - (self.m[10] * self.m[12]);
let c0 = (self.m[08] * self.m[13]) - (self.m[09] * self.m[12]);
let det = (s0 * c5) - (s1 * c4) + (s2 * c3) + (s3 * c2) - (s4 * c1) + (s5 * c0);
let inv_det = T::one() / det;
Mat4 {
m: [
(self.m[5] * c5 - self.m[6] * c4 + self.m[7] * c3) * inv_det,
-(self.m[1] * c5 - self.m[2] * c4 + self.m[3] * c3) * inv_det,
(self.m[13] * s5 - self.m[14] * s4 + self.m[15] * s3) * inv_det,
-(self.m[9] * s5 - self.m[10] * s4 + self.m[11] * s3) * inv_det,
-(self.m[4] * c5 - self.m[6] * c2 + self.m[7] * c1) * inv_det,
(self.m[0] * c5 - self.m[2] * c2 + self.m[3] * c1) * inv_det,
-(self.m[12] * s5 - self.m[14] * s2 + self.m[15] * s1) * inv_det,
(self.m[8] * s5 - self.m[10] * s2 + self.m[11] * s1) * inv_det,
(self.m[4] * c4 - self.m[5] * c2 + self.m[7] * c0) * inv_det,
-(self.m[0] * c4 - self.m[1] * c2 + self.m[3] * c0) * inv_det,
(self.m[12] * s4 - self.m[13] * s2 + self.m[15] * s0) * inv_det,
-(self.m[8] * s4 - self.m[9] * s2 + self.m[11] * s0) * inv_det,
-(self.m[4] * c3 - self.m[5] * c1 + self.m[6] * c0) * inv_det,
(self.m[0] * c3 - self.m[1] * c1 + self.m[2] * c0) * inv_det,
-(self.m[12] * s3 - self.m[13] * s1 + self.m[14] * s0) * inv_det,
(self.m[8] * s3 - self.m[9] * s1 + self.m[10] * s0) * inv_det,
]
}
}
}
pub trait MatProjection<T> {
fn get_frustum_planes(&self) -> [Vec4<T>; 6];
fn get_frustum_corners(&self) -> [Vec3<T>; 8];
fn create_ortho_matrix(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Self;
fn create_perspective_projection_lh_yup(fov: T, aspect: T, near: T, far: T) -> Self;
fn create_perspective_projection_rh_yup(fov: T, aspect: T, near: T, far: T) -> Self;
}
fn plane_from_vectors<T: Float + FloatOps<T>>(plane_vectors: &[Vec3<T>; 18], offset: usize) -> Vec4<T> {
let v1 = super::normalize(plane_vectors[offset + 1] - plane_vectors[offset]);
let v2 = super::normalize(plane_vectors[offset + 2] - plane_vectors[offset]);
let pn = super::cross(v1, v2);
let pd = super::plane_distance(plane_vectors[offset], pn);
Vec4::from((pn, pd))
}
fn create_perspective_matrix_internal_lh<T: Float + FloatOps<T>>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
Mat4::from((
Vec4::new((T::two() * near) / (right - left), T::zero(), (right + left) / (right - left), T::zero()),
Vec4::new(T::zero(), (T::two() * near) / (top - bottom), (top + bottom) / (top - bottom), T::zero()),
Vec4::new(T::zero(), T::zero(), (-far - near) / (far - near), (-(T::two() * near) * far) / (far - near)),
Vec4::new(T::zero(), T::zero(), T::minus_one(), T::zero())
))
}
fn create_perspective_matrix_internal_rh<T: Float + FloatOps<T>>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
Mat4::from((
Vec4::new((T::two() * near) / (right - left), T::zero(), (right + left) / (right - left), T::zero()),
Vec4::new(T::zero(), (T::two() * near) / (top - bottom), (top + bottom) / (top - bottom), T::zero()),
Vec4::new(T::zero(), T::zero(), (-far - near) / (far - near), (-(T::two() * near) * far) / (far - near)),
Vec4::new(T::zero(), T::zero(), T::one(), T::zero())
))
}
impl<T> MatProjection<T> for Mat4<T> where T: Float + FloatOps<T>, Vec3<T>: FloatOps<T> {
fn get_frustum_planes(&self) -> [Vec4<T>; 6] {
let ndc_coords = [
Vec2::<T>::new(T::zero(), T::one()),
Vec2::<T>::new(T::one(), T::one()),
Vec2::<T>::new(T::zero(), T::zero()),
Vec2::<T>::new(T::one(), T::zero()),
];
let corners = [[
super::unproject_sc(Vec3::from((ndc_coords[0], T::zero())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[1], T::zero())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[2], T::zero())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[3], T::zero())), *self, Vec2::one()),
],
[
super::unproject_sc(Vec3::from((ndc_coords[0], T::one())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[1], T::one())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[2], T::one())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[3], T::one())), *self, Vec2::one()),
]];
let plane_vectors = [
corners[0][0], corners[1][0], corners[0][2], corners[0][0], corners[0][1], corners[1][0], corners[0][1], corners[0][3], corners[1][1], corners[0][2], corners[1][2], corners[0][3], corners[0][0], corners[0][2], corners[0][1], corners[1][0], corners[1][1], corners[1][2] ];
[
plane_from_vectors(&plane_vectors, 0),
plane_from_vectors(&plane_vectors, 3),
plane_from_vectors(&plane_vectors, 6),
plane_from_vectors(&plane_vectors, 9),
plane_from_vectors(&plane_vectors, 12),
plane_from_vectors(&plane_vectors, 15),
]
}
fn get_frustum_corners(&self) -> [Vec3<T>; 8] {
let ndc_coords = [
Vec2::<T>::new(T::zero(), T::one()),
Vec2::<T>::new(T::one(), T::one()),
Vec2::<T>::new(T::zero(), T::zero()),
Vec2::<T>::new(T::one(), T::zero()),
];
[
super::unproject_sc(Vec3::from((ndc_coords[0], T::zero())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[1], T::zero())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[2], T::zero())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[3], T::zero())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[0], T::one())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[1], T::one())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[2], T::one())), *self, Vec2::one()),
super::unproject_sc(Vec3::from((ndc_coords[3], T::one())), *self, Vec2::one()),
]
}
fn create_ortho_matrix(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
Mat4::from((
Vec4::new(T::two() / (right - left), T::zero(), T::zero(), T::zero()),
Vec4::new(T::zero(), T::two() / (top - bottom), T::zero(), T::zero()),
Vec4::new(T::zero(), T::zero(), T::one() / (near - far), T::zero()),
Vec4::new((right + left) / (left - right), (top + bottom) / (bottom - top), near / (near - far), T::one()),
))
}
fn create_perspective_projection_lh_yup(fov: T, aspect: T, near: T, far: T) -> Mat4<T> {
let tfov = T::tan(fov * T::point_five());
let right = tfov * aspect * near;
let left = -right;
let top = tfov * near;
let bottom = -top;
create_perspective_matrix_internal_lh(left, right, bottom, top, near, far)
}
fn create_perspective_projection_rh_yup(fov: T, aspect: T, near: T, far: T) -> Mat4<T> {
let tfov = T::tan(fov * T::point_five());
let right = tfov * aspect * near;
let left = -right;
let top = tfov * near;
let bottom = -top;
create_perspective_matrix_internal_rh(left, right, bottom, top, near, far)
}
}
pub trait MatNew2<T> {
fn new(
m00: T, m01: T,
m10: T, m11: T
) -> Self;
}
impl<T> MatNew2<T> for Mat2<T> where T: Number {
fn new(
m00: T, m01: T,
m10: T, m11: T
) -> Self {
Self {
m: [
m00, m01,
m10, m11
]
}
}
}
#[allow(clippy::too_many_arguments)]
pub trait MatNew3<T> {
fn new(
m00: T, m01: T, m02: T,
m10: T, m11: T, m12: T,
m20: T, m21: T, m22: T,
) -> Self;
}
impl<T> MatNew3<T> for Mat3<T> where T: Number {
fn new(
m00: T, m01: T, m02: T,
m10: T, m11: T, m12: T,
m20: T, m21: T, m22: T,
) -> Self {
Self {
m: [
m00, m01, m02,
m10, m11, m12,
m20, m21, m22,
]
}
}
}
#[allow(clippy::too_many_arguments)]
pub trait MatNew34<T> {
fn new(
m00: T, m01: T, m02: T, m03: T,
m10: T, m11: T, m12: T, m13: T,
m20: T, m21: T, m22: T, m23: T,
) -> Self;
}
impl<T> MatNew34<T> for Mat34<T> where T: Number {
fn new(
m00: T, m01: T, m02: T, m03: T,
m10: T, m11: T, m12: T, m13: T,
m20: T, m21: T, m22: T, m23: T,
) -> Self {
Self {
m: [
m00, m01, m02, m03,
m10, m11, m12, m13,
m20, m21, m22, m23
]
}
}
}
#[allow(clippy::too_many_arguments)]
pub trait MatNew4<T> {
fn new(
m00: T, m01: T, m02: T, m03: T,
m10: T, m11: T, m12: T, m13: T,
m20: T, m21: T, m22: T, m23: T,
m30: T, m31: T, m32: T, m33: T,
) -> Self;
}
impl<T> MatNew4<T> for Mat4<T> where T: Number {
fn new(
m00: T, m01: T, m02: T, m03: T,
m10: T, m11: T, m12: T, m13: T,
m20: T, m21: T, m22: T, m23: T,
m30: T, m31: T, m32: T, m33: T,
) -> Self {
Self {
m: [
m00, m01, m02, m03,
m10, m11, m12, m13,
m20, m21, m22, m23,
m30, m31, m32, m33
]
}
}
}
mat_impl!(Mat2, 2, 2, 4, Vec2 {x, 0, y, 1}, Vec2 {x, 0, y, 1});
mat_impl!(Mat3, 3, 3, 9, Vec3 {x, 0, y, 1, z, 2}, Vec3 {x, 0, y, 1, z, 2});
mat_impl!(Mat4, 4, 4, 16, Vec4 {x, 0, y, 1, z, 2, w, 3}, Vec4 {x, 0, y, 1, z, 2, w, 3});
mat_impl!(Mat34, 3, 4, 12, Vec4 {x, 0, y, 1, z, 2, w, 3}, Vec3 {x, 0, y, 1, z, 2});