use vec::*;
extern crate num_traits;
use self::num_traits::{Zero, One, Float};
use core::ops::*;
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[repr(packed,simd)]
pub struct Quat<T> { pub x: T, pub y: T, pub z: T, pub w: T }
impl<T: Zero + One> Default for Quat<T> {
fn default() -> Self {
Self::identity()
}
}
impl<T> Quat<T> {
pub fn new(x: T, y: T, z: T, w: T) -> Self {
Self { x, y, z, w }
}
pub fn identity() -> Self where T: Zero + One {
Self {
x: T::zero(),
y: T::zero(),
z: T::zero(),
w: T::one(),
}
}
pub fn conjugate(self) -> Self where T: Neg<Output=T> {
Self {
x: -self.x,
y: -self.y,
z: -self.z,
w: self.w,
}
}
pub fn dot(self, q: Self) -> T
where T: Zero + Copy + Mul<Output=T>
{
self.into_xyzw().dot(q.into_xyzw())
}
pub fn normalized(self) -> Self where T: Float {
Self::from_xyzw(self.into_xyzw().normalized())
}
pub fn rotation(angle_radians: T, axis: Vec3<T>) -> Self
where T: Float
{
let two = T::from(2).unwrap();
let v = axis * (angle_radians/two).sin();
let Xyz { x, y, z } = v.to_xyz();
let w = (angle_radians/two).cos();
Self { x, y, z, w }
}
pub fn mul_vec3<V: Exactly3<T>>(self, v: V) -> V
where T: Float
{
let Xyz { x, y, z } = v.into().to_xyz();
let v = Self { x, y, z, w: T::zero() };
let r = v * self.conjugate().normalized();
V::from((self * r).into_xyzw().into_vec3())
}
pub fn into_xyzw(self) -> Xyzw<T> {
self.into()
}
pub fn from_xyzw(v: Xyzw<T>) -> Self {
Self::from(v)
}
pub fn into_xyz(self) -> Xyz<T> {
self.into()
}
}
impl<T> From<Xyzw<T>> for Quat<T> {
fn from(v: Xyzw<T>) -> Self {
let Xyzw { x, y, z, w } = v;
Self { x, y, z, w }
}
}
impl<T> From<Quat<T>> for Xyzw<T> {
fn from(v: Quat<T>) -> Self {
let Quat { x, y, z, w } = v;
Self { x, y, z, w }
}
}
impl<T> From<Quat<T>> for Xyz<T> {
fn from(v: Quat<T>) -> Self {
let Quat { x, y, z, .. } = v;
Self { x, y, z }
}
}
impl<T> Add for Quat<T> where T: Add<Output=T> {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
w: self.w + rhs.w,
}
}
}
impl<T> Sub for Quat<T> where T: Sub<Output=T> {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self {
x: self.x - rhs.x,
y: self.y - rhs.y,
z: self.z - rhs.z,
w: self.w - rhs.w,
}
}
}
impl<T> Mul for Quat<T>
where T: Copy + Mul<Output=T> + Sub<Output=T> + Zero
{
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
let p = self.into_xyz();
let q = rhs.into_xyz();
let r = p.cross(q);
let w = p * rhs.w;
let r = r + w;
let w = q * self.w;
let r = r + w;
Self {
x: r.x,
y: r.y,
z: r.z,
w: self.w * rhs.w - self.dot(rhs)
}
}
}
impl<T> Mul<T> for Quat<T>
where T: Mul<Output=T> + Clone
{
type Output = Self;
fn mul(self, rhs: T) -> Self::Output {
Self {
x: self.x * rhs.clone(),
y: self.y * rhs.clone(),
z: self.z * rhs.clone(),
w: self.w * rhs.clone(),
}
}
}