Add methods in the Mat3 and Quat anonymous impls in preparation for implementing Rotation

rot::Rotation won't be able to be implemented until https://github.com/mozilla/rust/issues/4306 is fixed.
This commit is contained in:
Brendan Zabarauskas 2012-12-28 16:41:21 +10:00
parent 5c9d882efe
commit 0b55dc2105
4 changed files with 154 additions and 99 deletions

View file

@ -286,11 +286,6 @@ pub trait Matrix2<T,V>: Matrix<T,V> {
* A 3 x 3 matrix
*/
pub trait Matrix3<T,V>: Matrix<T,V> {
/**
* Construct a matrix from an axis and an angular rotation
*/
static pure fn from_axis_angle<A:Angle<T>>(axis: &V, theta: A) -> Mat3<T>;
/**
* Returns the the matrix with an extra row and column added
* ~~~
@ -307,11 +302,6 @@ pub trait Matrix3<T,V>: Matrix<T,V> {
* ~~~
*/
pure fn to_mat4(&self) -> Mat4<T>;
/**
* Convert the matrix to a quaternion
*/
pure fn to_Quat() -> Quat<T>;
}
/**

View file

@ -10,6 +10,7 @@ use numeric::types::float::Float;
use numeric::types::number::Number;
use quat::Quat;
use rot::Rotation;
use vec::Vec3;
/**
@ -133,6 +134,7 @@ pub impl<T:Copy Float> Mat3<T> {
/**
* Construct a matrix from an angular rotation around the `x` axis
*/
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_angle_x<A:Angle<T>>(theta: A) -> Mat3<T> {
// http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
@ -149,6 +151,7 @@ pub impl<T:Copy Float> Mat3<T> {
/**
* Construct a matrix from an angular rotation around the `y` axis
*/
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_angle_y<A:Angle<T>>(theta: A) -> Mat3<T> {
// http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
@ -165,6 +168,7 @@ pub impl<T:Copy Float> Mat3<T> {
/**
* Construct a matrix from an angular rotation around the `z` axis
*/
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_angle_z<A:Angle<T>>(theta: A) -> Mat3<T> {
// http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
@ -187,6 +191,7 @@ pub impl<T:Copy Float> Mat3<T> {
* * `theta_y` - the angular rotation around the `y` axis (yaw)
* * `theta_z` - the angular rotation around the `z` axis (roll)
*/
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_angle_xyz<A:Angle<T>>(theta_x: A, theta_y: A, theta_z: A) -> Mat3<T> {
// http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations
@ -205,8 +210,9 @@ pub impl<T:Copy Float> Mat3<T> {
/**
* Construct a matrix from an axis and an angular rotation
*/
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_axis_angle<A:Angle<T>>(axis: &Vec3<T>, theta: A) -> Mat3<T> {
static pure fn from_angle_axis<A:Angle<T>>(theta: A, axis: &Vec3<T>) -> Mat3<T> {
let c: T = cos(&theta.to_radians());
let s: T = sin(&theta.to_radians());
let _0: T = Number::from(0);
@ -221,6 +227,83 @@ pub impl<T:Copy Float> Mat3<T> {
_1_c*x*y - s*z, _1_c*y*y + c, _1_c*y*z + s*x,
_1_c*x*z + s*y, _1_c*y*z - s*x, _1_c*z*z + c)
}
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_axes(x: Vec3<T>, y: Vec3<T>, z: Vec3<T>) -> Mat3<T> {
Mat3::from_cols(x, y, z)
}
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn look_at(dir: &Vec3<T>, up: &Vec3<T>) -> Mat3<T> {
let dir_ = dir.normalize();
let up_ = up.normalize().cross(&dir_).normalize();
let side = dir_.cross(&up_).normalize();
Mat3::from_axes(up_, side, dir_)
}
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
pure fn concat(&self, other: &Mat3<T>) -> Mat3<T> { self.mul_m(other) }
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
pure fn rotate_vec(&self, vec: &Vec3<T>) -> Vec3<T> { self.mul_v(vec) }
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
pure fn to_mat3(&self) -> Mat3<T> { *self }
/**
* Convert the matrix to a quaternion
*/
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
pure fn to_quat(&self) -> Quat<T> {
// Implemented using a mix of ideas from jMonkeyEngine and Ken Shoemake's
// paper on Quaternions: http://www.cs.ucr.edu/~vbz/resources/Quatut.pdf
let mut s;
let w, x, y, z;
let trace = self.trace();
let _1: T = Number::from(1.0);
let half: T = Number::from(0.5);
if trace >= Number::from(0) {
s = (_1 + trace).sqrt();
w = half * s;
s = half / s;
x = (self[1][2] - self[2][1]) * s;
y = (self[2][0] - self[0][2]) * s;
z = (self[0][1] - self[1][0]) * s;
} else if (self[0][0] > self[1][1]) && (self[0][0] > self[2][2]) {
s = (half + (self[0][0] - self[1][1] - self[2][2])).sqrt();
w = half * s;
s = half / s;
x = (self[0][1] - self[1][0]) * s;
y = (self[2][0] - self[0][2]) * s;
z = (self[1][2] - self[2][1]) * s;
} else if self[1][1] > self[2][2] {
s = (half + (self[1][1] - self[0][0] - self[2][2])).sqrt();
w = half * s;
s = half / s;
x = (self[0][1] - self[1][0]) * s;
y = (self[1][2] - self[2][1]) * s;
z = (self[2][0] - self[0][2]) * s;
} else {
s = (half + (self[2][2] - self[0][0] - self[1][1])).sqrt();
w = half * s;
s = half / s;
x = (self[2][0] - self[0][2]) * s;
y = (self[1][2] - self[2][1]) * s;
z = (self[0][1] - self[1][0]) * s;
}
Quat::new(w, x, y, z)
}
}
pub impl<T:Copy Float> Mat3<T>: Matrix<T, Vec3<T>> {
@ -485,23 +568,6 @@ pub impl<T:Copy Float> Mat3<T>: MutableMatrix<T, Vec3<T>> {
}
pub impl<T:Copy Float> Mat3<T>: Matrix3<T, Vec3<T>> {
#[inline(always)]
static pure fn from_axis_angle<A:Angle<T>>(axis: &Vec3<T>, theta: A) -> Mat3<T> {
let c: T = cos(&theta.to_radians());
let s: T = sin(&theta.to_radians());
let _0: T = Number::from(0);
let _1: T = Number::from(1);
let _1_c: T = _1 - c;
let x = axis.x;
let y = axis.y;
let z = axis.z;
Mat3::new(_1_c * x * x + c, _1_c * x * y + s * z, _1_c * x * z - s * y,
_1_c * x * y - s * z, _1_c * y * y + c, _1_c * y * z + s * x,
_1_c * x * z + s * y, _1_c * y * z - s * x, _1_c * z * z + c)
}
#[inline(always)]
pure fn to_mat4(&self) -> Mat4<T> {
let _0 = Number::from(0);
@ -511,50 +577,6 @@ pub impl<T:Copy Float> Mat3<T>: Matrix3<T, Vec3<T>> {
self[2][0], self[2][1], self[2][2], _0,
_0, _0, _0, _1)
}
pure fn to_Quat() -> Quat<T> {
// Implemented using a mix of ideas from jMonkeyEngine and Ken Shoemake's
// paper on Quaternions: http://www.cs.ucr.edu/~vbz/resources/Quatut.pdf
let mut s;
let w, x, y, z;
let trace = self.trace();
let _1: T = Number::from(1.0);
let half: T = Number::from(0.5);
if trace >= Number::from(0) {
s = (_1 + trace).sqrt();
w = half * s;
s = half / s;
x = (self[1][2] - self[2][1]) * s;
y = (self[2][0] - self[0][2]) * s;
z = (self[0][1] - self[1][0]) * s;
} else if (self[0][0] > self[1][1]) && (self[0][0] > self[2][2]) {
s = (half + (self[0][0] - self[1][1] - self[2][2])).sqrt();
w = half * s;
s = half / s;
x = (self[0][1] - self[1][0]) * s;
y = (self[2][0] - self[0][2]) * s;
z = (self[1][2] - self[2][1]) * s;
} else if self[1][1] > self[2][2] {
s = (half + (self[1][1] - self[0][0] - self[2][2])).sqrt();
w = half * s;
s = half / s;
x = (self[0][1] - self[1][0]) * s;
y = (self[1][2] - self[2][1]) * s;
z = (self[2][0] - self[0][2]) * s;
} else {
s = (half + (self[2][2] - self[0][0] - self[1][1])).sqrt();
w = half * s;
s = half / s;
x = (self[2][0] - self[0][2]) * s;
y = (self[1][2] - self[2][1]) * s;
z = (self[0][1] - self[1][0]) * s;
}
Quat::new(w, x, y, z)
}
}
pub impl<T:Copy> Mat3<T>: Index<uint, Vec3<T>> {

View file

@ -67,12 +67,6 @@ pub impl<T:Copy Float> Quat<T> {
Quat { s: s, v: v }
}
#[inline(always)]
static pure fn from_axis_angle<A:Angle<T>>(axis: &Vec3<T>, theta: A) -> Quat<T> {
let half = theta.to_radians() / Number::from(2);
Quat::from_sv(cos(&half), axis.mul_t(sin(&half)))
}
/**
* # Return value
*
@ -301,9 +295,75 @@ pub impl<T:Copy Float> Quat<T> {
}
}
/**
* # Return value
*
* A pointer to the first component of the quaternion
*/
#[inline(always)]
pure fn to_ptr(&self) -> *T {
unsafe {
transmute::<*Quat<T>, *T>(
to_unsafe_ptr(self)
)
}
}
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_angle_x<A:Angle<T>>(_theta: A) -> Quat<T> {
fail(~"Not yet implemented!")
}
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_angle_y<A:Angle<T>>(_theta: A) -> Quat<T> {
fail(~"Not yet implemented!")
}
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_angle_z<A:Angle<T>>(_theta: A) -> Quat<T> {
fail(~"Not yet implemented!")
}
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_angle_xyz<A:Angle<T>>(_x: A, _y: A, _z: A) -> Quat<T> {
fail(~"Not yet implemented!")
}
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_angle_axis<A:Angle<T>>(theta: A, axis: &Vec3<T>) -> Quat<T> {
let half = theta.to_radians() / Number::from(2);
Quat::from_sv(cos(&half), axis.mul_t(sin(&half)))
}
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn from_axes(x: Vec3<T>, y: Vec3<T>, z: Vec3<T>) -> Quat<T> {
Mat3::from_axes(x, y, z).to_quat()
}
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
static pure fn look_at(_dir: &Vec3<T>, _up: &Vec3<T>) -> Quat<T> {
fail(~"Not yet implemented!")
}
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
pure fn concat(&self, other: &Quat<T>) -> Quat<T> { self.mul_q(other) }
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
pure fn rotate_vec(&self, vec: &Vec3<T>) -> Vec3<T> { self.mul_v(vec) }
/**
* Convert the quaternion to a 3 x 3 rotation matrix
*/
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
pure fn to_mat3(&self) -> Mat3<T> {
let x2 = self.v.x + self.v.x;
@ -329,27 +389,9 @@ pub impl<T:Copy Float> Quat<T> {
xz2 + sy2, yz2 - sx2, _1 - xx2 - yy2)
}
/**
* Convert the quaternion to a 4 x 4 transformation matrix
*/
// TODO: Move to Rotation implementation. See: https://github.com/mozilla/rust/issues/4306
#[inline(always)]
pure fn to_mat4(&self) -> Mat4<T> {
self.to_mat3().to_mat4()
}
/**
* # Return value
*
* A pointer to the first component of the quaternion
*/
#[inline(always)]
pure fn to_ptr(&self) -> *T {
unsafe {
transmute::<*Quat<T>, *T>(
to_unsafe_ptr(self)
)
}
}
pure fn to_quat(&self) -> Quat<T> { *self }
}
pub impl<T:Copy> Quat<T>: Index<uint, T> {

View file

@ -32,7 +32,8 @@ fn test_quat() {
fn test_quat_2() {
let v = Vec3::new(1.0, 0.0, 0.0);
let q = Quat::from_axis_angle(&Vec3::new(0.0, 0.0, -1.0), Degrees(-45.0));
// let q: Quat<float> = rot::Rotation::from_angle_axis(Degrees(-45.0), &Vec3::new(0.0, 0.0, -1.0));
let q = Quat::from_angle_axis(Degrees(-45.0), &Vec3::new(0.0, 0.0, -1.0));
// http://www.wolframalpha.com/input/?i={1,0}+rotate+-45+degrees
assert q.mul_v(&v).fuzzy_eq(&Vec3::new(1.0/sqrt(&2.0), 1.0/sqrt(&2.0), 0.0));