diff --git a/src/angle.rs b/src/angle.rs index 869a6fc..7cb6066 100644 --- a/src/angle.rs +++ b/src/angle.rs @@ -1,8 +1,14 @@ use core::cmp::{Eq, Ord}; use core::f64::consts::pi; -use num::cast::*; +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 @@ -66,11 +72,41 @@ pub impl Degrees: Ord { #[inline(always)] pure fn gt(other: &Degrees) -> bool { *self > **other } } -pub struct AxialRotation { +/** + * An angular rotation around an arbitary axis + */ +pub struct Rotation { axis: Vec3, theta: Radians, } +pub impl Rotation { + 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 diff --git a/src/funs/test/test_transform.rs b/src/funs/test/test_transform.rs deleted file mode 100644 index 907ec5c..0000000 --- a/src/funs/test/test_transform.rs +++ /dev/null @@ -1,34 +0,0 @@ -use funs::transform::*; -use angle::Degrees; -use mat::Mat4; -use vec::{Vec3, Vec4}; - -#[test] -fn test_mat4_from_rotation() { - { - let pos = Vec4::new(1f32, 0f32, 0f32, 1f32); - // let tform = mat4_from_rotation(180f32, Vec3::unit_z()); - let tform = mat4_from_rotation(Degrees(180f32).to_radians(), Vec3::new(0f32, 0f32, 1f32)); - let newpos = tform.mul_v(&pos); - - let expected = Vec4::new(-1f32, 0f32, 0f32, 1f32); - - assert newpos == expected; - } - { - let pos = Vec4::new(4f32, 0f32, 0f32, 1f32); - - // let tform_a = mat4_from_rotation(90f32, Vec3::unit_y()); - // let tform_b = mat4_from_rotation(90f32, -Vec3::unit_y()); - let tform_a = mat4_from_rotation(Degrees(90f32).to_radians(), Vec3::new(0f32, 1f32, 0f32)); - let tform_b = mat4_from_rotation(Degrees(90f32).to_radians(), -Vec3::new(0f32, 1f32, 0f32)); - let newpos_a = tform_a.mul_v(&pos); - let newpos_b = tform_b.mul_v(&pos); - - let expected_a = Vec4::new(0f32, 0f32, -4f32, 1f32); - let expected_b = Vec4::new(0f32, 0f32, 4f32, 1f32); - - assert newpos_a == expected_a; - assert newpos_b == expected_b; - } -} \ No newline at end of file diff --git a/src/funs/transform.rs b/src/funs/transform.rs deleted file mode 100644 index 462520f..0000000 --- a/src/funs/transform.rs +++ /dev/null @@ -1,21 +0,0 @@ -use funs::triganomic::{cos, sin}; -use angle::Radians; -use mat::{Mat3, Mat4}; -use num::cast::{NumCast, cast}; -use vec::Vec3; - -pub pure fn mat3_from_rotation(theta: Radians, 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; - - Mat3::new(t * axis.x * axis.x + c, t * axis.x * axis.y + s * axis.z, t * axis.x * axis.z - s * axis.y, - t * axis.x * axis.y - s * axis.z, t * axis.y * axis.y + c, t * axis.y * axis.z + s * axis.x, - 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: Radians, axis: Vec3) -> Mat4 { - mat3_from_rotation(theta, axis).to_mat4() -} \ No newline at end of file diff --git a/src/lmath.rc b/src/lmath.rc index a3a6d47..6fc2b3f 100644 --- a/src/lmath.rc +++ b/src/lmath.rc @@ -39,13 +39,11 @@ pub mod funs { pub mod exponential; pub mod projection; pub mod relational; - pub mod transform; pub mod triganomic; #[test] mod test { mod test_common; mod test_relational; - mod test_transform; } } \ No newline at end of file diff --git a/src/quat.rs b/src/quat.rs index 55f0549..771dd64 100644 --- a/src/quat.rs +++ b/src/quat.rs @@ -220,12 +220,6 @@ pub impl Quat: Quaternion { self.mul_t(cos(&theta)).add_q(&q.mul_t(sin(&theta))) } - - #[inline(always)] - pub pure fn from_axis_angle(axis: Vec3, theta: Radians) -> Quat { - let half = theta / cast(2); - Quat::from_sv(cos(&half), axis.mul_t(sin(&half))) - } #[inline(always)] pure fn to_mat3() -> Mat3 { diff --git a/src/test/test_angle.rs b/src/test/test_angle.rs index a0f948b..ca9461b 100644 --- a/src/test/test_angle.rs +++ b/src/test/test_angle.rs @@ -1,6 +1,8 @@ use core::float::consts::pi; use angle::*; +use mat::Mat4; +use vec::{Vec3, Vec4}; #[test] fn test_radians() { @@ -44,4 +46,44 @@ fn test_degrees() { assert *(Degrees(180.0) / 2.0) == *Degrees(90.0); assert *(Degrees(540.0) % (360.0)) == *Degrees(180.0); assert *(-Degrees(180.0)) == *Degrees(-180.0); +} + + + +#[test] +fn test_rotation() { + { + let pos = Vec4::new(1.0, 0.0, 0.0, 1.0); // the position to transform + let rot = Rotation { + axis: Vec3::new(0.0, 0.0, 1.0), // unit_z + theta: Degrees(180.0).to_radians(), + }; + + let newpos = rot.to_mat4().mul_v(&pos); + let expected_pos = Vec4::new(-1.0, 0.0, 0.0, 1.0); + + assert newpos == expected_pos; + } + { + let pos = Vec4::new(4f32, 0f32, 0f32, 1f32); + + let rot_a = Rotation { + axis: Vec3::new(0f32, 1f32, 0f32), // unit_y + theta: Degrees(90f32).to_radians(), + }; + + let rot_b = Rotation { + axis: -Vec3::new(0f32, 1f32, 0f32), // -unit_y + theta: Degrees(90f32).to_radians(), + }; + + let newpos_a = rot_a.to_mat4().mul_v(&pos); + let newpos_b = rot_b.to_mat4().mul_v(&pos); + + let expected_pos_a = Vec4::new(0f32, 0f32, -4f32, 1f32); + let expected_pos_b = Vec4::new(0f32, 0f32, 4f32, 1f32); + + assert newpos_a == expected_pos_a; + assert newpos_b == expected_pos_b; + } } \ No newline at end of file