use crate::{scalar, Matrix};
use num::traits::NumAssign;
pub type Vector<T, const R: usize> = Matrix<T, R, 1>;
pub type Vec2<T = f32> = Vector<T, 2>;
pub type Vec3<T = f32> = Vector<T, 3>;
pub type Vec4<T = f32> = Vector<T, 4>;
pub type Mat2<T = f32> = Matrix<T, 2, 2>;
pub type Mat3<T = f32> = Matrix<T, 3, 3>;
pub type Mat4<T = f32> = Matrix<T, 4, 4>;
impl<T: Copy + NumAssign, const R: usize> Vector<T, R> {
pub fn from_array(arr: [T; R]) -> Self {
Self([arr])
}
}
#[inline]
pub fn vec2<T: Copy + NumAssign>(x: T, y: T) -> Vec2<T> {
Vec2::new([[x, y]])
}
#[inline]
pub fn vec3<T: Copy + NumAssign>(x: T, y: T, z: T) -> Vec3<T> {
Vec3::new([[x, y, z]])
}
#[inline]
pub fn vec4<T: Copy + NumAssign>(x: T, y: T, z: T, w: T) -> Vec4<T> {
Vec4::new([[x, y, z, w]])
}
#[inline]
pub fn mat2<T: Copy + NumAssign>() -> Mat2<T> {
Mat2::identity()
}
#[inline]
pub fn mat3<T: Copy + NumAssign>() -> Mat3<T> {
Mat3::identity()
}
#[inline]
pub fn mat4<T: Copy + NumAssign>() -> Mat4<T> {
Mat4::identity()
}
impl<T: Copy + NumAssign, const R: usize> From<[T; R]> for Vector<T, R> {
#[inline]
fn from(data: [T; R]) -> Self {
Self::from_array(data)
}
}
impl<T: Copy + NumAssign, const R: usize> From<Vector<T, R>> for [T; R] {
#[inline]
fn from(v: Vector<T, R>) -> Self {
v.0[0]
}
}
impl<T: Copy + NumAssign> From<Vec2<T>> for Vec3<T> {
fn from(v: Vec2<T>) -> Self {
Vec3::new([[v[0], v[1], T::one()]])
}
}
impl<T: Copy + NumAssign> From<Vec3<T>> for Vec2<T> {
fn from(v: Vec3<T>) -> Self {
Vec2::new([[v[0], v[1]]])
}
}
impl<T: Copy + NumAssign> From<Vec3<T>> for Vec4<T> {
fn from(v: Vec3<T>) -> Self {
Vec4::new([[v[0], v[1], v[2], T::one()]])
}
}
impl<T: Copy + NumAssign> From<Vec4<T>> for Vec3<T> {
fn from(v: Vec4<T>) -> Self {
Vec3::new([[v[0], v[1], v[2]]])
}
}
impl<T: Copy + NumAssign> From<Mat2<T>> for Mat3<T> {
fn from(m: Mat2<T>) -> Self {
let mut m3 = Self::identity();
for c in 0..2 {
for r in 0..2 {
m3[(r, c)] = m[(r, c)];
}
}
m3
}
}
impl<T: Copy + NumAssign> From<Mat3<T>> for Mat2<T> {
fn from(m: Mat3<T>) -> Self {
let mut m2 = Self::default();
for c in 0..2 {
for r in 0..2 {
m2[(r, c)] = m[(r, c)];
}
}
m2
}
}
impl<T: Copy + NumAssign> From<Mat3<T>> for Mat4<T> {
fn from(m: Mat3<T>) -> Self {
let mut m4 = Self::identity();
for c in 0..3 {
for r in 0..3 {
m4[(r, c)] = m[(r, c)];
}
}
m4
}
}
impl<T: Copy + NumAssign> From<Mat4<T>> for Mat3<T> {
fn from(m: Mat4<T>) -> Self {
let mut m3 = Self::default();
for c in 0..3 {
for r in 0..3 {
m3[(r, c)] = m[(r, c)];
}
}
m3
}
}
impl<T: Copy + NumAssign> Vec3<T> {
#[inline]
pub fn from_vec2(v: Vec2<T>, z: T) -> Self {
Vec3::new([[v.0[0][0], v.0[0][1], z]])
}
#[inline]
pub fn xy(&self) -> Vec2<T> {
Vec2::new([[self.0[0][0], self.0[0][1]]])
}
}
impl<T: Copy + NumAssign> Vec4<T> {
#[inline]
pub fn from_vec3(v: Vec3<T>, w: T) -> Self {
Vec4::new([[v.0[0][0], v.0[0][1], v.0[0][2], w]])
}
#[inline]
pub fn xy(&self) -> Vec2<T> {
Vec2::new([[self.0[0][0], self.0[0][1]]])
}
#[inline]
pub fn xyz(&self) -> Vec3<T> {
Vec3::new([[self.0[0][0], self.0[0][1], self.0[0][2]]])
}
}
impl<T: Copy + NumAssign> Vec3<T> {
pub fn cross(&self, rhs: Self) -> Self {
let x = self.0[0][1] * rhs.0[0][2] - rhs.0[0][1] * self.0[0][2];
let y = self.0[0][2] * rhs.0[0][0] - rhs.0[0][2] * self.0[0][0];
let z = self.0[0][0] * rhs.0[0][1] - rhs.0[0][0] * self.0[0][1];
Self::new([[x, y, z]])
}
}
impl<T: Copy + NumAssign> Mat2<T> {
pub fn det(&self) -> T {
self.0[0][0] * self.0[1][1] - self.0[1][0] * self.0[0][1]
}
pub fn invert(&mut self) -> bool {
let det = self.det();
if det == T::zero() {
false
} else {
let neg = scalar::neg();
let (m0, m1, m2, m3) = (
self.0[1][1] / det,
self.0[0][1] * neg / det,
self.0[1][0] * neg / det,
self.0[0][0] / det,
);
self.0[0][0] = m0;
self.0[0][1] = m1;
self.0[1][0] = m2;
self.0[1][1] = m3;
true
}
}
}
impl<T: Copy + NumAssign> Mat3<T> {
pub fn det(&self) -> T {
self.0[0][0] * (self.0[1][1] * self.0[2][2] - self.0[2][1] * self.0[1][2])
- self.0[1][0] * (self.0[0][1] * self.0[2][2] - self.0[2][1] * self.0[0][2])
+ self.0[2][0] * (self.0[0][1] * self.0[1][2] - self.0[1][1] * self.0[0][2])
}
pub fn invert(&mut self) -> bool {
let det = self.det();
if det == T::zero() {
false
} else {
let (m0, m1, m2, m3, m4, m5, m6, m7, m8) = (
self.0[1][1] * self.0[2][2] - self.0[2][1] * self.0[1][2],
self.0[2][1] * self.0[0][2] - self.0[0][1] * self.0[2][2],
self.0[0][1] * self.0[1][2] - self.0[1][1] * self.0[0][2],
self.0[2][0] * self.0[1][2] - self.0[1][0] * self.0[2][2],
self.0[0][0] * self.0[2][2] - self.0[2][0] * self.0[0][2],
self.0[1][0] * self.0[0][2] - self.0[0][0] * self.0[1][2],
self.0[1][0] * self.0[2][1] - self.0[2][0] * self.0[1][1],
self.0[2][0] * self.0[0][1] - self.0[0][0] * self.0[2][1],
self.0[0][0] * self.0[1][1] - self.0[1][0] * self.0[0][1],
);
self.0[0][0] = m0 / det;
self.0[0][1] = m1 / det;
self.0[0][2] = m2 / det;
self.0[1][0] = m3 / det;
self.0[1][1] = m4 / det;
self.0[1][2] = m5 / det;
self.0[2][0] = m6 / det;
self.0[2][1] = m7 / det;
self.0[2][2] = m8 / det;
true
}
}
#[inline]
pub fn normal_matrix(&mut self) -> bool {
if !self.invert() {
false
} else {
self.transpose();
true
}
}
}
impl<T: Copy + NumAssign> Mat4<T> {
pub fn det(&self) -> T {
let fa0 = self.0[0][0] * self.0[1][1] - self.0[1][0] * self.0[0][1];
let fa1 = self.0[0][0] * self.0[2][1] - self.0[2][0] * self.0[0][1];
let fa2 = self.0[0][0] * self.0[3][1] - self.0[3][0] * self.0[0][1];
let fa3 = self.0[1][0] * self.0[2][1] - self.0[2][0] * self.0[1][1];
let fa4 = self.0[1][0] * self.0[3][1] - self.0[3][0] * self.0[1][1];
let fa5 = self.0[2][0] * self.0[3][1] - self.0[3][0] * self.0[2][1];
let fb0 = self.0[0][2] * self.0[1][3] - self.0[1][2] * self.0[0][3];
let fb1 = self.0[0][2] * self.0[2][3] - self.0[2][2] * self.0[0][3];
let fb2 = self.0[0][2] * self.0[3][3] - self.0[3][2] * self.0[0][3];
let fb3 = self.0[1][2] * self.0[2][3] - self.0[2][2] * self.0[1][3];
let fb4 = self.0[1][2] * self.0[3][3] - self.0[3][2] * self.0[1][3];
let fb5 = self.0[2][2] * self.0[3][3] - self.0[3][2] * self.0[2][3];
fa0 * fb5 - fa1 * fb4 + fa2 * fb3 + fa3 * fb2 - fa4 * fb1 + fa5 * fb0
}
pub fn invert(&mut self) -> bool {
let fa0 = self.0[0][0] * self.0[1][1] - self.0[1][0] * self.0[0][1];
let fa1 = self.0[0][0] * self.0[2][1] - self.0[2][0] * self.0[0][1];
let fa2 = self.0[0][0] * self.0[3][1] - self.0[3][0] * self.0[0][1];
let fa3 = self.0[1][0] * self.0[2][1] - self.0[2][0] * self.0[1][1];
let fa4 = self.0[1][0] * self.0[3][1] - self.0[3][0] * self.0[1][1];
let fa5 = self.0[2][0] * self.0[3][1] - self.0[3][0] * self.0[2][1];
let fb0 = self.0[0][2] * self.0[1][3] - self.0[1][2] * self.0[0][3];
let fb1 = self.0[0][2] * self.0[2][3] - self.0[2][2] * self.0[0][3];
let fb2 = self.0[0][2] * self.0[3][3] - self.0[3][2] * self.0[0][3];
let fb3 = self.0[1][2] * self.0[2][3] - self.0[2][2] * self.0[1][3];
let fb4 = self.0[1][2] * self.0[3][3] - self.0[3][2] * self.0[1][3];
let fb5 = self.0[2][2] * self.0[3][3] - self.0[3][2] * self.0[2][3];
let det = fa0 * fb5 - fa1 * fb4 + fa2 * fb3 + fa3 * fb2 - fa4 * fb1 + fa5 * fb0;
if det == T::zero() {
false
} else {
let zero = T::zero();
let (m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15) = (
self.0[1][1] * fb5 - self.0[2][1] * fb4 + self.0[3][1] * fb3,
zero - self.0[0][1] * fb5 + self.0[2][1] * fb2 - self.0[3][1] * fb1,
self.0[0][1] * fb4 - self.0[1][1] * fb2 + self.0[3][1] * fb0,
zero - self.0[0][1] * fb3 + self.0[1][1] * fb1 - self.0[2][1] * fb0,
zero - self.0[1][0] * fb5 + self.0[2][0] * fb4 - self.0[3][0] * fb3,
self.0[0][0] * fb5 - self.0[2][0] * fb2 + self.0[3][0] * fb1,
zero - self.0[0][0] * fb4 + self.0[1][0] * fb2 - self.0[3][0] * fb0,
self.0[0][0] * fb3 - self.0[1][0] * fb1 + self.0[2][0] * fb0,
self.0[1][3] * fa5 - self.0[2][3] * fa4 + self.0[3][3] * fa3,
zero - self.0[0][3] * fa5 + self.0[2][3] * fa2 - self.0[3][3] * fa1,
self.0[0][3] * fa4 - self.0[1][3] * fa2 + self.0[3][3] * fa0,
zero - self.0[0][3] * fa3 + self.0[1][3] * fa1 - self.0[2][3] * fa0,
zero - self.0[1][2] * fa5 + self.0[2][2] * fa4 - self.0[3][2] * fa3,
self.0[0][2] * fa5 - self.0[2][2] * fa2 + self.0[3][2] * fa1,
zero - self.0[0][2] * fa4 + self.0[1][2] * fa2 - self.0[3][2] * fa0,
self.0[0][2] * fa3 - self.0[1][2] * fa1 + self.0[2][2] * fa0,
);
self.0[0][0] = m0 / det;
self.0[0][1] = m1 / det;
self.0[0][2] = m2 / det;
self.0[0][3] = m3 / det;
self.0[1][0] = m4 / det;
self.0[1][1] = m5 / det;
self.0[1][2] = m6 / det;
self.0[1][3] = m7 / det;
self.0[2][0] = m8 / det;
self.0[2][1] = m9 / det;
self.0[2][2] = m10 / det;
self.0[2][3] = m11 / det;
self.0[3][0] = m12 / det;
self.0[3][1] = m13 / det;
self.0[3][2] = m14 / det;
self.0[3][3] = m15 / det;
true
}
}
}