use core::num::{One, Zero}; // , Trigonometric}; use core::rand::{Rand, Rng, RngUtil}; use std::cmp::FuzzyEq; use traits::workarounds::rlmul::{RMul, LMul}; use traits::workarounds::trigonometric::Trigonometric; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; use traits::rotation::Rotation; use dim1::vec1::{Vec1, vec1}; use dim2::mat2::{Mat2, mat2}; use dim3::mat3::{Mat3, mat3}; use dim3::vec3::{Vec3}; // FIXME: use a newtype here? #[deriving(Eq)] pub struct Rotmat { priv submat: M } pub fn rotmat2>(angle: T) -> Rotmat> { let coa = Trigonometric::cos(angle); let sia = Trigonometric::sin(angle); Rotmat { submat: mat2(coa, -sia, sia, coa) } } pub fn rotmat3 + One + Sub + Add + Mul> (axis: &Vec3, angle: T) -> Rotmat> { let _1 = One::one::(); let ux = axis.x; let uy = axis.y; let uz = axis.z; let sqx = ux * ux; let sqy = uy * uy; let sqz = uz * uz; let cos = Trigonometric::cos(angle); let one_m_cos = _1 - cos; let sin = Trigonometric::sin(angle); Rotmat { submat: mat3( (sqx + (_1 - sqx) * cos), (ux * uy * one_m_cos - uz * sin), (ux * uz * one_m_cos + uy * sin), (ux * uy * one_m_cos + uz * sin), (sqy + (_1 - sqy) * cos), (uy * uz * one_m_cos - ux * sin), (ux * uz * one_m_cos - uy * sin), (uy * uz * one_m_cos + ux * sin), (sqz + (_1 - sqz) * cos)) } } impl + Trigonometric + Neg + Mul + Add + Copy> Rotation> for Rotmat> { fn rotation(&self) -> Vec1 { vec1(-Trigonometric::atan(self.submat.m12 / self.submat.m11)) } fn rotated(&self, rot: &Vec1) -> Rotmat> { rotmat2(rot.x) * *self } fn rotate(&mut self, rot: &Vec1) { *self = self.rotated(rot) } } impl + Trigonometric + Neg + Mul + Add + Copy + One + Sub> Rotation<(Vec3, T)> for Rotmat> { fn rotation(&self) -> (Vec3, T) { fail!("Not yet implemented.") } fn rotated(&self, &(axis, angle): &(Vec3, T)) -> Rotmat> { rotmat3(&axis, angle) * *self } fn rotate(&mut self, rot: &(Vec3, T)) { *self = self.rotated(rot) } } impl> Rand for Rotmat> { fn rand(rng: &R) -> Rotmat> { rotmat2(rng.gen()) } } impl + One + Sub + Add + Mul> Rand for Rotmat> { fn rand(rng: &R) -> Rotmat> { rotmat3(&rng.gen(), rng.gen()) } } impl Dim for Rotmat { fn dim() -> uint { Dim::dim::() } } impl One for Rotmat { fn one() -> Rotmat { Rotmat { submat: One::one() } } } impl> Mul, Rotmat> for Rotmat { fn mul(&self, other: &Rotmat) -> Rotmat { Rotmat { submat: self.submat.mul(&other.submat) } } } impl> RMul for Rotmat { fn rmul(&self, other: &V) -> V { self.submat.rmul(other) } } impl> LMul for Rotmat { fn lmul(&self, other: &V) -> V { self.submat.lmul(other) } } impl Inv for Rotmat { fn invert(&mut self) { self.transpose() } fn inverse(&self) -> Rotmat { self.transposed() } } impl Transpose for Rotmat { fn transposed(&self) -> Rotmat { Rotmat { submat: self.submat.transposed() } } fn transpose(&mut self) { self.submat.transpose() } } impl> FuzzyEq for Rotmat { fn fuzzy_eq(&self, other: &Rotmat) -> bool { self.submat.fuzzy_eq(&other.submat) } fn fuzzy_eq_eps(&self, other: &Rotmat, epsilon: &T) -> bool { self.submat.fuzzy_eq_eps(&other.submat, epsilon) } } impl ToStr for Rotmat { fn to_str(&self) -> ~str { ~"Rotmat {" + " submat: " + self.submat.to_str() + " }" } }