use std::ops::*;
use std::cmp::Ord;
#[cfg(test)]
mod tests {
use crate::Vec2;
use std::ops::*;
#[test]
fn vec2_add() {
assert_eq!(Vec2(1, 2) + Vec2(2, 1), Vec2(3, 3));
}
}
#[derive(PartialEq, Copy, Clone, Debug, Ord, PartialOrd, Eq)]
pub struct Vec2<T>(T, T);
#[derive(PartialEq, Copy, Clone, Debug, Ord, PartialOrd, Eq)]
pub struct Vec3<T>(T, T, T);
#[derive(PartialEq, Copy, Clone, Debug, Ord, PartialOrd, Eq)]
pub struct Vec4<T>(T, T, T, T);
#[derive(PartialEq, Copy, Clone, Debug, Ord, PartialOrd, Eq)]
pub struct Mat2<T>(Vec2<T>, Vec2<T>);
#[derive(PartialEq, Copy, Clone, Debug, Ord, PartialOrd, Eq)]
pub struct Mat3<T>(Vec3<T>, Vec3<T>, Vec3<T>);
#[derive(PartialEq, Copy, Clone, Debug, Ord, PartialOrd, Eq)]
pub struct Mat4<T>(Vec4<T>, Vec4<T>, Vec4<T>, Vec4<T>);
type Quat32 = Vec4<f32>;
type Quat64 = Vec4<f64>;
impl Vec2<f32> {
pub fn abs(self) -> Self {
Vec2(if self.0 < 0f32 { -self.0 } else { self.0 },
if self.1 < 0f32 { -self.1 } else { self.1 })
}
pub fn powf(self, rhs: Self) -> Self {
Vec2(self.0.powf(rhs.0),
self.1.powf(rhs.1))
}
pub fn powi(self, rhs: Vec2<i32>) -> Self {
Vec2(self.0.powi(rhs.0),
self.1.powi(rhs.1))
}
pub fn sqrt(self) -> Self {
Vec2(self.0.sqrt(),
self.1.sqrt())
}
pub fn cbrt(self) -> Self {
Vec2(self.0.cbrt(),
self.1.cbrt())
}
pub fn log(self, rhs: Self) -> Self {
Vec2(self.0.log(rhs.0),
self.1.log(rhs.1))
}
pub fn len(self) -> f32 {
(self.0 * self.0 + self.1 * self.1).sqrt()
}
pub fn normalize(self, len: f32) -> Self {
let inv_len = len / self.len();
Vec2(self.0 * inv_len,
self.1 * inv_len)
}
pub fn disf32ance(self, other: Self) -> f32 {
(other - self).len()
}
pub fn angle(self, other: Self) -> f32 {
self.dot(other) / (self.len() * other.len())
}
}
impl Vec2<f64> {
pub fn abs(self) -> Self {
Vec2(if self.0 < 0f64 { -self.0 } else { self.0 },
if self.1 < 0f64 { -self.1 } else { self.1 })
}
pub fn powf(self, rhs: Self) -> Self {
Vec2(self.0.powf(rhs.0),
self.1.powf(rhs.1))
}
pub fn powi(self, rhs: Vec2<i32>) -> Self {
Vec2(self.0.powi(rhs.0),
self.1.powi(rhs.1))
}
pub fn sqrt(self) -> Self {
Vec2(self.0.sqrt(),
self.1.sqrt())
}
pub fn cbrt(self) -> Self {
Vec2(self.0.cbrt(),
self.1.cbrt())
}
pub fn log(self, rhs: Self) -> Self {
Vec2(self.0.log(rhs.0),
self.1.log(rhs.1))
}
pub fn len(self) -> f64 {
(self.0 * self.0 + self.1 * self.1).sqrt()
}
pub fn normalize(self, len: f64) -> Self {
let inv_len = len / self.len();
Vec2(self.0 * inv_len,
self.1 * inv_len)
}
pub fn distance(self, other: Self) -> f64 {
(other - self).len()
}
pub fn angle(self, other: Self) -> f64 {
self.dot(other) / (self.len() * other.len())
}
}
impl<T: std::cmp::Ord> Vec2<T> {
pub fn min(self, other: Self) -> Self {
Vec2(if self.0 < other.0 { self.0 } else { other.0 },
if self.1 < other.1 { self.1 } else { other.1 })
}
pub fn max(self, other: Self) -> Self {
Vec2(if self.0 > other.0 { self.0 } else { other.0 },
if self.1 > other.1 { self.1 } else { other.1 })
}
pub fn clamp(self, lower: Self, upper: Self) -> Self {
Vec2(if self.0 < lower.0 { lower.0 } else if self.0 > upper.0 { upper.0 } else { self.0 },
if self.1 < lower.1 { lower.1 } else if self.1 > upper.1 { upper.1 } else { self.1 })
}
}
impl<T: Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Copy> Vec2<T> {
pub fn dot(self, other: Self) -> T {
self.0 * other.0 + self.1 * other.1
}
pub fn mix(self, a: Self, b: Self) -> Self {
Vec2(a.0 + (b.0 - a.0) * self.0,
a.1 + (b.1 - a.1) * self.1)
}
}
impl<T: Add<Output = U>, U> Add for Vec2<T> {
type Output = Vec2<U>;
fn add(self, rhs: Self) -> Self::Output {
Vec2(self.0 + rhs.0,
self.1 + rhs.1)
}
}
impl<T: Sub<Output = U>, U> Sub for Vec2<T> {
type Output = Vec2<U>;
fn sub(self, rhs: Self) -> Self::Output {
Vec2(self.0 - rhs.0,
self.1 - rhs.1)
}
}
impl<T: Mul<Output = U>, U> Mul for Vec2<T> {
type Output = Vec2<U>;
fn mul(self, rhs: Self) -> Self::Output {
Vec2(self.0 * rhs.0,
self.1 * rhs.1)
}
}
impl<T: Div<Output = U>, U> Div for Vec2<T> {
type Output = Vec2<U>;
fn div(self, rhs: Self) -> Self::Output {
Vec2(self.0 / rhs.0,
self.1 / rhs.1)
}
}
impl<T: Rem<Output = U>, U> Rem for Vec2<T> {
type Output = Vec2<U>;
fn rem(self, rhs: Self) -> Self::Output {
Vec2(self.0 % rhs.0,
self.1 % rhs.1)
}
}
impl<T: Neg<Output = U>, U> Neg for Vec2<T> {
type Output = Vec2<U>;
fn neg(self) -> Self::Output {
Vec2(-self.0,
-self.1)
}
}
impl<T: AddAssign> AddAssign for Vec2<T> {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
self.1 += rhs.1;
}
}
impl<T: SubAssign> SubAssign for Vec2<T> {
fn sub_assign(&mut self, rhs: Self) {
self.0 -= rhs.0;
self.1 -= rhs.1;
}
}
impl<T: MulAssign> MulAssign for Vec2<T> {
fn mul_assign(&mut self, rhs: Self) {
self.0 *= rhs.0;
self.1 *= rhs.1;
}
}
impl<T: DivAssign> DivAssign for Vec2<T> {
fn div_assign(&mut self, rhs: Self) {
self.0 /= rhs.0;
self.1 /= rhs.1;
}
}
impl<T: RemAssign> RemAssign for Vec2<T> {
fn rem_assign(&mut self, rhs: Self) {
self.0 %= rhs.0;
self.1 %= rhs.1;
}
}
impl Vec3<f32> {
pub fn abs(self) -> Self {
Vec3(if self.0 < 0f32 { -self.0 } else { self.0 },
if self.1 < 0f32 { -self.1 } else { self.1 },
if self.2 < 0f32 { -self.2 } else { self.2 })
}
pub fn powf(self, rhs: Self) -> Self {
Vec3(self.0.powf(rhs.0),
self.1.powf(rhs.1),
self.2.powf(rhs.2))
}
pub fn powi(self, rhs: Vec3<i32>) -> Self {
Vec3(self.0.powi(rhs.0),
self.1.powi(rhs.1),
self.2.powi(rhs.2))
}
pub fn sqrt(self) -> Self {
Vec3(self.0.sqrt(),
self.1.sqrt(),
self.2.sqrt())
}
pub fn cbrt(self) -> Self {
Vec3(self.0.cbrt(),
self.1.cbrt(),
self.2.cbrt())
}
pub fn log(self, rhs: Self) -> Self {
Vec3(self.0.log(rhs.0),
self.1.log(rhs.1),
self.2.log(rhs.2))
}
pub fn len(self) -> f32 {
(self.0 * self.0 + self.1 * self.1 + self.2 * self.2).sqrt()
}
pub fn normalize(self, len: f32) -> Self {
let inv_len = len / self.len();
Vec3(self.0 * inv_len,
self.1 * inv_len,
self.2 * inv_len)
}
pub fn distance(self, other: Self) -> f32 {
(other - self).len()
}
pub fn angle(self, other: Self) -> f32 {
self.dot(other) / (self.len() * other.len())
}
}
impl Vec3<f64> {
pub fn abs(self) -> Self {
Vec3(if self.0 < 0f64 { -self.0 } else { self.0 },
if self.1 < 0f64 { -self.1 } else { self.1 },
if self.2 < 0f64 { -self.2 } else { self.2 })
}
pub fn powf(self, rhs: Self) -> Self {
Vec3(self.0.powf(rhs.0),
self.1.powf(rhs.1),
self.2.powf(rhs.2))
}
pub fn powi(self, rhs: Vec3<i32>) -> Self {
Vec3(self.0.powi(rhs.0),
self.1.powi(rhs.1),
self.2.powi(rhs.2))
}
pub fn sqrt(self) -> Self {
Vec3(self.0.sqrt(),
self.1.sqrt(),
self.2.sqrt())
}
pub fn cbrt(self) -> Self {
Vec3(self.0.cbrt(),
self.1.cbrt(),
self.2.cbrt())
}
pub fn log(self, rhs: Self) -> Self {
Vec3(self.0.log(rhs.0),
self.1.log(rhs.1),
self.2.log(rhs.2))
}
pub fn len(self) -> f64 {
(self.0 * self.0 + self.1 * self.1 + self.2 * self.2).sqrt()
}
pub fn normalize(self, len: f64) -> Self {
let inv_len = len / self.len();
Vec3(self.0 * inv_len,
self.1 * inv_len,
self.2 * inv_len)
}
pub fn distance(self, other: Self) -> f64 {
(other - self).len()
}
pub fn angle(self, other: Self) -> f64 {
self.dot(other) / (self.len() * other.len())
}
}
impl<T: std::cmp::Ord> Vec3<T> {
pub fn min(self, other: Self) -> Self {
Vec3(if self.0 < other.0 { self.0 } else { other.0 },
if self.1 < other.1 { self.1 } else { other.1 },
if self.2 < other.2 { self.2 } else { other.2 })
}
pub fn max(self, other: Self) -> Self {
Vec3(if self.0 > other.0 { self.0 } else { other.0 },
if self.1 > other.1 { self.1 } else { other.1 },
if self.2 > other.2 { self.2 } else { other.2 })
}
pub fn clamp(self, lower: Self, upper: Self) -> Self {
Vec3(if self.0 < lower.0 { lower.0 } else if self.0 > upper.0 { upper.0 } else { self.0 },
if self.1 < lower.1 { lower.1 } else if self.1 > upper.1 { upper.1 } else { self.1 },
if self.2 < lower.2 { lower.2 } else if self.2 > upper.2 { upper.2 } else { self.2 })
}
}
impl<T: Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Copy> Vec3<T> {
pub fn dot(self, other: Self) -> T {
self.0 * other.0 + self.1 * other.1 + self.2 * other.2
}
pub fn cross(self, other: Self) -> Self {
Vec3(self.1 * other.2 - self.2 * other.1,
self.2 * other.0 - self.0 * other.2,
self.0 * other.1 - self.1 * other.0)
}
pub fn mix(self, a: Self, b: Self) -> Self {
Vec3(a.0 + (b.0 - a.0) * self.0,
a.1 + (b.1 - a.1) * self.1,
a.2 + (b.2 - a.2) * self.2)
}
}
impl<T: Add<Output = U>, U> Add for Vec3<T> {
type Output = Vec3<U>;
fn add(self, rhs: Self) -> Self::Output {
Vec3(self.0 + rhs.0,
self.1 + rhs.1,
self.2 + rhs.2)
}
}
impl<T: Sub<Output = U>, U> Sub for Vec3<T> {
type Output = Vec3<U>;
fn sub(self, rhs: Self) -> Self::Output {
Vec3(self.0 - rhs.0,
self.1 - rhs.1,
self.2 - rhs.2)
}
}
impl<T: Mul<Output = U>, U> Mul for Vec3<T> {
type Output = Vec3<U>;
fn mul(self, rhs: Self) -> Self::Output {
Vec3(self.0 * rhs.0,
self.1 * rhs.1,
self.2 * rhs.2)
}
}
impl<T: Div<Output = U>, U> Div for Vec3<T> {
type Output = Vec3<U>;
fn div(self, rhs: Self) -> Self::Output {
Vec3(self.0 / rhs.0,
self.1 / rhs.1,
self.2 / rhs.2)
}
}
impl<T: Rem<Output = U>, U> Rem for Vec3<T> {
type Output = Vec3<U>;
fn rem(self, rhs: Self) -> Self::Output {
Vec3(self.0 % rhs.0,
self.1 % rhs.1,
self.2 % rhs.2)
}
}
impl<T: Neg<Output = U>, U> Neg for Vec3<T> {
type Output = Vec3<U>;
fn neg(self) -> Self::Output {
Vec3(-self.0,
-self.1,
-self.2)
}
}
impl<T: AddAssign> AddAssign for Vec3<T> {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
self.1 += rhs.1;
self.2 += rhs.2;
}
}
impl<T: SubAssign> SubAssign for Vec3<T> {
fn sub_assign(&mut self, rhs: Self) {
self.0 -= rhs.0;
self.1 -= rhs.1;
self.2 -= rhs.2;
}
}
impl<T: MulAssign> MulAssign for Vec3<T> {
fn mul_assign(&mut self, rhs: Self) {
self.0 *= rhs.0;
self.1 *= rhs.1;
self.2 *= rhs.2;
}
}
impl<T: DivAssign> DivAssign for Vec3<T> {
fn div_assign(&mut self, rhs: Self) {
self.0 /= rhs.0;
self.1 /= rhs.1;
self.2 /= rhs.2;
}
}
impl<T: RemAssign> RemAssign for Vec3<T> {
fn rem_assign(&mut self, rhs: Self) {
self.0 %= rhs.0;
self.1 %= rhs.1;
self.2 %= rhs.2;
}
}
impl Vec4<f32> {
pub fn abs(self) -> Self {
Vec4(if self.0 < 0f32 { -self.0 } else { self.0 },
if self.1 < 0f32 { -self.1 } else { self.1 },
if self.2 < 0f32 { -self.2 } else { self.2 },
if self.3 < 0f32 { -self.3 } else { self.3 })
}
pub fn powf(self, rhs: Self) -> Self {
Vec4(self.0.powf(rhs.0),
self.1.powf(rhs.1),
self.2.powf(rhs.2),
self.3.powf(rhs.3))
}
pub fn powi(self, rhs: Vec4<i32>) -> Self {
Vec4(self.0.powi(rhs.0),
self.1.powi(rhs.1),
self.2.powi(rhs.2),
self.3.powi(rhs.3))
}
pub fn sqrt(self) -> Self {
Vec4(self.0.sqrt(),
self.1.sqrt(),
self.2.sqrt(),
self.3.sqrt())
}
pub fn cbrt(self) -> Self {
Vec4(self.0.cbrt(),
self.1.cbrt(),
self.2.cbrt(),
self.3.cbrt())
}
pub fn log(self, rhs: Self) -> Self {
Vec4(self.0.log(rhs.0),
self.1.log(rhs.1),
self.2.log(rhs.2),
self.2.log(rhs.3))
}
pub fn len(self) -> f32 {
(self.0 * self.0 + self.1 * self.1 + self.2 * self.2 + self.3 * self.3).sqrt()
}
pub fn normalize(self, len: f32) -> Self {
let inv_len = len / self.len();
Vec4(self.0 * inv_len,
self.1 * inv_len,
self.2 * inv_len,
self.3 * inv_len)
}
pub fn distance(self, other: Self) -> f32 {
(other - self).len()
}
pub fn angle(self, other: Self) -> f32 {
self.dot(other) / (self.len() * other.len())
}
}
impl Vec4<f64> {
pub fn abs(self) -> Self {
Vec4(if self.0 < 0f64 { -self.0 } else { self.0 },
if self.1 < 0f64 { -self.1 } else { self.1 },
if self.2 < 0f64 { -self.2 } else { self.2 },
if self.3 < 0f64 { -self.3 } else { self.3 })
}
pub fn powf(self, rhs: Self) -> Self {
Vec4(self.0.powf(rhs.0),
self.1.powf(rhs.1),
self.2.powf(rhs.2),
self.3.powf(rhs.3))
}
pub fn powi(self, rhs: Vec4<i32>) -> Self {
Vec4(self.0.powi(rhs.0),
self.1.powi(rhs.1),
self.2.powi(rhs.2),
self.3.powi(rhs.3))
}
pub fn sqrt(self) -> Self {
Vec4(self.0.sqrt(),
self.1.sqrt(),
self.2.sqrt(),
self.3.sqrt())
}
pub fn cbrt(self) -> Self {
Vec4(self.0.cbrt(),
self.1.cbrt(),
self.2.cbrt(),
self.3.cbrt())
}
pub fn log(self, rhs: Self) -> Self {
Vec4(self.0.log(rhs.0),
self.1.log(rhs.1),
self.2.log(rhs.2),
self.2.log(rhs.3))
}
pub fn len(self) -> f64 {
(self.0 * self.0 + self.1 * self.1 + self.2 * self.2 + self.3 * self.3).sqrt()
}
pub fn normalize(self, len: f64) -> Self {
let inv_len = len / self.len();
Vec4(self.0 * inv_len,
self.1 * inv_len,
self.2 * inv_len,
self.3 * inv_len)
}
pub fn distance(self, other: Self) -> f64 {
(other - self).len()
}
pub fn angle(self, other: Self) -> f64 {
self.dot(other) / (self.len() * other.len())
}
}
impl<T: std::cmp::Ord> Vec4<T> {
pub fn min(self, other: Self) -> Self {
Vec4(if self.0 < other.0 { self.0 } else { other.0 },
if self.1 < other.1 { self.1 } else { other.1 },
if self.2 < other.2 { self.2 } else { other.2 },
if self.3 < other.3 { self.3 } else { other.3 })
}
pub fn max(self, other: Self) -> Self {
Vec4(if self.0 > other.0 { self.0 } else { other.0 },
if self.1 > other.1 { self.1 } else { other.1 },
if self.2 > other.2 { self.2 } else { other.2 },
if self.3 > other.3 { self.3 } else { other.3 })
}
pub fn clamp(self, lower: Self, upper: Self) -> Self {
Vec4(if self.0 < lower.0 { lower.0 } else if self.0 > upper.0 { upper.0 } else { self.0 },
if self.1 < lower.1 { lower.1 } else if self.1 > upper.1 { upper.1 } else { self.1 },
if self.2 < lower.2 { lower.2 } else if self.2 > upper.2 { upper.2 } else { self.2 },
if self.3 < lower.3 { lower.3 } else if self.3 > upper.3 { upper.3 } else { self.3 })
}
}
impl<T: Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Copy> Vec4<T> {
pub fn dot(self, other: Self) -> T {
self.0 * other.0 + self.1 * other.1 + self.2 * other.2 + self.3 * other.3
}
pub fn mix(self, a: Self, b: Self) -> Self {
Vec4(a.0 + (b.0 - a.0) * self.0,
a.1 + (b.1 - a.1) * self.1,
a.2 + (b.2 - a.2) * self.2,
a.3 + (b.3 - a.3) * self.3)
}
}
impl<T: Add<Output = U>, U> Add for Vec4<T> {
type Output = Vec4<U>;
fn add(self, rhs: Self) -> Self::Output {
Vec4(self.0 + rhs.0,
self.1 + rhs.1,
self.2 + rhs.2,
self.3 + rhs.3)
}
}
impl<T: Sub<Output = U>, U> Sub for Vec4<T> {
type Output = Vec4<U>;
fn sub(self, rhs: Self) -> Self::Output {
Vec4(self.0 - rhs.0,
self.1 - rhs.1,
self.2 - rhs.2,
self.3 - rhs.3)
}
}
impl<T: Mul<Output = U>, U> Mul for Vec4<T> {
type Output = Vec4<U>;
fn mul(self, rhs: Self) -> Self::Output {
Vec4(self.0 * rhs.0,
self.1 * rhs.1,
self.2 * rhs.2,
self.3 * rhs.3)
}
}
impl<T: Div<Output = U>, U> Div for Vec4<T> {
type Output = Vec4<U>;
fn div(self, rhs: Self) -> Self::Output {
Vec4(self.0 / rhs.0,
self.1 / rhs.1,
self.2 / rhs.2,
self.3 / rhs.3)
}
}
impl<T: Rem<Output = U>, U> Rem for Vec4<T> {
type Output = Vec4<U>;
fn rem(self, rhs: Self) -> Self::Output {
Vec4(self.0 % rhs.0,
self.1 % rhs.1,
self.2 % rhs.2,
self.3 % rhs.3)
}
}
impl<T: Neg<Output = U>, U> Neg for Vec4<T> {
type Output = Vec4<U>;
fn neg(self) -> Self::Output {
Vec4(-self.0,
-self.1,
-self.2,
-self.3)
}
}
impl<T: AddAssign> AddAssign for Vec4<T> {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
self.1 += rhs.1;
self.2 += rhs.2;
self.3 += rhs.3;
}
}
impl<T: SubAssign> SubAssign for Vec4<T> {
fn sub_assign(&mut self, rhs: Self) {
self.0 -= rhs.0;
self.1 -= rhs.1;
self.2 -= rhs.2;
self.3 -= rhs.3;
}
}
impl<T: MulAssign> MulAssign for Vec4<T> {
fn mul_assign(&mut self, rhs: Self) {
self.0 *= rhs.0;
self.1 *= rhs.1;
self.2 *= rhs.2;
self.3 *= rhs.3;
}
}
impl<T: DivAssign> DivAssign for Vec4<T> {
fn div_assign(&mut self, rhs: Self) {
self.0 /= rhs.0;
self.1 /= rhs.1;
self.2 /= rhs.2;
self.3 /= rhs.3;
}
}
impl<T: RemAssign> RemAssign for Vec4<T> {
fn rem_assign(&mut self, rhs: Self) {
self.0 %= rhs.0;
self.1 %= rhs.1;
self.2 %= rhs.2;
self.3 %= rhs.3;
}
}
impl Quat32 {
pub fn from_rotation_x(angle: f32) -> Self {
Vec4((angle * 0.5f32).sin(), 0f32, 0f32, (angle * 0.5f32).cos())
}
pub fn from_rotation_y(angle: f32) -> Self {
Vec4(0f32, (angle * 0.5f32).sin(), 0f32, (angle * 0.5f32).cos())
}
pub fn from_rotation_z(angle: f32) -> Self {
Vec4(0f32, 0f32, (angle * 0.5f32).sin(), (angle * 0.5f32).cos())
}
pub fn from_axis_angle(axis: Vec3<f32>, angle: f32) -> Self {
let sin = (angle * 0.5f32).sin();
let inv_len = 1f32 / axis.len();
Vec4(axis.0 * inv_len * sin,
axis.1 * inv_len * sin,
axis.2 * inv_len * sin,
(angle * 0.5f32).cos())
}
pub fn rotate_x_local(self, angle: f32) -> Self {
let sin = (angle * 0.5f32).sin();
let cos = (angle * 0.5f32).cos();
Vec4(self.0 * cos + self.3 * sin,
self.1 * cos - self.2 * sin,
self.2 * cos + self.1 * sin,
self.3 * cos - self.0 * sin)
}
pub fn rotate_y_local(self, angle: f32) -> Self {
let sin = (angle * 0.5f32).sin();
let cos = (angle * 0.5f32).cos();
Vec4(self.0 * cos + self.2 * sin,
self.1 * cos + self.3 * sin,
self.2 * cos - self.0 * sin,
self.3 * cos - self.1 * sin)
}
pub fn rotate_z_local(self, angle: f32) -> Self {
let sin = (angle * 0.5f32).sin();
let cos = (angle * 0.5f32).cos();
Vec4(self.0 * cos - self.1 * sin,
self.1 * cos + self.0 * sin,
self.2 * cos + self.3 * sin,
self.3 * cos - self.2 * sin)
}
pub fn rotate_x(self, angle: f32) -> Self {
let sin = (angle * 0.5f32).sin();
let cos = (angle * 0.5f32).cos();
Vec4(self.3 * sin + self.0 * cos,
self.1 * cos + self.2 * sin,
self.2 * cos - self.1 * sin,
self.3 * cos - self.0 * sin)
}
pub fn rotate_y(self, angle: f32) -> Self {
let sin = (angle * 0.5f32).sin();
let cos = (angle * 0.5f32).cos();
Vec4(self.0 * cos - self.2 * sin,
self.3 * sin + self.1 * cos,
self.0 * sin + self.2 * cos,
self.3 * cos - self.1 * sin)
}
pub fn rotate_z(self, angle: f32) -> Self {
let sin = (angle * 0.5f32).sin();
let cos = (angle * 0.5f32).cos();
Vec4(self.0 * cos + self.1 * sin,
self.1 * cos - self.0 * sin,
self.3 * sin + self.2 * cos,
self.3 * cos - self.2 * sin)
}
pub fn rotate_axis(self, axis: Vec3<f32>, angle: f32) -> Self {
let sin = (angle * 0.5f32).sin();
let inv_len = 1f32 / axis.len();
let rx = axis.0 * inv_len * sin;
let ry = axis.1 * inv_len * sin;
let rz = axis.2 * inv_len * sin;
let rw = (angle * 0.5f32).cos();
Vec4(self.3 * rx + self.0 * rw + self.1 * rz - self.2 * ry,
self.3 * ry + self.0 * rz + self.1 * rw - self.2 * rx,
self.3 * rz + self.0 * ry + self.1 * rx - self.2 * rw,
self.3 * rw + self.0 * rx + self.1 * ry - self.2 * rz)
}
}
impl Quat64 {
pub fn from_rotation_x(angle: f64) -> Self {
Vec4((angle * 0.5f64).sin(), 0f64, 0f64, (angle * 0.5f64).cos())
}
pub fn from_rotation_y(angle: f64) -> Self {
Vec4(0f64, (angle * 0.5f64).sin(), 0f64, (angle * 0.5f64).cos())
}
pub fn from_rotation_z(angle: f64) -> Self {
Vec4(0f64, 0f64, (angle * 0.5f64).sin(), (angle * 0.5f64).cos())
}
pub fn from_axis_angle(axis: Vec3<f64>, angle: f64) -> Self {
let sin = (angle * 0.5f64).sin();
let inv_len = 1f64 / axis.len();
Vec4(axis.0 * inv_len * sin,
axis.1 * inv_len * sin,
axis.2 * inv_len * sin,
(angle * 0.5f64).cos())
}
pub fn rotate_x_local(self, angle: f64) -> Self {
let sin = (angle * 0.5f64).sin();
let cos = (angle * 0.5f64).cos();
Vec4(self.0 * cos + self.3 * sin,
self.1 * cos + self.2 * sin,
self.2 * cos - self.1 * sin,
self.3 * cos - self.0 * sin)
}
pub fn rotate_y_local(self, angle: f64) -> Self {
let sin = (angle * 0.5f64).sin();
let cos = (angle * 0.5f64).cos();
Vec4(self.0 * cos + self.2 * sin,
self.1 * cos + self.3 * sin,
self.2 * cos - self.0 * sin,
self.3 * cos - self.1 * sin)
}
pub fn rotate_z_local(self, angle: f64) -> Self {
let sin = (angle * 0.5f64).sin();
let cos = (angle * 0.5f64).cos();
Vec4(self.0 * cos + self.1 * sin,
self.1 * cos + self.0 * sin,
self.2 * cos - self.3 * sin,
self.3 * cos - self.2 * sin)
}
pub fn rotate_x(self, angle: f64) -> Self {
let sin = (angle * 0.5f64).sin();
let cos = (angle * 0.5f64).cos();
Vec4(self.3 * sin + self.0 * cos,
self.1 * cos + self.2 * sin,
self.2 * cos - self.1 * sin,
self.3 * cos - self.0 * sin)
}
pub fn rotate_y(self, angle: f64) -> Self {
let sin = (angle * 0.5f64).sin();
let cos = (angle * 0.5f64).cos();
Vec4(self.0 * cos - self.2 * sin,
self.3 * sin + self.1 * cos,
self.0 * sin + self.2 * cos,
self.3 * cos - self.1 * sin)
}
pub fn rotate_z(self, angle: f64) -> Self {
let sin = (angle * 0.5f64).sin();
let cos = (angle * 0.5f64).cos();
Vec4(self.0 * cos + self.1 * sin,
self.1 * cos + self.0 * sin,
self.3 * sin - self.2 * cos,
self.3 * cos - self.2 * sin)
}
pub fn rotate_axis(self, axis: Vec3<f64>, angle: f64) -> Self {
let sin = (angle * 0.5f64).sin();
let inv_len = 1f64 / axis.len();
let rx = axis.0 * inv_len * sin;
let ry = axis.1 * inv_len * sin;
let rz = axis.2 * inv_len * sin;
let rw = (angle * 0.5f64).cos();
Vec4(self.3 * rx + self.0 * rw + self.1 * rz - self.2 * ry,
self.3 * ry + self.0 * rz + self.1 * rw - self.2 * rx,
self.3 * rz + self.0 * ry + self.1 * rx - self.2 * rw,
self.3 * rw + self.0 * rx + self.1 * ry - self.2 * rz)
}
}
impl Default for Mat4<f32> {
fn default() -> Self {
Mat4(Vec4(1f32, 0f32, 0f32, 0f32),
Vec4(0f32, 1f32, 0f32, 0f32),
Vec4(0f32, 0f32, 1f32, 0f32),
Vec4(0f32, 0f32, 0f32, 1f32))
}
}
impl Default for Mat4<f64> {
fn default() -> Self {
Mat4(Vec4(1f64, 0f64, 0f64, 0f64),
Vec4(0f64, 1f64, 0f64, 0f64),
Vec4(0f64, 0f64, 1f64, 0f64),
Vec4(0f64, 0f64, 0f64, 1f64))
}
}
impl Mat4<f32> {
pub fn transform_pos(&self, vec: Vec3<f32>) -> Vec3<f32> {
Vec3((self.0).0 * vec.0 + (self.1).0 * vec.1 + (self.2).0 * vec.2 + (self.3).0,
(self.0).1 * vec.0 + (self.1).1 * vec.1 + (self.2).1 * vec.2 + (self.3).1,
(self.0).2 * vec.0 + (self.1).2 * vec.1 + (self.2).2 * vec.2 + (self.3).2)
}
pub fn from_translation(trans: Vec3<f32>) -> Self
{
let mut mat = Mat4::default();
(mat.3).0 = trans.0;
(mat.3).1 = trans.1;
(mat.3).2 = trans.2;
mat
}
pub fn from_rotation(quat: Quat32) -> Self
{
let mut mat = Mat4::default();
let w2 = quat.3 * quat.3;
let x2 = quat.0 * quat.0;
let y2 = quat.1 * quat.1;
let z2 = quat.2 * quat.2;
let zw = quat.2 * quat.3;
let xy = quat.0 * quat.1;
let xz = quat.0 * quat.2;
let yw = quat.1 * quat.3;
let yz = quat.1 * quat.2;
let xw = quat.0 * quat.3;
(mat.0).0 = w2 + x2 - z2 - y2;
(mat.0).1 = xy + zw + zw + xy;
(mat.0).2 = xz - yw + xz - yw;
(mat.1).0 = -zw + xy - zw + xy;
(mat.1).1 = y2 - z2 + w2 - x2;
(mat.1).2 = yz + yz + xw + xw;
(mat.2).0 = yw + xz + xz + yw;
(mat.2).1 = yz + yz - xw - xw;
(mat.2).2 = z2 - y2 - x2 + w2;
mat
}
pub fn from_scale(scale: Vec3<f32>) -> Self
{
let mut mat = Mat4::default();
(mat.0).0 = scale.0;
(mat.1).1 = scale.1;
(mat.2).2 = scale.2;
mat
}
pub fn from_transform(t: Vec3<f32>, q: Quat32, s: Vec3<f32>) -> Self
{
let mut mat = Mat4::default();
let dqx = q.0 + q.0;
let dqy = q.1 + q.1;
let dqz = q.2 + q.2;
let q00 = dqx * q.0;
let q11 = dqy * q.1;
let q22 = dqz * q.2;
let q01 = dqx * q.1;
let q02 = dqx * q.2;
let q03 = dqx * q.3;
let q12 = dqy * q.2;
let q13 = dqy * q.3;
let q23 = dqz * q.3;
(mat.0).0 = s.0 - (q11 + q22) * s.0;
(mat.0).1 = (q01 + q23) * s.0;
(mat.0).2 = (q02 - q13) * s.0;
(mat.0).3 = 0f32;
(mat.1).0 = (q01 - q23) * s.1;
(mat.1).1 = s.1 - (q22 + q00) * s.1;
(mat.1).2 = (q12 + q03) * s.1;
(mat.1).3 = 0f32;
(mat.2).0 = (q02 + q13) * s.2;
(mat.2).1 = (q12 - q03) * s.2;
(mat.2).2 = s.2 - (q11 + q00) * s.2;
(mat.2).3 = 0f32;
(mat.3).0 = t.0;
(mat.3).1 = t.1;
(mat.3).2 = t.2;
(mat.3).3 = 1f32;
mat
}
pub fn from_perspective(y_fov: f32, aspect: f32, z_near: f32, z_far: f32, z_zero_to_one: bool) -> Self
{
let mut mat = Mat4::default();
let h = (y_fov * 0.5f32).tan();
(mat.0).0 = 1f32 / (h * aspect);
(mat.1).1 = 1f32 / h;
if z_far > 0f32 && (z_far == std::f32::INFINITY || z_far == std::f32::NEG_INFINITY) {
(mat.2).2 = 1E-6f32 - 1f32;
(mat.3).2 = (1E-6f32 - if z_zero_to_one { 1f32 } else { 2f32 }) * z_near;
} else if z_near > 0f32 && (z_near == std::f32::INFINITY || z_near == std::f32::NEG_INFINITY) {
(mat.2).2 = (if z_zero_to_one { 0f32 } else { 1f32 }) - 1E-6f32;
(mat.3).2 = ((if z_zero_to_one { 1f32 } else { 2f32 }) - 1E-6f32) * z_far;
} else {
(mat.2).2 = (if z_zero_to_one { z_far } else { z_far + z_near }) / (z_near - z_far);
(mat.3).2 = (if z_zero_to_one { z_far } else { z_far + z_far }) * z_near / (z_near - z_far);
}
(mat.2).3 = -1f32;
(mat.3).3 = 0f32;
mat
}
pub fn from_ortho(left: f32, right: f32, bottom: f32, top: f32, z_near: f32, z_far: f32, z_zero_to_one: bool) -> Self
{
let mut mat = Mat4::default();
(mat.0).0 = 2f32 / (right - left);
(mat.1).1 = 2f32 / (top - bottom);
(mat.2).2 = (if z_zero_to_one { 1f32 } else { 2f32 }) / (z_near - z_far);
(mat.3).0 = (right + left) / (left - right);
(mat.3).1 = (top + bottom) / (bottom - top);
(mat.3).2 = (if z_zero_to_one { z_near } else { z_far + z_near }) / (z_near - z_far);
mat
}
pub fn from_ortho_symmetric(width: f32, height: f32, z_near: f32, z_far: f32, z_zero_to_one: bool) -> Self
{
let mut mat = Mat4::default();
(mat.0).0 = 2f32 / width;
(mat.1).1 = 2f32 / height;
(mat.2).2 = (if z_zero_to_one { 1f32 } else { 2f32 }) / (z_near - z_far);
(mat.3).2 = (if z_zero_to_one { z_near } else { z_far + z_near }) / (z_near - z_far);
mat
}
}
impl<T: Add<Output = T> + Mul<Output = T> + Copy> Mul for Mat4<T> {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
Mat4(Vec4((self.0).0 * (rhs.0).0 + (self.1).0 * (rhs.0).1 + (self.2).0 * (rhs.0).2 + (self.3).0 * (rhs.0).3,
(self.0).1 * (rhs.0).0 + (self.1).1 * (rhs.0).1 + (self.2).1 * (rhs.0).2 + (self.3).1 * (rhs.0).3,
(self.0).2 * (rhs.0).0 + (self.1).2 * (rhs.0).1 + (self.2).2 * (rhs.0).2 + (self.3).2 * (rhs.0).3,
(self.0).3 * (rhs.0).0 + (self.1).3 * (rhs.0).1 + (self.2).3 * (rhs.0).2 + (self.3).3 * (rhs.0).3),
Vec4((self.0).0 * (rhs.1).0 + (self.1).0 * (rhs.1).1 + (self.2).0 * (rhs.1).2 + (self.3).0 * (rhs.1).3,
(self.0).1 * (rhs.1).0 + (self.1).1 * (rhs.1).1 + (self.2).1 * (rhs.1).2 + (self.3).1 * (rhs.1).3,
(self.0).2 * (rhs.1).0 + (self.1).2 * (rhs.1).1 + (self.2).2 * (rhs.1).2 + (self.3).2 * (rhs.1).3,
(self.0).3 * (rhs.1).0 + (self.1).3 * (rhs.1).1 + (self.2).3 * (rhs.1).2 + (self.3).3 * (rhs.1).3),
Vec4((self.0).0 * (rhs.2).0 + (self.1).0 * (rhs.2).1 + (self.2).0 * (rhs.2).2 + (self.3).0 * (rhs.2).3,
(self.0).1 * (rhs.2).0 + (self.1).1 * (rhs.2).1 + (self.2).1 * (rhs.2).2 + (self.3).1 * (rhs.2).3,
(self.0).2 * (rhs.2).0 + (self.1).2 * (rhs.2).1 + (self.2).2 * (rhs.2).2 + (self.3).2 * (rhs.2).3,
(self.0).3 * (rhs.2).0 + (self.1).3 * (rhs.2).1 + (self.2).3 * (rhs.2).2 + (self.3).3 * (rhs.2).3),
Vec4((self.0).0 * (rhs.3).0 + (self.1).0 * (rhs.3).1 + (self.2).0 * (rhs.3).2 + (self.3).0 * (rhs.3).3,
(self.0).1 * (rhs.3).0 + (self.1).1 * (rhs.3).1 + (self.2).1 * (rhs.3).2 + (self.3).1 * (rhs.3).3,
(self.0).2 * (rhs.3).0 + (self.1).2 * (rhs.3).1 + (self.2).2 * (rhs.3).2 + (self.3).2 * (rhs.3).3,
(self.0).3 * (rhs.3).0 + (self.1).3 * (rhs.3).1 + (self.2).3 * (rhs.3).2 + (self.3).3 * (rhs.3).3))
}
}
impl Not for Mat4<f32> {
type Output = Self;
fn not(self) -> Self {
let a = (self.0).0 * (self.1).1 - (self.0).1 * (self.1).0;
let b = (self.0).0 * (self.1).2 - (self.0).2 * (self.1).0;
let c = (self.0).0 * (self.1).3 - (self.0).3 * (self.1).0;
let d = (self.0).1 * (self.1).2 - (self.0).2 * (self.1).1;
let e = (self.0).1 * (self.1).3 - (self.0).3 * (self.1).1;
let f = (self.0).2 * (self.1).3 - (self.0).3 * (self.1).2;
let g = (self.2).0 * (self.3).1 - (self.2).1 * (self.3).0;
let h = (self.2).0 * (self.3).2 - (self.2).2 * (self.3).0;
let i = (self.2).0 * (self.3).3 - (self.2).3 * (self.3).0;
let j = (self.2).1 * (self.3).2 - (self.2).2 * (self.3).1;
let k = (self.2).1 * (self.3).3 - (self.2).3 * (self.3).1;
let l = (self.2).2 * (self.3).3 - (self.2).3 * (self.3).2;
let inv_det = 1f32 / (a * l - b * k + c * j + d * i - e * h + f * g);
Mat4(Vec4(( (self.1).1 * l - (self.1).2 * k + (self.1).3 * j) * inv_det,
(-(self.0).1 * l + (self.0).2 * k - (self.0).3 * j) * inv_det,
( (self.3).1 * f - (self.3).2 * e + (self.3).3 * d) * inv_det,
(-(self.2).1 * f + (self.2).2 * e - (self.2).3 * d) * inv_det),
Vec4((-(self.1).0 * l + (self.1).2 * i - (self.1).3 * h) * inv_det,
( (self.0).0 * l - (self.0).2 * i + (self.0).3 * h) * inv_det,
(-(self.3).0 * f + (self.3).2 * c - (self.3).3 * b) * inv_det,
( (self.2).0 * f - (self.2).2 * c + (self.2).3 * b) * inv_det),
Vec4(( (self.1).0 * k - (self.1).1 * i + (self.1).3 * g) * inv_det,
(-(self.0).0 * k + (self.0).1 * i - (self.0).3 * g) * inv_det,
( (self.3).0 * e - (self.3).1 * c + (self.3).3 * a) * inv_det,
(-(self.2).0 * e + (self.2).1 * c - (self.2).3 * a) * inv_det),
Vec4((-(self.1).0 * j + (self.1).1 * h - (self.1).2 * g) * inv_det,
( (self.0).0 * j - (self.0).1 * h + (self.0).2 * g) * inv_det,
(-(self.3).0 * d + (self.3).1 * b - (self.3).2 * a) * inv_det,
( (self.2).0 * d - (self.2).1 * b + (self.2).2 * a) * inv_det))
}
}