//! Quaternion definition. #![allow(missing_docs)] // we allow missing to avoid having to document the dispatch trait. use std::mem; use std::num::{Zero, One, Bounded}; use std::num; use std::rand::{Rand, Rng}; use std::slice::{Items, MutItems}; use structs::{Vec3, Pnt3, Rot3, Mat3, Vec3MulRhs, Pnt3MulRhs}; use traits::operations::{ApproxEq, Inv, POrd, POrdering, NotComparable, PartialLess, PartialGreater, PartialEqual, Axpy, ScalarAdd, ScalarSub, ScalarMul, ScalarDiv}; use traits::structure::{Cast, Indexable, Iterable, IterableMut, Dim, Shape}; use traits::geometry::{Norm, Cross, Rotation, Rotate, Transform}; /// A quaternion. #[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Rand, Zero, Show)] pub struct Quat { /// The scalar component of the quaternion. pub w: N, /// The first vector component of the quaternion. pub i: N, /// The second vector component of the quaternion. pub j: N, /// The third vector component of the quaternion. pub k: N } impl Quat { /// Creates a new quaternion from its components. #[inline] pub fn new(w: N, i: N, j: N, k: N) -> Quat { Quat { w: w, i: i, j: j, k: k } } /// The vector part `(i, j, k)` of this quaternion. #[inline] pub fn vector<'a>(&'a self) -> &'a Vec3 { // FIXME: do this require a `repr(C)` ? unsafe { mem::transmute(&self.i) } } /// The scalar part `w` of this quaternion. #[inline] pub fn scalar<'a>(&'a self) -> &'a N { &self.w } } impl> Quat { /// Replaces this quaternion by its conjugate. #[inline] pub fn conjugate(&mut self) { self.i = -self.i; self.j = -self.j; self.k = -self.k; } } impl + Clone> Inv for Quat { #[inline] fn inv_cpy(m: &Quat) -> Option> { let mut res = m.clone(); if res.inv() { Some(res) } else { None } } #[inline] fn inv(&mut self) -> bool { let sqnorm = Norm::sqnorm(self); if ApproxEq::approx_eq(&sqnorm, &Zero::zero()) { false } else { self.conjugate(); self.w = self.w / sqnorm; self.i = self.i / sqnorm; self.j = self.j / sqnorm; self.k = self.k / sqnorm; true } } } impl Norm for Quat { #[inline] fn sqnorm(q: &Quat) -> N { q.w * q.w + q.i * q.i + q.j * q.j + q.k * q.k } #[inline] fn normalize_cpy(v: &Quat) -> Quat { let n = Norm::norm(v); Quat::new(v.w / n, v.i / n, v.j / n, v.k / n) } #[inline] fn normalize(&mut self) -> N { let n = Norm::norm(self); self.w = self.w / n; self.i = self.i / n; self.j = self.j / n; self.k = self.k / n; n } } impl + Sub + Add> QuatMulRhs> for Quat { #[inline] fn binop(left: &Quat, right: &Quat) -> Quat { Quat::new( left.w * right.w - left.i * right.i - left.j * right.j - left.k * right.k, left.w * right.i + left.i * right.w + left.j * right.k - left.k * right.j, left.w * right.j - left.i * right.k + left.j * right.w + left.k * right.i, left.w * right.k + left.i * right.j - left.j * right.i + left.k * right.w) } } impl + Float + Clone> QuatDivRhs> for Quat { #[inline] fn binop(left: &Quat, right: &Quat) -> Quat { *left * Inv::inv_cpy(right).expect("Unable to invert the denominator.") } } /// A unit quaternion that can represent a 3D rotation. #[deriving(Eq, PartialEq, Encodable, Decodable, Clone, Hash, Show)] pub struct UnitQuat { q: Quat } impl UnitQuat { /// Creates a new unit quaternion from the axis-angle representation of a rotation. #[inline] pub fn new(axisangle: Vec3) -> UnitQuat { let sqang = Norm::sqnorm(&axisangle); if sqang.is_zero() { One::one() } else { let ang = sqang.sqrt(); let (s, c) = (ang / num::cast(2.0f64).unwrap()).sin_cos(); let s_ang = s / ang; unsafe { UnitQuat::new_with_unit_quat( Quat::new( c, axisangle.x * s_ang, axisangle.y * s_ang, axisangle.z * s_ang) ) } } } /// Creates a new unit quaternion from a quaternion. /// /// The input quaternion will be normalized. #[inline] pub fn new_with_quat(q: Quat) -> UnitQuat { let mut q = q; let _ = q.normalize(); UnitQuat { q: q } } /// Creates a new unit quaternion from Euler angles. /// /// The primitive rotations are applied in order: 1 roll − 2 pitch − 3 yaw. #[inline] pub fn new_with_euler_angles(roll: N, pitch: N, yaw: N) -> UnitQuat { let _0_5: N = num::cast(0.5f64).unwrap(); let (sr, cr) = (roll * _0_5).sin_cos(); let (sp, cp) = (pitch * _0_5).sin_cos(); let (sy, cy) = (yaw * _0_5).sin_cos(); unsafe { UnitQuat::new_with_unit_quat( Quat::new( cr * cp * cy + sr * sp * sy, sr * cp * cy - cr * sp * sy, cr * sp * cy + sr * cp * sy, cr * cp * sy - sr * sp * cy) ) } } /// Builds a rotation matrix from this quaternion. pub fn to_rot(&self) -> Rot3 { let _2: N = num::cast(2.0f64).unwrap(); let ww = self.q.w * self.q.w; let ii = self.q.i * self.q.i; let jj = self.q.j * self.q.j; let kk = self.q.k * self.q.k; let ij = _2 * self.q.i * self.q.j; let wk = _2 * self.q.w * self.q.k; let wj = _2 * self.q.w * self.q.j; let ik = _2 * self.q.i * self.q.k; let jk = _2 * self.q.j * self.q.k; let wi = _2 * self.q.w * self.q.i; unsafe { Rot3::new_with_mat( Mat3::new( ww + ii - jj - kk, ij - wk, wj + ik, wk + ij, ww - ii + jj - kk, jk - wi, ik - wj, wi + jk, ww - ii - jj + kk ) ) } } } impl UnitQuat { /// Creates a new unit quaternion from a quaternion. /// /// This is unsafe because the input quaternion will not be normalized. #[inline] pub unsafe fn new_with_unit_quat(q: Quat) -> UnitQuat { UnitQuat { q: q } } /// The `Quat` representation of this unit quaternion. #[inline] pub fn quat<'a>(&'a self) -> &'a Quat { &self.q } } impl One for UnitQuat { #[inline] fn one() -> UnitQuat { unsafe { UnitQuat::new_with_unit_quat(Quat::new(One::one(), Zero::zero(), Zero::zero(), Zero::zero())) } } } impl> Inv for UnitQuat { #[inline] fn inv_cpy(m: &UnitQuat) -> Option> { let mut cpy = m.clone(); cpy.inv(); Some(cpy) } #[inline] fn inv(&mut self) -> bool { self.q.conjugate(); true } } impl Rand for UnitQuat { #[inline] fn rand(rng: &mut R) -> UnitQuat { UnitQuat::new(rng.gen()) } } impl> ApproxEq for UnitQuat { #[inline] fn approx_epsilon(_: Option>) -> N { ApproxEq::approx_epsilon(None::) } #[inline] fn approx_eq(a: &UnitQuat, b: &UnitQuat) -> bool { ApproxEq::approx_eq(&a.q, &b.q) } #[inline] fn approx_eq_eps(a: &UnitQuat, b: &UnitQuat, eps: &N) -> bool { ApproxEq::approx_eq_eps(&a.q, &b.q, eps) } } impl + Clone> Div, UnitQuat> for UnitQuat { #[inline] fn div(&self, other: &UnitQuat) -> UnitQuat { UnitQuat { q: self.q / other.q } } } impl UnitQuatMulRhs> for UnitQuat { #[inline] fn binop(left: &UnitQuat, right: &UnitQuat) -> UnitQuat { UnitQuat { q: left.q * right.q } } } impl UnitQuatMulRhs> for Vec3 { #[inline] fn binop(left: &UnitQuat, right: &Vec3) -> Vec3 { let _2: N = num::one::() + num::one(); let mut t = Cross::cross(left.q.vector(), right); t.x = t.x * _2; t.y = t.y * _2; t.z = t.z * _2; Vec3::new(t.x * left.q.w, t.y * left.q.w, t.z * left.q.w) + Cross::cross(left.q.vector(), &t) + *right } } impl UnitQuatMulRhs> for Pnt3 { #[inline] fn binop(left: &UnitQuat, right: &Pnt3) -> Pnt3 { ::orig::>() + *left * *right.as_vec() } } impl Vec3MulRhs> for UnitQuat { #[inline] fn binop(left: &Vec3, right: &UnitQuat) -> Vec3 { let mut inv_quat = right.clone(); inv_quat.inv(); inv_quat * *left } } impl Pnt3MulRhs> for UnitQuat { #[inline] fn binop(left: &Pnt3, right: &UnitQuat) -> Pnt3 { ::orig::>() + *left.as_vec() * *right } } impl Rotation> for UnitQuat { #[inline] fn rotation(&self) -> Vec3 { let _2 = num::one::() + num::one(); let mut v = self.q.vector().clone(); let ang = _2 * v.normalize().atan2(self.q.w); if ang.is_zero() { num::zero() } else { Vec3::new(v.x * ang, v.y * ang, v.z * ang) } } #[inline] fn inv_rotation(&self) -> Vec3 { -self.rotation() } #[inline] fn append_rotation(&mut self, amount: &Vec3) { *self = Rotation::append_rotation_cpy(self, amount) } #[inline] fn append_rotation_cpy(t: &UnitQuat, amount: &Vec3) -> UnitQuat { *t * UnitQuat::new(amount.clone()) } #[inline] fn prepend_rotation(&mut self, amount: &Vec3) { *self = Rotation::prepend_rotation_cpy(self, amount) } #[inline] fn prepend_rotation_cpy(t: &UnitQuat, amount: &Vec3) -> UnitQuat { UnitQuat::new(amount.clone()) * *t } #[inline] fn set_rotation(&mut self, v: Vec3) { *self = UnitQuat::new(v) } } impl Rotate> for UnitQuat { #[inline] fn rotate(&self, v: &Vec3) -> Vec3 { *self * *v } #[inline] fn inv_rotate(&self, v: &Vec3) -> Vec3 { *v * *self } } impl Rotate> for UnitQuat { #[inline] fn rotate(&self, p: &Pnt3) -> Pnt3 { *self * *p } #[inline] fn inv_rotate(&self, p: &Pnt3) -> Pnt3 { *p * *self } } impl Transform> for UnitQuat { #[inline] fn transform(&self, v: &Vec3) -> Vec3 { *self * *v } #[inline] fn inv_transform(&self, v: &Vec3) -> Vec3 { *v * *self } } impl Transform> for UnitQuat { #[inline] fn transform(&self, p: &Pnt3) -> Pnt3 { *self * *p } #[inline] fn inv_transform(&self, p: &Pnt3) -> Pnt3 { *p * *self } } double_dispatch_binop_decl_trait!(Quat, QuatMulRhs) double_dispatch_binop_decl_trait!(Quat, QuatDivRhs) double_dispatch_binop_decl_trait!(Quat, QuatAddRhs) double_dispatch_binop_decl_trait!(Quat, QuatSubRhs) double_dispatch_cast_decl_trait!(Quat, QuatCast) mul_redispatch_impl!(Quat, QuatMulRhs) div_redispatch_impl!(Quat, QuatDivRhs) add_redispatch_impl!(Quat, QuatAddRhs) sub_redispatch_impl!(Quat, QuatSubRhs) cast_redispatch_impl!(Quat, QuatCast) ord_impl!(Quat, w, i, j, k) vec_axis_impl!(Quat, w, i, j, k) vec_cast_impl!(Quat, QuatCast, w, i, j, k) as_slice_impl!(Quat, 4) index_impl!(Quat) indexable_impl!(Quat, 4) at_fast_impl!(Quat, 4) new_repeat_impl!(Quat, val, w, i, j, k) dim_impl!(Quat, 3) container_impl!(Quat) add_impl!(Quat, QuatAddRhs, w, i, j, k) sub_impl!(Quat, QuatSubRhs, w, i, j, k) neg_impl!(Quat, w, i, j, k) scalar_ops_impl!(Quat, w, i, j, k) vec_mul_scalar_impl!(Quat, f64, QuatMulRhs, w, i, j, k) vec_mul_scalar_impl!(Quat, f32, QuatMulRhs, w, i, j, k) vec_mul_scalar_impl!(Quat, u64, QuatMulRhs, w, i, j, k) vec_mul_scalar_impl!(Quat, u32, QuatMulRhs, w, i, j, k) vec_mul_scalar_impl!(Quat, u16, QuatMulRhs, w, i, j, k) vec_mul_scalar_impl!(Quat, u8, QuatMulRhs, w, i, j, k) vec_mul_scalar_impl!(Quat, i64, QuatMulRhs, w, i, j, k) vec_mul_scalar_impl!(Quat, i32, QuatMulRhs, w, i, j, k) vec_mul_scalar_impl!(Quat, i16, QuatMulRhs, w, i, j, k) vec_mul_scalar_impl!(Quat, i8, QuatMulRhs, w, i, j, k) vec_mul_scalar_impl!(Quat, uint, QuatMulRhs, w, i, j, k) vec_mul_scalar_impl!(Quat, int, QuatMulRhs, w, i, j, k) vec_div_scalar_impl!(Quat, f64, QuatDivRhs, w, i, j, k) vec_div_scalar_impl!(Quat, f32, QuatDivRhs, w, i, j, k) vec_div_scalar_impl!(Quat, u64, QuatDivRhs, w, i, j, k) vec_div_scalar_impl!(Quat, u32, QuatDivRhs, w, i, j, k) vec_div_scalar_impl!(Quat, u16, QuatDivRhs, w, i, j, k) vec_div_scalar_impl!(Quat, u8, QuatDivRhs, w, i, j, k) vec_div_scalar_impl!(Quat, i64, QuatDivRhs, w, i, j, k) vec_div_scalar_impl!(Quat, i32, QuatDivRhs, w, i, j, k) vec_div_scalar_impl!(Quat, i16, QuatDivRhs, w, i, j, k) vec_div_scalar_impl!(Quat, i8, QuatDivRhs, w, i, j, k) vec_div_scalar_impl!(Quat, uint, QuatDivRhs, w, i, j, k) vec_div_scalar_impl!(Quat, int, QuatDivRhs, w, i, j, k) vec_add_scalar_impl!(Quat, f64, QuatAddRhs, w, i, j, k) vec_add_scalar_impl!(Quat, f32, QuatAddRhs, w, i, j, k) vec_add_scalar_impl!(Quat, u64, QuatAddRhs, w, i, j, k) vec_add_scalar_impl!(Quat, u32, QuatAddRhs, w, i, j, k) vec_add_scalar_impl!(Quat, u16, QuatAddRhs, w, i, j, k) vec_add_scalar_impl!(Quat, u8, QuatAddRhs, w, i, j, k) vec_add_scalar_impl!(Quat, i64, QuatAddRhs, w, i, j, k) vec_add_scalar_impl!(Quat, i32, QuatAddRhs, w, i, j, k) vec_add_scalar_impl!(Quat, i16, QuatAddRhs, w, i, j, k) vec_add_scalar_impl!(Quat, i8, QuatAddRhs, w, i, j, k) vec_add_scalar_impl!(Quat, uint, QuatAddRhs, w, i, j, k) vec_add_scalar_impl!(Quat, int, QuatAddRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, f64, QuatSubRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, f32, QuatSubRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, u64, QuatSubRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, u32, QuatSubRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, u16, QuatSubRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, u8, QuatSubRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, i64, QuatSubRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, i32, QuatSubRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, i16, QuatSubRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, i8, QuatSubRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, uint, QuatSubRhs, w, i, j, k) vec_sub_scalar_impl!(Quat, int, QuatSubRhs, w, i, j, k) approx_eq_impl!(Quat, w, i, j, k) from_iterator_impl!(Quat, iterator, iterator, iterator, iterator) bounded_impl!(Quat, w, i, j, k) axpy_impl!(Quat, w, i, j, k) iterable_impl!(Quat, 4) iterable_mut_impl!(Quat, 4) double_dispatch_binop_decl_trait!(UnitQuat, UnitQuatMulRhs) mul_redispatch_impl!(UnitQuat, UnitQuatMulRhs) dim_impl!(UnitQuat, 3) as_slice_impl!(UnitQuat, 4) index_impl!(UnitQuat) indexable_impl!(UnitQuat, 5)