diff --git a/src/mat.rs b/src/mat.rs index ea3cab0..6978204 100644 --- a/src/mat.rs +++ b/src/mat.rs @@ -286,11 +286,6 @@ pub trait Matrix2: Matrix { * A 3 x 3 matrix */ pub trait Matrix3: Matrix { - /** - * Construct a matrix from an axis and an angular rotation - */ - static pure fn from_axis_angle>(axis: &V, theta: A) -> Mat3; - /** * Returns the the matrix with an extra row and column added * ~~~ @@ -307,11 +302,6 @@ pub trait Matrix3: Matrix { * ~~~ */ pure fn to_mat4(&self) -> Mat4; - - /** - * Convert the matrix to a quaternion - */ - pure fn to_Quat() -> Quat; } /** diff --git a/src/mat3.rs b/src/mat3.rs index 8311a10..d51d113 100644 --- a/src/mat3.rs +++ b/src/mat3.rs @@ -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 Mat3 { /** * 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>(theta: A) -> Mat3 { // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations @@ -149,6 +151,7 @@ pub impl Mat3 { /** * 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>(theta: A) -> Mat3 { // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations @@ -165,6 +168,7 @@ pub impl Mat3 { /** * 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>(theta: A) -> Mat3 { // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations @@ -187,6 +191,7 @@ pub impl Mat3 { * * `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>(theta_x: A, theta_y: A, theta_z: A) -> Mat3 { // http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations @@ -205,8 +210,9 @@ pub impl Mat3 { /** * 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>(axis: &Vec3, theta: A) -> Mat3 { + static pure fn from_angle_axis>(theta: A, axis: &Vec3) -> Mat3 { 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 Mat3 { _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, y: Vec3, z: Vec3) -> Mat3 { + 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, up: &Vec3) -> Mat3 { + 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) -> Mat3 { 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) -> Vec3 { 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 { *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 { + // 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 Mat3: Matrix> { @@ -485,23 +568,6 @@ pub impl Mat3: MutableMatrix> { } pub impl Mat3: Matrix3> { - #[inline(always)] - static pure fn from_axis_angle>(axis: &Vec3, theta: A) -> Mat3 { - 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 { let _0 = Number::from(0); @@ -511,50 +577,6 @@ pub impl Mat3: Matrix3> { self[2][0], self[2][1], self[2][2], _0, _0, _0, _0, _1) } - - pure fn to_Quat() -> Quat { - // 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 Mat3: Index> { diff --git a/src/quat.rs b/src/quat.rs index 421dbaf..aaab24e 100644 --- a/src/quat.rs +++ b/src/quat.rs @@ -67,12 +67,6 @@ pub impl Quat { Quat { s: s, v: v } } - #[inline(always)] - static pure fn from_axis_angle>(axis: &Vec3, theta: A) -> Quat { - 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 Quat { } } + /** + * # Return value + * + * A pointer to the first component of the quaternion + */ + #[inline(always)] + pure fn to_ptr(&self) -> *T { + unsafe { + transmute::<*Quat, *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>(_theta: A) -> Quat { + 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>(_theta: A) -> Quat { + 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>(_theta: A) -> Quat { + 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>(_x: A, _y: A, _z: A) -> Quat { + 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>(theta: A, axis: &Vec3) -> Quat { + 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, y: Vec3, z: Vec3) -> Quat { + 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, _up: &Vec3) -> Quat { + 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) -> Quat { 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) -> Vec3 { 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 { let x2 = self.v.x + self.v.x; @@ -329,27 +389,9 @@ pub impl Quat { 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 { - 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>( - to_unsafe_ptr(self) - ) - } - } + pure fn to_quat(&self) -> Quat { *self } } pub impl Quat: Index { diff --git a/src/test/test_quat.rs b/src/test/test_quat.rs index 5f32de8..ff327c6 100644 --- a/src/test/test_quat.rs +++ b/src/test/test_quat.rs @@ -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 = 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));