Move axial rotation conversions to angle module

This commit is contained in:
Brendan Zabarauskas 2012-11-26 17:31:02 +10:00
parent 11b5b12d0a
commit c3071b6260
6 changed files with 80 additions and 65 deletions

View file

@ -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<T>: Add<self,self>
, Sub<self,self>
, Mul<T,self>
@ -66,11 +72,41 @@ pub impl<T:Copy Ord> Degrees<T>: Ord {
#[inline(always)] pure fn gt(other: &Degrees<T>) -> bool { *self > **other }
}
pub struct AxialRotation<T> {
/**
* An angular rotation around an arbitary axis
*/
pub struct Rotation<T> {
axis: Vec3<T>,
theta: Radians<T>,
}
pub impl<T:Copy Num NumCast> Rotation<T> {
pure fn to_mat3() -> Mat3<T> {
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<T> {
self.to_mat3().to_mat4()
}
pure fn to_quat() -> Quat<T> {
let half = self.theta / cast(2);
Quat::from_sv(cos(&half), self.axis.mul_t(sin(&half)))
}
}
pub struct Euler<T> {
x: Radians<T>, // pitch
y: Radians<T>, // yaw

View file

@ -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;
}
}

View file

@ -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<T:Copy Num NumCast>(theta: Radians<T>, axis: Vec3<T>) -> Mat3<T> {
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<T:Copy Num NumCast>(theta: Radians<T>, axis: Vec3<T>) -> Mat4<T> {
mat3_from_rotation(theta, axis).to_mat4()
}

View file

@ -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;
}
}

View file

@ -220,12 +220,6 @@ pub impl<T:Copy Num NumCast Exp Clamp Ord InvTrig> Quat<T>: Quaternion<T> {
self.mul_t(cos(&theta)).add_q(&q.mul_t(sin(&theta)))
}
#[inline(always)]
pub pure fn from_axis_angle(axis: Vec3<T>, theta: Radians<T>) -> Quat<T> {
let half = theta / cast(2);
Quat::from_sv(cos(&half), axis.mul_t(sin(&half)))
}
#[inline(always)]
pure fn to_mat3() -> Mat3<T> {

View file

@ -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;
}
}