From eda42604b7bed080c0e52ce8749564df4df60d26 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 26 Nov 2012 03:44:24 +1000 Subject: [PATCH] Use Angle type with triganomic functions --- src/funs/projection.rs | 5 +- src/funs/transform.rs | 9 +- src/funs/trig.rs | 523 +++++++++++++++++++---------------------- src/quat.rs | 6 +- 4 files changed, 253 insertions(+), 290 deletions(-) diff --git a/src/funs/projection.rs b/src/funs/projection.rs index 3200987..1240895 100644 --- a/src/funs/projection.rs +++ b/src/funs/projection.rs @@ -1,4 +1,5 @@ use funs::trig::*; +use angle::Angle; use mat::Mat4; use num::cast::cast; use num::consts::pi; @@ -11,8 +12,8 @@ use num::ext::FloatExt; // http://www.opengl.org/wiki/GluPerspective_code // #[inline(always)] -pure fn perspective(fovy: T, aspectRatio: T, near: T, far: T) -> Mat4 { - let ymax = near * tan(&(fovy * pi() / cast(360))); +pure fn perspective(fovy: Angle, aspectRatio: T, near: T, far: T) -> Mat4 { + let ymax = near * tan(&fovy); let xmax = ymax * aspectRatio; return frustum(-xmax, xmax, -ymax, ymax, near, far); } diff --git a/src/funs/transform.rs b/src/funs/transform.rs index 3520371..f818091 100644 --- a/src/funs/transform.rs +++ b/src/funs/transform.rs @@ -3,10 +3,9 @@ use angle::Angle; use mat::{Mat3, Mat4}; use num::cast::*; -pub pure fn mat3_from_rotation(theta: Angle, axis: Vec3) -> Mat3 { - let rad = theta.radians(); - let c: T = cos(&rad); - let s: T = sin(&rad); +pub pure fn mat3_from_rotation(theta: Angle, axis: Vec3) -> Mat3 { + let c: T = cos(&theta); + let s: T = sin(&theta); let _0: T = cast(0); let _1: T = cast(1); let t: T = _1 - c; @@ -16,6 +15,6 @@ pub pure fn mat3_from_rotation(theta: Angle, axis: V t * axis.x * axis.z - s - axis.y, t * axis.y * axis.z - s * axis.x, t * axis.z * axis.z + c) } -pub pure fn mat4_from_rotation(theta: Angle, axis: Vec3) -> Mat4 { +pub pure fn mat4_from_rotation(theta: Angle, axis: Vec3) -> Mat4 { mat3_from_rotation(theta, axis).to_mat4() } \ No newline at end of file diff --git a/src/funs/trig.rs b/src/funs/trig.rs index b5619bf..55d8e7a 100644 --- a/src/funs/trig.rs +++ b/src/funs/trig.rs @@ -1,327 +1,290 @@ use num::cast::*; +use angle::*; use vec::{Vec3, Vec2, Vec4}; -pub trait AngleConv { - pure fn to_degrees() -> self; - pure fn to_radians() -> self; +/// +/// Triganomic functions +/// +/// http://en.wikipedia.org/wiki/Trigonometric_functions +/// +priv trait Trig { + pure fn sin() -> T; + pure fn cos() -> T; + pure fn tan() -> T; } -#[inline(always)] pub pure fn degrees(theta: &T) -> T { theta.to_degrees() } -#[inline(always)] pub pure fn radians(theta: &T) -> T { theta.to_radians() } +#[inline(always)] pub pure fn sin, R>(theta: &T) -> R { theta.sin() } +#[inline(always)] pub pure fn cos, R>(theta: &T) -> R { theta.cos() } +#[inline(always)] pub pure fn tan, R>(theta: &T) -> R { theta.tan() } -pub impl f32: AngleConv { - #[inline(always)] pure fn to_degrees() -> f32 { self * (180f32 / f32::consts::pi) } - #[inline(always)] pure fn to_radians() -> f32 { self * (f32::consts::pi / 180f32) } +priv impl Angle: Trig { + #[inline(always)] pure fn sin() -> T { cast(f64::sin(cast(self.radians()))) } + #[inline(always)] pure fn cos() -> T { cast(f64::cos(cast(self.radians()))) } + #[inline(always)] pure fn tan() -> T { cast(f64::tan(cast(self.radians()))) } } -pub impl f64: AngleConv { - #[inline(always)] pure fn to_degrees() -> f64 { self * (180f64 / f64::consts::pi) } - #[inline(always)] pure fn to_radians() -> f64 { self * (f64::consts::pi / 180f64) } +/// +/// Inverse triganomic functions +/// +/// http://en.wikipedia.org/wiki/Inverse_trigonometric_functions +/// +pub trait InvTrig { + pure fn asin() -> Angle; + pure fn acos() -> Angle; + pure fn atan() -> Angle; } -pub impl float: AngleConv { - #[inline(always)] pure fn to_degrees() -> float { self * (180f / float::consts::pi) } - #[inline(always)] pure fn to_radians() -> float { self * (float::consts::pi / 180f) } +#[inline(always)] pub pure fn asin(x: &T) -> Angle { x.asin() } +#[inline(always)] pub pure fn acos(x: &T) -> Angle { x.acos() } +#[inline(always)] pub pure fn atan(x: &T) -> Angle { x.atan() } + +pub impl f32: InvTrig { + #[inline(always)] pure fn asin() -> Angle { radians(f32::asin(self)) } + #[inline(always)] pure fn acos() -> Angle { radians(f32::acos(self)) } + #[inline(always)] pure fn atan() -> Angle { radians(f32::atan(self)) } } -pub impl Vec2: AngleConv { - #[inline(always)] - pure fn to_degrees() -> Vec2 { - Vec2::new(degrees(&self[0]), - degrees(&self[1])) - } - - #[inline(always)] - pure fn to_radians() -> Vec2 { - Vec2::new(radians(&self[0]), - radians(&self[1])) - } +pub impl f64: InvTrig { + #[inline(always)] pure fn asin() -> Angle { radians(f64::asin(self)) } + #[inline(always)] pure fn acos() -> Angle { radians(f64::acos(self)) } + #[inline(always)] pure fn atan() -> Angle { radians(f64::atan(self)) } } -pub impl Vec3: AngleConv { - #[inline(always)] - pure fn to_degrees() -> Vec3 { - Vec3::new(degrees(&self[0]), - degrees(&self[1]), - degrees(&self[2])) - } - - #[inline(always)] - pure fn to_radians() -> Vec3 { - Vec3::new(radians(&self[0]), - radians(&self[1]), - radians(&self[2])) - } +pub impl float: InvTrig { + #[inline(always)] pure fn asin() -> Angle { radians(f64::asin(cast(self)).to_float()) } + #[inline(always)] pure fn acos() -> Angle { radians(f64::acos(cast(self)).to_float()) } + #[inline(always)] pure fn atan() -> Angle { radians(f64::atan(cast(self)).to_float()) } } -pub impl Vec4: AngleConv { - #[inline(always)] - pure fn to_degrees() -> Vec4 { - Vec4::new(degrees(&self[0]), - degrees(&self[1]), - degrees(&self[2]), - degrees(&self[3])) - } - - #[inline(always)] - pure fn to_radians() -> Vec4 { - Vec4::new(radians(&self[0]), - radians(&self[1]), - radians(&self[2]), - radians(&self[3])) - } -} - - -pub trait Trig { - pure fn sin() -> self; - pure fn cos() -> self; - pure fn tan() -> self; - pure fn asin() -> self; - pure fn acos() -> self; - pure fn atan() -> self; +/// +/// Hyperbolic functions +/// +/// http://en.wikipedia.org/wiki/Hyperbolic_function +/// +pub trait Hyp { pure fn sinh() -> self; pure fn cosh() -> self; pure fn tanh() -> self; + // pure fn asinh() -> self; + // pure fn acosh() -> self; + // pure fn atanh() -> self; } -#[inline(always)] pub pure fn sin(theta: &T) -> T { theta.sin() } -#[inline(always)] pub pure fn cos(theta: &T) -> T { theta.cos() } -#[inline(always)] pub pure fn tan(theta: &T) -> T { theta.tan() } -#[inline(always)] pub pure fn asin(x: &T) -> T { x.asin() } -#[inline(always)] pub pure fn acos(x: &T) -> T { x.acos() } -#[inline(always)] pub pure fn atan(x: &T) -> T { x.atan() } -#[inline(always)] pub pure fn sinh(x: &T) -> T { x.sinh() } -#[inline(always)] pub pure fn cosh(x: &T) -> T { x.cosh() } -#[inline(always)] pub pure fn tanh(x: &T) -> T { x.tanh() } +#[inline(always)] pub pure fn sinh(x: &T) -> T { x.sinh() } +#[inline(always)] pub pure fn cosh(x: &T) -> T { x.cosh() } +#[inline(always)] pub pure fn tanh(x: &T) -> T { x.tanh() } -pub impl f32: Trig { - #[inline(always)] pure fn sin() -> f32 { f32::sin (self) } - #[inline(always)] pure fn cos() -> f32 { f32::cos (self) } - #[inline(always)] pure fn tan() -> f32 { f32::tan (self) } - #[inline(always)] pure fn asin() -> f32 { f32::asin(self) } - #[inline(always)] pure fn acos() -> f32 { f32::acos(self) } - #[inline(always)] pure fn atan() -> f32 { f32::atan(self) } +pub impl f32: Hyp { #[inline(always)] pure fn sinh() -> f32 { f32::sinh(self) } #[inline(always)] pure fn cosh() -> f32 { f32::cosh(self) } #[inline(always)] pure fn tanh() -> f32 { f32::tanh(self) } } -pub impl f64: Trig { - #[inline(always)] pure fn sin() -> f64 { f64::sin (self) } - #[inline(always)] pure fn cos() -> f64 { f64::cos (self) } - #[inline(always)] pure fn tan() -> f64 { f64::tan (self) } - #[inline(always)] pure fn asin() -> f64 { f64::asin(self) } - #[inline(always)] pure fn acos() -> f64 { f64::acos(self) } - #[inline(always)] pure fn atan() -> f64 { f64::atan(self) } +pub impl f64: Hyp { #[inline(always)] pure fn sinh() -> f64 { f64::sinh(self) } #[inline(always)] pure fn cosh() -> f64 { f64::cosh(self) } #[inline(always)] pure fn tanh() -> f64 { f64::tanh(self) } } -pub impl float: Trig { - #[inline(always)] pure fn sin() -> float { cast(f64::sin (cast(self))) } - #[inline(always)] pure fn cos() -> float { cast(f64::cos (cast(self))) } - #[inline(always)] pure fn tan() -> float { cast(f64::tan (cast(self))) } - #[inline(always)] pure fn asin() -> float { cast(f64::asin(cast(self))) } - #[inline(always)] pure fn acos() -> float { cast(f64::acos(cast(self))) } - #[inline(always)] pure fn atan() -> float { cast(f64::atan(cast(self))) } +pub impl float: Hyp { #[inline(always)] pure fn sinh() -> float { cast(f64::sinh(cast(self))) } #[inline(always)] pure fn cosh() -> float { cast(f64::cosh(cast(self))) } #[inline(always)] pure fn tanh() -> float { cast(f64::tanh(cast(self))) } } -pub impl Vec2: Trig { - #[inline(always)] - pure fn sin() -> Vec2 { - Vec2::new(sin(&self[0]), - sin(&self[1])) - } - - #[inline(always)] - pure fn cos() -> Vec2 { - Vec2::new(cos(&self[0]), - cos(&self[1])) - } - - #[inline(always)] - pure fn tan() -> Vec2 { - Vec2::new(tan(&self[0]), - tan(&self[1])) - } - - #[inline(always)] - pure fn asin() -> Vec2 { - Vec2::new(asin(&self[0]), - asin(&self[1])) - } - - #[inline(always)] - pure fn acos() -> Vec2 { - Vec2::new(acos(&self[0]), - acos(&self[1])) - } - - #[inline(always)] - pure fn atan() -> Vec2 { - Vec2::new(atan(&self[0]), - atan(&self[1])) - } - - #[inline(always)] - pure fn sinh() -> Vec2 { - Vec2::new(sinh(&self[0]), - sinh(&self[1])) - } - - #[inline(always)] - pure fn cosh() -> Vec2 { - Vec2::new(cosh(&self[0]), - cosh(&self[1])) - } - - #[inline(always)] - pure fn tanh() -> Vec2 { - Vec2::new(tanh(&self[0]), - tanh(&self[1])) - } -} -pub impl Vec3: Trig { - #[inline(always)] - pure fn sin() -> Vec3 { - Vec3::new(sin(&self[0]), - sin(&self[1]), - sin(&self[2])) - } - - #[inline(always)] - pure fn cos() -> Vec3 { - Vec3::new(cos(&self[0]), - cos(&self[1]), - cos(&self[2])) - } - - #[inline(always)] - pure fn tan() -> Vec3 { - Vec3::new(tan(&self[0]), - tan(&self[1]), - tan(&self[2])) - } - - #[inline(always)] - pure fn asin() -> Vec3 { - Vec3::new(asin(&self[0]), - asin(&self[1]), - asin(&self[2])) - } - - #[inline(always)] - pure fn acos() -> Vec3 { - Vec3::new(acos(&self[0]), - acos(&self[1]), - acos(&self[2])) - } - - #[inline(always)] - pure fn atan() -> Vec3 { - Vec3::new(atan(&self[0]), - atan(&self[1]), - atan(&self[2])) - } - - #[inline(always)] - pure fn sinh() -> Vec3 { - Vec3::new(sinh(&self[0]), - sinh(&self[1]), - sinh(&self[2])) - } - - #[inline(always)] - pure fn cosh() -> Vec3 { - Vec3::new(cosh(&self[0]), - cosh(&self[1]), - cosh(&self[2])) - } - - #[inline(always)] - pure fn tanh() -> Vec3 { - Vec3::new(tanh(&self[0]), - tanh(&self[1]), - tanh(&self[2])) - } -} -pub impl Vec4: Trig { - #[inline(always)] - pure fn sin() -> Vec4 { - Vec4::new(sin(&self[0]), - sin(&self[1]), - sin(&self[2]), - sin(&self[3])) - } +// pub impl Vec2: Trig { +// #[inline(always)] +// pure fn sin() -> Vec2 { +// Vec2::new(sin(&self[0]), +// sin(&self[1])) +// } - #[inline(always)] - pure fn cos() -> Vec4 { - Vec4::new(cos(&self[0]), - cos(&self[1]), - cos(&self[2]), - cos(&self[3])) - } +// #[inline(always)] +// pure fn cos() -> Vec2 { +// Vec2::new(cos(&self[0]), +// cos(&self[1])) +// } - #[inline(always)] - pure fn tan() -> Vec4 { - Vec4::new(tan(&self[0]), - tan(&self[1]), - tan(&self[2]), - tan(&self[3])) - } +// #[inline(always)] +// pure fn tan() -> Vec2 { +// Vec2::new(tan(&self[0]), +// tan(&self[1])) +// } - #[inline(always)] - pure fn asin() -> Vec4 { - Vec4::new(asin(&self[0]), - asin(&self[1]), - asin(&self[2]), - asin(&self[3])) - } +// #[inline(always)] +// pure fn asin() -> Vec2 { +// Vec2::new(asin(&self[0]), +// asin(&self[1])) +// } - #[inline(always)] - pure fn acos() -> Vec4 { - Vec4::new(acos(&self[0]), - acos(&self[1]), - acos(&self[2]), - acos(&self[3])) - } +// #[inline(always)] +// pure fn acos() -> Vec2 { +// Vec2::new(acos(&self[0]), +// acos(&self[1])) +// } - #[inline(always)] - pure fn atan() -> Vec4 { - Vec4::new(atan(&self[0]), - atan(&self[1]), - atan(&self[2]), - atan(&self[3])) - } +// #[inline(always)] +// pure fn atan() -> Vec2 { +// Vec2::new(atan(&self[0]), +// atan(&self[1])) +// } - #[inline(always)] - pure fn sinh() -> Vec4 { - Vec4::new(sinh(&self[0]), - sinh(&self[1]), - sinh(&self[2]), - sinh(&self[3])) - } +// #[inline(always)] +// pure fn sinh() -> Vec2 { +// Vec2::new(sinh(&self[0]), +// sinh(&self[1])) +// } - #[inline(always)] - pure fn cosh() -> Vec4 { - Vec4::new(cosh(&self[0]), - cosh(&self[1]), - cosh(&self[2]), - cosh(&self[3])) - } +// #[inline(always)] +// pure fn cosh() -> Vec2 { +// Vec2::new(cosh(&self[0]), +// cosh(&self[1])) +// } - #[inline(always)] - pure fn tanh() -> Vec4 { - Vec4::new(tanh(&self[0]), - tanh(&self[1]), - tanh(&self[2]), - tanh(&self[3])) - } -} \ No newline at end of file +// #[inline(always)] +// pure fn tanh() -> Vec2 { +// Vec2::new(tanh(&self[0]), +// tanh(&self[1])) +// } +// } + +// pub impl Vec3: Trig { +// #[inline(always)] +// pure fn sin() -> Vec3 { +// Vec3::new(sin(&self[0]), +// sin(&self[1]), +// sin(&self[2])) +// } + +// #[inline(always)] +// pure fn cos() -> Vec3 { +// Vec3::new(cos(&self[0]), +// cos(&self[1]), +// cos(&self[2])) +// } + +// #[inline(always)] +// pure fn tan() -> Vec3 { +// Vec3::new(tan(&self[0]), +// tan(&self[1]), +// tan(&self[2])) +// } + +// #[inline(always)] +// pure fn asin() -> Vec3 { +// Vec3::new(asin(&self[0]), +// asin(&self[1]), +// asin(&self[2])) +// } + +// #[inline(always)] +// pure fn acos() -> Vec3 { +// Vec3::new(acos(&self[0]), +// acos(&self[1]), +// acos(&self[2])) +// } + +// #[inline(always)] +// pure fn atan() -> Vec3 { +// Vec3::new(atan(&self[0]), +// atan(&self[1]), +// atan(&self[2])) +// } + +// #[inline(always)] +// pure fn sinh() -> Vec3 { +// Vec3::new(sinh(&self[0]), +// sinh(&self[1]), +// sinh(&self[2])) +// } + +// #[inline(always)] +// pure fn cosh() -> Vec3 { +// Vec3::new(cosh(&self[0]), +// cosh(&self[1]), +// cosh(&self[2])) +// } + +// #[inline(always)] +// pure fn tanh() -> Vec3 { +// Vec3::new(tanh(&self[0]), +// tanh(&self[1]), +// tanh(&self[2])) +// } +// } + +// pub impl Vec4: Trig { +// #[inline(always)] +// pure fn sin() -> Vec4 { +// Vec4::new(sin(&self[0]), +// sin(&self[1]), +// sin(&self[2]), +// sin(&self[3])) +// } + +// #[inline(always)] +// pure fn cos() -> Vec4 { +// Vec4::new(cos(&self[0]), +// cos(&self[1]), +// cos(&self[2]), +// cos(&self[3])) +// } + +// #[inline(always)] +// pure fn tan() -> Vec4 { +// Vec4::new(tan(&self[0]), +// tan(&self[1]), +// tan(&self[2]), +// tan(&self[3])) +// } + +// #[inline(always)] +// pure fn asin() -> Vec4 { +// Vec4::new(asin(&self[0]), +// asin(&self[1]), +// asin(&self[2]), +// asin(&self[3])) +// } + +// #[inline(always)] +// pure fn acos() -> Vec4 { +// Vec4::new(acos(&self[0]), +// acos(&self[1]), +// acos(&self[2]), +// acos(&self[3])) +// } + +// #[inline(always)] +// pure fn atan() -> Vec4 { +// Vec4::new(atan(&self[0]), +// atan(&self[1]), +// atan(&self[2]), +// atan(&self[3])) +// } + +// #[inline(always)] +// pure fn sinh() -> Vec4 { +// Vec4::new(sinh(&self[0]), +// sinh(&self[1]), +// sinh(&self[2]), +// sinh(&self[3])) +// } + +// #[inline(always)] +// pure fn cosh() -> Vec4 { +// Vec4::new(cosh(&self[0]), +// cosh(&self[1]), +// cosh(&self[2]), +// cosh(&self[3])) +// } + +// #[inline(always)] +// pure fn tanh() -> Vec4 { +// Vec4::new(tanh(&self[0]), +// tanh(&self[1]), +// tanh(&self[2]), +// tanh(&self[3])) +// } +// } \ No newline at end of file diff --git a/src/quat.rs b/src/quat.rs index 76028b5..840342b 100644 --- a/src/quat.rs +++ b/src/quat.rs @@ -70,7 +70,7 @@ pub impl Quat { } } -pub impl Quat: Quaternion { +pub impl Quat: Quaternion { #[inline(always)] static pure fn identity() -> Quat { Quat::new(NumCast::one(), @@ -222,8 +222,8 @@ pub impl Quat: Quaternion } #[inline(always)] - pub pure fn from_axis_angle(axis: Vec3, theta: T) -> Quat { - let half = radians(&theta) / cast(2); + pub pure fn from_axis_angle(axis: Vec3, theta: Angle) -> Quat { + let half = theta / cast(2); Quat::from_sv(cos(&half), axis.mul_t(sin(&half))) }