use std::num::{One, Zero}; use std::rand::{Rand, Rng, RngUtil}; use std::cmp::ApproxEq; use traits::workarounds::rlmul::{RMul, LMul}; use traits::dim::Dim; use traits::inv::Inv; use traits::transpose::Transpose; use traits::rotation::Rotation; use traits::delta_transform::{DeltaTransform, DeltaTransformVector}; use dim1::vec1::Vec1; use dim2::mat2::Mat2; use dim3::mat3::Mat3; use dim3::vec3::{Vec3}; #[deriving(Eq, ToStr)] pub struct Rotmat { priv submat: M } impl Rotmat { fn submat(&self) -> M { self.submat } } pub fn rotmat2>(angle: N) -> Rotmat> { let coa = angle.cos(); let sia = angle.sin(); Rotmat { submat: Mat2::new(coa, -sia, sia, coa) } } pub fn rotmat3 + One + Sub + Add + Mul> (axis: &Vec3, angle: N) -> 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 = angle.cos(); let one_m_cos = _1 - cos; let sin = angle.sin(); Rotmat { submat: Mat3::new( (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::new(-(self.submat.m12 / self.submat.m11).atan()) } 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, N)> for Rotmat> { fn rotation(&self) -> (Vec3, N) { fail!("Not yet implemented.") } fn rotated(&self, &(axis, angle): &(Vec3, N)) -> Rotmat> { rotmat3(&axis, angle) * *self } fn rotate(&mut self, rot: &(Vec3, N)) { *self = self.rotated(rot) } } impl> Rand for Rotmat> { fn rand(rng: &mut R) -> Rotmat> { rotmat2(rng.gen()) } } impl + One + Sub + Add + Mul> Rand for Rotmat> { fn rand(rng: &mut 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 DeltaTransform for Rotmat { fn delta_transform(&self) -> M { self.submat } } impl + Copy, V: Copy> DeltaTransformVector for Rotmat { fn delta_transform_vector(&self, v: &V) -> V { self.submat.rmul(v) } } 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, M: ApproxEq> ApproxEq for Rotmat { fn approx_epsilon() -> N { ApproxEq::approx_epsilon::() } fn approx_eq(&self, other: &Rotmat) -> bool { self.submat.approx_eq(&other.submat) } fn approx_eq_eps(&self, other: &Rotmat, epsilon: &N) -> bool { self.submat.approx_eq_eps(&other.submat, epsilon) } }