use core::cmp::{Eq, Ord}; use core::f64::consts::pi; use funs::triganomic::{cos, sin}; use mat::{Mat3, Mat4}; use num::cast::{NumCast, cast}; use quat::Quat; use vec::Vec3; /** * The base trait for anglular units */ pub trait Angle: Add , Sub , Mul , Div , Modulo , Neg , Eq, Ord { pure fn to_radians() -> Radians; pure fn to_degrees() -> Degrees; } pub enum Radians = T; pub impl Radians: Angle { #[inline(always)] pure fn to_radians() -> Radians { self } #[inline(always)] pure fn to_degrees() -> Degrees { Degrees(*self * cast(180.0 / pi)) } #[inline(always)] pure fn add(rhs: &Radians) -> Radians { Radians(*self + **rhs) } #[inline(always)] pure fn sub(rhs: &Radians) -> Radians { Radians(*self - **rhs) } #[inline(always)] pure fn mul(rhs: &T) -> Radians { Radians(*self * *rhs) } #[inline(always)] pure fn div(rhs: &T) -> Radians { Radians(*self / *rhs) } #[inline(always)] pure fn modulo(rhs: &T) -> Radians { Radians(*self % *rhs) } #[inline(always)] pure fn neg() -> Radians { Radians(-*self) } } pub impl Radians: Eq { #[inline(always)] pure fn eq(other: &Radians) -> bool { *self == **other } #[inline(always)] pure fn ne(other: &Radians) -> bool { *self != **other } } pub impl Radians: Ord { #[inline(always)] pure fn lt(other: &Radians) -> bool { *self < **other } #[inline(always)] pure fn le(other: &Radians) -> bool { *self <= **other } #[inline(always)] pure fn ge(other: &Radians) -> bool { *self >= **other } #[inline(always)] pure fn gt(other: &Radians) -> bool { *self > **other } } pub enum Degrees = T; pub impl Degrees: Angle { #[inline(always)] pure fn to_radians() -> Radians { Radians(*self * cast(pi / 180.0)) } #[inline(always)] pure fn to_degrees() -> Degrees { self } #[inline(always)] pure fn add(rhs: &Degrees) -> Degrees { Degrees(*self + **rhs) } #[inline(always)] pure fn sub(rhs: &Degrees) -> Degrees { Degrees(*self - **rhs) } #[inline(always)] pure fn mul(rhs: &T) -> Degrees { Degrees(*self * *rhs) } #[inline(always)] pure fn div(rhs: &T) -> Degrees { Degrees(*self / *rhs) } #[inline(always)] pure fn modulo(rhs: &T) -> Degrees { Degrees(*self % *rhs) } #[inline(always)] pure fn neg() -> Degrees { Degrees(-*self) } } pub impl Degrees: Eq { #[inline(always)] pure fn eq(other: &Degrees) -> bool { *self == **other } #[inline(always)] pure fn ne(other: &Degrees) -> bool { *self != **other } } pub impl Degrees: Ord { #[inline(always)] pure fn lt(other: &Degrees) -> bool { *self < **other } #[inline(always)] pure fn le(other: &Degrees) -> bool { *self <= **other } #[inline(always)] pure fn ge(other: &Degrees) -> bool { *self >= **other } #[inline(always)] pure fn gt(other: &Degrees) -> bool { *self > **other } } /** * An angular rotation around an arbitary axis */ pub struct Rotation { theta: Radians, axis: Vec3, } pub impl Rotation { static pure fn new(theta: Radians, axis: Vec3) -> Rotation { Rotation { theta: move theta, axis: move axis } } pure fn to_mat3() -> Mat3 { let c: T = cos(&self.theta); let s: T = sin(&self.theta); let _0: T = cast(0); let _1: T = cast(1); let t: T = _1 - c; let x = self.axis.x; let y = self.axis.y; let z = self.axis.z; Mat3::new(t * x * x + c, t * x * y + s * z, t * x * z - s * y, t * x * y - s * z, t * y * y + c, t * y * z + s * x, t * x * z - s - y, t * y * z - s * x, t * z * z + c) } pure fn to_mat4() -> Mat4 { self.to_mat3().to_mat4() } pure fn to_quat() -> Quat { let half = self.theta / cast(2); Quat::from_sv(cos(&half), self.axis.mul_t(sin(&half))) } } pub struct Euler { x: Radians, // pitch y: Radians, // yaw z: Radians, // roll }