From e4e9b6909ec5f7a37d740e1a5a244d7468da5965 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 30 Sep 2013 14:30:40 +1000 Subject: [PATCH 01/10] Reduce the number of rotation types, shifting some of the functionality to the quaternion and matrix constructors. --- src/cgmath/matrix.rs | 65 +++++++++- src/cgmath/quaternion.rs | 47 ++++++- src/cgmath/rotation.rs | 259 +++++---------------------------------- 3 files changed, 142 insertions(+), 229 deletions(-) diff --git a/src/cgmath/matrix.rs b/src/cgmath/matrix.rs index 117ec26..e00662d 100644 --- a/src/cgmath/matrix.rs +++ b/src/cgmath/matrix.rs @@ -17,7 +17,7 @@ use std::num::{Zero, zero, One, one, cast, sqrt}; -use angle::{Rad, sin, cos}; +use angle::{Angle, Rad, sin, cos, sin_cos}; use array::{Array, build}; use quaternion::{Quat, ToQuat}; use vector::{Vector, EuclideanVector}; @@ -121,6 +121,69 @@ impl Mat3 { Mat3::from_cols(up, side, dir) } + + /// Create a matrix from a rotation around the `x` axis (pitch). + pub fn from_angle_x>(theta: A) -> Mat3 { + // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations + let (s, c) = sin_cos(theta); + Mat3::new(one(), zero(), zero(), + zero(), c.clone(), s.clone(), + zero(), -s.clone(), c.clone()) + } + + /// Create a matrix from a rotation around the `y` axis (yaw). + pub fn from_angle_y>(theta: A) -> Mat3 { + // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations + let (s, c) = sin_cos(theta); + Mat3::new(c.clone(), zero(), -s.clone(), + zero(), one(), zero(), + s.clone(), zero(), c.clone()) + } + + /// Create a matrix from a rotation around the `z` axis (roll). + pub fn from_angle_z>(theta: A) -> Mat3 { + // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations + let (s, c) = sin_cos(theta); + Mat3::new(c.clone(), s.clone(), zero(), + -s.clone(), c.clone(), zero(), + zero(), zero(), one()) + } + + /// Create a matrix from a set of euler angles. + /// + /// # Parameters + /// + /// - `x`: the angular rotation around the `x` axis (pitch). + /// - `y`: the angular rotation around the `y` axis (yaw). + /// - `z`: the angular rotation around the `z` axis (roll). + pub fn from_euler>(x: A, y: A, z: A) -> Mat3 { + // http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations + let (sx, cx) = sin_cos(x); + let (sy, cy) = sin_cos(y); + let (sz, cz) = sin_cos(z); + + Mat3::new(cy * cz, cy * sz, -sy, + -cx * sz + sx * sy * cz, cx * cz + sx * sy * sz, sx * cy, + sx * sz + cx * sy * cz, -sx * cz + cx * sy * sz, cx * cy) + } + + /// Create a matrix from a rotation around an arbitrary axis + pub fn from_axis_angle>(axis: &Vec3, angle: A) -> Mat3 { + let (s, c) = sin_cos(angle); + let _1subc = one::() - c; + + Mat3::new(_1subc * axis.x * axis.x + c, + _1subc * axis.x * axis.y + s * axis.z, + _1subc * axis.x * axis.z - s * axis.y, + + _1subc * axis.x * axis.y - s * axis.z, + _1subc * axis.y * axis.y + c, + _1subc * axis.y * axis.z + s * axis.x, + + _1subc * axis.x * axis.z + s * axis.y, + _1subc * axis.y * axis.z - s * axis.x, + _1subc * axis.z * axis.z + c) + } } impl Mat4 { diff --git a/src/cgmath/quaternion.rs b/src/cgmath/quaternion.rs index 846f38f..8de82ff 100644 --- a/src/cgmath/quaternion.rs +++ b/src/cgmath/quaternion.rs @@ -15,7 +15,7 @@ use std::num::{zero, one, cast, sqrt}; -use angle::{Angle, Rad, acos, cos, sin}; +use angle::{Angle, Rad, acos, cos, sin, sin_cos}; use array::{Array, build}; use matrix::{Mat3, ToMat3}; use vector::{Vec3, Vector, EuclideanVector}; @@ -50,6 +50,51 @@ impl Quat { Mat3::look_at(dir, up).to_quat() } + /// Create a matrix from a rotation around the `x` axis (pitch). + #[inline] + pub fn from_angle_x>(theta: A) -> Quat { + Quat::new(cos(theta.mul_s(cast(0.5))), sin(theta), zero(), zero()) + } + + /// Create a matrix from a rotation around the `y` axis (yaw). + #[inline] + pub fn from_angle_y>(theta: A) -> Quat { + Quat::new(cos(theta.mul_s(cast(0.5))), zero(), sin(theta), zero()) + } + + /// Create a matrix from a rotation around the `z` axis (roll). + #[inline] + pub fn from_angle_z>(theta: A) -> Quat { + Quat::new(cos(theta.mul_s(cast(0.5))), zero(), zero(), sin(theta)) + } + + /// Create a quaternion from a set of euler angles. + /// + /// # Parameters + /// + /// - `x`: the angular rotation around the `x` axis (pitch). + /// - `y`: the angular rotation around the `y` axis (yaw). + /// - `z`: the angular rotation around the `z` axis (roll). + pub fn from_euler>(x: A, y: A, z: A) -> Quat { + // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Conversion + let (sx2, cx2) = sin_cos(x.mul_s(cast(0.5))); + let (sy2, cy2) = sin_cos(y.mul_s(cast(0.5))); + let (sz2, cz2) = sin_cos(z.mul_s(cast(0.5))); + + Quat::new(cz2 * cx2 * cy2 + sz2 * sx2 * sy2, + sz2 * cx2 * cy2 - cz2 * sx2 * sy2, + cz2 * sx2 * cy2 + sz2 * cx2 * sy2, + cz2 * cx2 * sy2 - sz2 * sx2 * cy2) + } + + /// Create a quaternion from a rotation around an arbitrary axis + #[inline] + pub fn from_axis_angle>(axis: &Vec3, angle: A) -> Quat { + let half = angle.mul_s(cast(0.5)); + Quat::from_sv(cos(half.clone()), + axis.mul_s(sin(half))) + } + /// The additive identity, ie: `q = 0 + 0i + 0j + 0i` #[inline] pub fn zero() -> Quat { diff --git a/src/cgmath/rotation.rs b/src/cgmath/rotation.rs index eae3973..64193db 100644 --- a/src/cgmath/rotation.rs +++ b/src/cgmath/rotation.rs @@ -13,10 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::num::{cast, one}; - -use angle::{Angle, sin, cos, sin_cos}; -use array::Array; +use angle::Angle; use matrix::Matrix; use matrix::{Mat2, ToMat2}; use matrix::{Mat3, ToMat3}; @@ -156,6 +153,37 @@ impl Rot3 { Rot3 { mat: Mat3::look_at(dir, up) } } + /// Create a rotation matrix from a rotation around the `x` axis (pitch). + pub fn from_angle_x>(theta: A) -> Rot3 { + Rot3 { mat: Mat3::from_angle_x(theta) } + } + + /// Create a rotation matrix from a rotation around the `y` axis (yaw). + pub fn from_angle_y>(theta: A) -> Rot3 { + Rot3 { mat: Mat3::from_angle_y(theta) } + } + + /// Create a rotation matrix from a rotation around the `z` axis (roll). + pub fn from_angle_z>(theta: A) -> Rot3 { + Rot3 { mat: Mat3::from_angle_z(theta) } + } + + /// Create a rotation matrix from a set of euler angles. + /// + /// # Parameters + /// + /// - `x`: the angular rotation around the `x` axis (pitch). + /// - `y`: the angular rotation around the `y` axis (yaw). + /// - `z`: the angular rotation around the `z` axis (roll). + pub fn from_euler>(x: A, y: A, z: A) -> Rot3 { + Rot3 { mat: Mat3::from_euler(x, y ,z) } + } + + /// Create a rotation matrix from a rotation around an arbitrary axis. + pub fn from_axis_angle>(axis: &Vec3, angle: A) -> Rot3 { + Rot3 { mat: Mat3::from_axis_angle(axis, angle) } + } + #[inline] pub fn as_mat3<'a>(&'a self) -> &'a Mat3 { &'a self.mat } } @@ -258,226 +286,3 @@ impl Rotation3 for Quat { #[inline] fn invert_self(&mut self) { *self = self.invert() } } - -/// Euler angles -/// -/// # Fields -/// -/// - `x`: the angular rotation around the `x` axis (pitch) -/// - `y`: the angular rotation around the `y` axis (yaw) -/// - `z`: the angular rotation around the `z` axis (roll) -/// -/// # Notes -/// -/// Whilst Euler angles are more intuitive to specify than quaternions, -/// they are not recommended for general use because they are prone to gimble -/// lock, and are hard to interpolate between. -#[deriving(Eq, Clone)] -pub struct Euler { x: A, y: A, z: A } - -array!(impl Euler -> [A, ..3] _3) - -impl> Euler { - #[inline] - pub fn new(x: A, y: A, z: A) -> Euler { - Euler { x: x, y: y, z: z } - } -} - -pub trait ToEuler { - fn to_euler(&self) -> Euler; -} - -impl> ToMat3 for Euler { - fn to_mat3(&self) -> Mat3 { - // http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations - let (sx, cx) = sin_cos(self.x.clone()); - let (sy, cy) = sin_cos(self.y.clone()); - let (sz, cz) = sin_cos(self.z.clone()); - - Mat3::new(cy * cz, cy * sz, -sy, - -cx * sz + sx * sy * cz, cx * cz + sx * sy * sz, sx * cy, - sx * sz + cx * sy * cz, -sx * cz + cx * sy * sz, cx * cy) - } -} - -impl> ToRot3 for Euler { - #[inline] - fn to_rot3(&self) -> Rot3 { - Rot3 { mat: self.to_mat3() } - } -} - -impl> ToQuat for Euler { - fn to_quat(&self) -> Quat { - // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Conversion - let (sx2, cx2) = sin_cos(self.x.mul_s(cast(0.5))); - let (sy2, cy2) = sin_cos(self.y.mul_s(cast(0.5))); - let (sz2, cz2) = sin_cos(self.z.mul_s(cast(0.5))); - - Quat::new(cz2 * cx2 * cy2 + sz2 * sx2 * sy2, - sz2 * cx2 * cy2 - cz2 * sx2 * sy2, - cz2 * sx2 * cy2 + sz2 * cx2 * sy2, - cz2 * cx2 * sy2 - sz2 * sx2 * cy2) - } -} - -impl> Rotation3 for Euler { - #[inline] - fn rotate_point3(&self, _point: &Point3) -> Point3 { fail!("Not yet implemented") } - - #[inline] - fn rotate_vec3(&self, _vec: &Vec3) -> Vec3 { fail!("Not yet implemented"); } - - #[inline] - fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { fail!("Not yet implemented") } - - #[inline] - fn concat(&self, _other: &Euler) -> Euler { fail!("Not yet implemented") } - - #[inline] - fn concat_self(&mut self, _other: &Euler) { fail!("Not yet implemented"); } - - #[inline] - fn invert(&self) -> Euler { fail!("Not yet implemented") } - - #[inline] - fn invert_self(&mut self) { fail!("Not yet implemented"); } -} - -impl> ApproxEq for Euler { - #[inline] - fn approx_epsilon() -> S { - // TODO: fix this after static methods are fixed in rustc - fail!(~"Doesn't work!"); - } - - #[inline] - fn approx_eq(&self, other: &Euler) -> bool { - self.x.approx_eq(&other.x) && - self.y.approx_eq(&other.y) && - self.z.approx_eq(&other.z) - } - - #[inline] - fn approx_eq_eps(&self, other: &Euler, approx_epsilon: &S) -> bool { - self.x.approx_eq_eps(&other.x, approx_epsilon) && - self.y.approx_eq_eps(&other.y, approx_epsilon) && - self.z.approx_eq_eps(&other.z, approx_epsilon) - } -} - -/// A rotation about an arbitrary axis -/// -/// # Fields -/// -/// - `v`: the axis of rotation -/// - `a`: the angular rotation -#[deriving(Eq, Clone)] -pub struct AxisAngle { v: Vec3, a: A } - -pub trait ToAxisAngle { - fn to_axis_angle(&self) -> AxisAngle; -} - -impl> AxisAngle { - #[inline] - pub fn new(v: Vec3, a: A) -> AxisAngle { - AxisAngle { v: v, a: a } - } -} - -impl> ToMat3 for AxisAngle { - fn to_mat3(&self) -> Mat3 { - let (s, c) = sin_cos(self.a.clone()); - let _1subc = one::() - c; - - Mat3::new(_1subc * self.v.x * self.v.x + c, - _1subc * self.v.x * self.v.y + s * self.v.z, - _1subc * self.v.x * self.v.z - s * self.v.y, - - _1subc * self.v.x * self.v.y - s * self.v.z, - _1subc * self.v.y * self.v.y + c, - _1subc * self.v.y * self.v.z + s * self.v.x, - - _1subc * self.v.x * self.v.z + s * self.v.y, - _1subc * self.v.y * self.v.z - s * self.v.x, - _1subc * self.v.z * self.v.z + c) - } -} - -impl> ToRot3 for AxisAngle { - #[inline] - fn to_rot3(&self) -> Rot3 { - Rot3 { mat: self.to_mat3() } - } -} - -impl> ToQuat for AxisAngle { - fn to_quat(&self) -> Quat { - let half = self.a.mul_s(cast(0.5)); - Quat::from_sv( - cos(half.clone()), - self.v.mul_s(sin(half.clone())) - ) - } -} - -impl> Rotation3 for AxisAngle { - #[inline] - fn rotate_point3(&self, _point: &Point3) -> Point3 { fail!("Not yet implemented") } - - #[inline] - fn rotate_vec3(&self, _vec: &Vec3) -> Vec3 { fail!("Not yet implemented"); } - - #[inline] - fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { fail!("Not yet implemented") } - - #[inline] - fn concat(&self, _other: &AxisAngle) -> AxisAngle { fail!("Not yet implemented") } - - #[inline] - fn concat_self(&mut self, _other: &AxisAngle) { fail!("Not yet implemented"); } - - #[inline] - fn invert(&self) -> AxisAngle { - AxisAngle::new(self.v.clone(), (-self.a).normalize()) - } - - #[inline] - fn invert_self(&mut self) { - self.a = (-self.a).normalize() - } -} - -impl> ApproxEq for AxisAngle { - #[inline] - fn approx_epsilon() -> S { - // TODO: fix this after static methods are fixed in rustc - fail!(~"Doesn't work!"); - } - - #[inline] - fn approx_eq(&self, other: &AxisAngle) -> bool { - self.v.approx_eq(&other.v) && - self.a.approx_eq(&other.a) - } - - #[inline] - fn approx_eq_eps(&self, other: &AxisAngle, approx_epsilon: &S) -> bool { - self.v.approx_eq_eps(&other.v, approx_epsilon) && - self.a.approx_eq_eps(&other.a, approx_epsilon) - } -} - -/// An angle around the X axis (pitch). -#[deriving(Eq, Ord, Clone)] -pub struct AngleX(A); - -/// An angle around the X axis (yaw). -#[deriving(Eq, Ord, Clone)] -pub struct AngleY(A); - -/// An angle around the Z axis (roll). -#[deriving(Eq, Ord, Clone)] -pub struct AngleZ(A); From 2ac675ae100f612a422d0be53043f579dbd272b3 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 13 Oct 2013 06:54:24 +1100 Subject: [PATCH 02/10] Fix slerp --- AUTHORS | 1 + src/cgmath/quaternion.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/AUTHORS b/AUTHORS index e834dec..3fa559d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -11,6 +11,7 @@ Erick Tryzelaar Luqman Aden Maik Klein Mikko Perttunen +Tomasz Stachowiak With thanks to: diff --git a/src/cgmath/quaternion.rs b/src/cgmath/quaternion.rs index 8de82ff..29cc10f 100644 --- a/src/cgmath/quaternion.rs +++ b/src/cgmath/quaternion.rs @@ -252,14 +252,14 @@ impl Quat { // stay within the domain of acos() let robust_dot = dot.clamp(&-one::(), &one::()); - let theta: Rad = acos(robust_dot.clone()); // the angle between the quaternions - let theta: Rad = theta.mul_s(amount); // the fraction of theta specified by `amount` + let theta: Rad = acos(robust_dot.clone()); - let q = other.sub_q(&self.mul_s(robust_dot)) - .normalize(); + let scale1 = sin(theta.mul_s(one::() - amount)); + let scale2 = sin(theta.mul_s(amount)); - self.mul_s(cos(theta.clone())) - .add_q(&q.mul_s(sin(theta))) + self.mul_s(scale1) + .add_q(&other.mul_s(scale2)) + .mul_s(sin(theta).recip()) } } } From 3862e867ba1db993542b073e8c5387cb5f39003c Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 13 Oct 2013 06:56:05 +1100 Subject: [PATCH 03/10] Update to latest Rust --- src/cgmath/angle.rs | 12 ++++++------ src/cgmath/lib.rs | 3 +++ src/cgmath/matrix.rs | 2 +- src/cgmath/projection.rs | 34 +++++++++++++++++----------------- src/cgmath/quaternion.rs | 18 +++++++++--------- 5 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/cgmath/angle.rs b/src/cgmath/angle.rs index ad71f15..7b80e96 100644 --- a/src/cgmath/angle.rs +++ b/src/cgmath/angle.rs @@ -113,15 +113,15 @@ pub trait Angle /// Returns the interior bisector of the two angles #[inline] fn bisect(&self, other: Self) -> Self { - self.add_a(self.sub_a(other).mul_s(cast(0.5))).normalize() + self.add_a(self.sub_a(other).mul_s(cast(0.5).unwrap())).normalize() } fn full_turn() -> Self; - #[inline] fn turn_div_2() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(2)) } - #[inline] fn turn_div_3() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(3)) } - #[inline] fn turn_div_4() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(4)) } - #[inline] fn turn_div_6() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(6)) } + #[inline] fn turn_div_2() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(2).unwrap()) } + #[inline] fn turn_div_3() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(3).unwrap()) } + #[inline] fn turn_div_4() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(4).unwrap()) } + #[inline] fn turn_div_6() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(6).unwrap()) } } #[inline] pub fn bisect>(a: A, b: A) -> A { a.bisect(b) } @@ -163,7 +163,7 @@ impl Angle for Rad { impl Angle for Deg { #[inline] fn from>(theta: A) -> Deg { theta.to_deg() } - #[inline] fn full_turn() -> Deg { deg(cast(360)) } + #[inline] fn full_turn() -> Deg { deg(cast(360).unwrap()) } } #[inline] pub fn sin>(theta: A) -> S { theta.to_rad().s.sin() } diff --git a/src/cgmath/lib.rs b/src/cgmath/lib.rs index ea340b4..7842085 100644 --- a/src/cgmath/lib.rs +++ b/src/cgmath/lib.rs @@ -22,6 +22,9 @@ #[license = "ASL2"]; #[crate_type = "lib"]; +#[feature(globs)]; +#[feature(macro_rules)]; + pub mod array; pub mod matrix; pub mod quaternion; diff --git a/src/cgmath/matrix.rs b/src/cgmath/matrix.rs index e00662d..9322f32 100644 --- a/src/cgmath/matrix.rs +++ b/src/cgmath/matrix.rs @@ -628,7 +628,7 @@ impl ToQuat for Mat3 { fn to_quat(&self) -> Quat { // http://www.cs.ucr.edu/~vbz/resources/Quatut.pdf let trace = self.trace(); - let half: S = cast(0.5); + let half: S = cast(0.5).unwrap(); match () { () if trace >= zero::() => { let s = sqrt(one::() + trace); diff --git a/src/cgmath/projection.rs b/src/cgmath/projection.rs index 0ede2a1..98f931f 100644 --- a/src/cgmath/projection.rs +++ b/src/cgmath/projection.rs @@ -78,7 +78,7 @@ pub struct PerspectiveFov { impl> PerspectiveFov { pub fn to_perspective(&self) -> Perspective { - let angle = self.fovy.div_s(cast(2)); + let angle = self.fovy.div_s(cast(2).unwrap()); let ymax = self.near * tan(angle); let xmax = ymax * self.aspect; @@ -104,15 +104,15 @@ impl> ToMat4 for PerspectiveFov { fn to_mat4(&self) -> Mat4 { let half_turn: A = Angle::turn_div_2(); - assert!(self.fovy > zero(), "The vertical field of view cannot be below zero, found: %?", self.fovy); - assert!(self.fovy < half_turn, "The vertical field of view cannot be greater than a half turn, found: %?", self.fovy); - assert!(self.aspect > zero(), "The aspect ratio cannot be below zero, found: %?", self.aspect); - assert!(self.near > zero(), "The near plane distance cannot be below zero, found: %?", self.near); - assert!(self.far > zero(), "The far plane distance cannot be below zero, found: %?", self.far); - assert!(self.far > self.near, "The far plane cannot be closer than the near plane, found: far: %?, near: %?", self.far, self.near); + assert!(self.fovy > zero(), "The vertical field of view cannot be below zero, found: {:?}", self.fovy); + assert!(self.fovy < half_turn, "The vertical field of view cannot be greater than a half turn, found: {:?}", self.fovy); + assert!(self.aspect > zero(), "The aspect ratio cannot be below zero, found: {:?}", self.aspect); + assert!(self.near > zero(), "The near plane distance cannot be below zero, found: {:?}", self.near); + assert!(self.far > zero(), "The far plane distance cannot be below zero, found: {:?}", self.far); + assert!(self.far > self.near, "The far plane cannot be closer than the near plane, found: far: {:?}, near: {:?}", self.far, self.near); - let f = cot(self.fovy.div_s(cast(2))); - let two: S = cast(2); + let f = cot(self.fovy.div_s(cast(2).unwrap())); + let two: S = cast(2).unwrap(); let c0r0 = f / self.aspect; let c0r1 = zero(); @@ -158,11 +158,11 @@ impl Projection for Perspective { impl ToMat4 for Perspective { fn to_mat4(&self) -> Mat4 { - assert!(self.left > self.right, "`left` cannot be greater than `right`, found: left: %? right: %?", self.left, self.right); - assert!(self.bottom > self.top, "`bottom` cannot be greater than `top`, found: bottom: %? top: %?", self.bottom, self.top); - assert!(self.near > self.far, "`near` cannot be greater than `far`, found: near: %? far: %?", self.near, self.far); + assert!(self.left > self.right, "`left` cannot be greater than `right`, found: left: {:?} right: {:?}", self.left, self.right); + assert!(self.bottom > self.top, "`bottom` cannot be greater than `top`, found: bottom: {:?} top: {:?}", self.bottom, self.top); + assert!(self.near > self.far, "`near` cannot be greater than `far`, found: near: {:?} far: {:?}", self.near, self.far); - let two: S = cast(2); + let two: S = cast(2).unwrap(); let c0r0 = (two * self.near) / (self.right - self.left); let c0r1 = zero(); @@ -214,11 +214,11 @@ impl Projection for Ortho { impl ToMat4 for Ortho { fn to_mat4(&self) -> Mat4 { - assert!(self.left > self.right, "`left` cannot be greater than `right`, found: left: %? right: %?", self.left, self.right); - assert!(self.bottom > self.top, "`bottom` cannot be greater than `top`, found: bottom: %? top: %?", self.bottom, self.top); - assert!(self.near > self.far, "`near` cannot be greater than `far`, found: near: %? far: %?", self.near, self.far); + assert!(self.left > self.right, "`left` cannot be greater than `right`, found: left: {:?} right: {:?}", self.left, self.right); + assert!(self.bottom > self.top, "`bottom` cannot be greater than `top`, found: bottom: {:?} top: {:?}", self.bottom, self.top); + assert!(self.near > self.far, "`near` cannot be greater than `far`, found: near: {:?} far: {:?}", self.near, self.far); - let two: S = cast(2); + let two: S = cast(2).unwrap(); let c0r0 = two / (self.right - self.left); let c0r1 = zero(); diff --git a/src/cgmath/quaternion.rs b/src/cgmath/quaternion.rs index 29cc10f..4d99872 100644 --- a/src/cgmath/quaternion.rs +++ b/src/cgmath/quaternion.rs @@ -53,19 +53,19 @@ impl Quat { /// Create a matrix from a rotation around the `x` axis (pitch). #[inline] pub fn from_angle_x>(theta: A) -> Quat { - Quat::new(cos(theta.mul_s(cast(0.5))), sin(theta), zero(), zero()) + Quat::new(cos(theta.mul_s(cast(0.5).unwrap())), sin(theta), zero(), zero()) } /// Create a matrix from a rotation around the `y` axis (yaw). #[inline] pub fn from_angle_y>(theta: A) -> Quat { - Quat::new(cos(theta.mul_s(cast(0.5))), zero(), sin(theta), zero()) + Quat::new(cos(theta.mul_s(cast(0.5).unwrap())), zero(), sin(theta), zero()) } /// Create a matrix from a rotation around the `z` axis (roll). #[inline] pub fn from_angle_z>(theta: A) -> Quat { - Quat::new(cos(theta.mul_s(cast(0.5))), zero(), zero(), sin(theta)) + Quat::new(cos(theta.mul_s(cast(0.5).unwrap())), zero(), zero(), sin(theta)) } /// Create a quaternion from a set of euler angles. @@ -77,9 +77,9 @@ impl Quat { /// - `z`: the angular rotation around the `z` axis (roll). pub fn from_euler>(x: A, y: A, z: A) -> Quat { // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Conversion - let (sx2, cx2) = sin_cos(x.mul_s(cast(0.5))); - let (sy2, cy2) = sin_cos(y.mul_s(cast(0.5))); - let (sz2, cz2) = sin_cos(z.mul_s(cast(0.5))); + let (sx2, cx2) = sin_cos(x.mul_s(cast(0.5).unwrap())); + let (sy2, cy2) = sin_cos(y.mul_s(cast(0.5).unwrap())); + let (sz2, cz2) = sin_cos(z.mul_s(cast(0.5).unwrap())); Quat::new(cz2 * cx2 * cy2 + sz2 * sx2 * sy2, sz2 * cx2 * cy2 - cz2 * sx2 * sy2, @@ -90,7 +90,7 @@ impl Quat { /// Create a quaternion from a rotation around an arbitrary axis #[inline] pub fn from_axis_angle>(axis: &Vec3, angle: A) -> Quat { - let half = angle.mul_s(cast(0.5)); + let half = angle.mul_s(cast(0.5).unwrap()); Quat::from_sv(cos(half.clone()), axis.mul_s(sin(half))) } @@ -123,7 +123,7 @@ impl Quat { #[inline] pub fn mul_v(&self, vec: &Vec3) -> Vec3 { let tmp = self.v.cross(vec).add_v(&vec.mul_s(self.s.clone())); - self.v.cross(&tmp).mul_s(cast(2)).add_v(vec) + self.v.cross(&tmp).mul_s(cast(2).unwrap()).add_v(vec) } /// The sum of this quaternion and `other` @@ -243,7 +243,7 @@ impl Quat { use std::num::cast; let dot = self.dot(other); - let dot_threshold = cast(0.9995); + let dot_threshold = cast(0.9995).unwrap(); // if quaternions are close together use `nlerp` if dot > dot_threshold { From 70d48ed37ba51cedd0751777cc9be1727b8fb984 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 13 Oct 2013 10:52:21 +1100 Subject: [PATCH 04/10] Force the client to perform Degree->Rad conversions by taking Rad parameters instead of generic Angles This should make the overhead of conversions evident to the client. --- src/cgmath/angle.rs | 22 +++++++++++----------- src/cgmath/matrix.rs | 12 ++++++------ src/cgmath/projection.rs | 4 ++-- src/cgmath/quaternion.rs | 10 +++++----- src/cgmath/rotation.rs | 12 ++++++------ 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/cgmath/angle.rs b/src/cgmath/angle.rs index 7b80e96..38a1ec9 100644 --- a/src/cgmath/angle.rs +++ b/src/cgmath/angle.rs @@ -166,19 +166,19 @@ impl Angle for Deg { #[inline] fn full_turn() -> Deg { deg(cast(360).unwrap()) } } -#[inline] pub fn sin>(theta: A) -> S { theta.to_rad().s.sin() } -#[inline] pub fn cos>(theta: A) -> S { theta.to_rad().s.cos() } -#[inline] pub fn tan>(theta: A) -> S { theta.to_rad().s.tan() } -#[inline] pub fn sin_cos>(theta: A) -> (S, S) { theta.to_rad().s.sin_cos() } +#[inline] pub fn sin(theta: Rad) -> S { theta.s.sin() } +#[inline] pub fn cos(theta: Rad) -> S { theta.s.cos() } +#[inline] pub fn tan(theta: Rad) -> S { theta.s.tan() } +#[inline] pub fn sin_cos(theta: Rad) -> (S, S) { theta.s.sin_cos() } -#[inline] pub fn cot>(theta: A) -> S { tan(theta).recip() } -#[inline] pub fn sec>(theta: A) -> S { cos(theta).recip() } -#[inline] pub fn csc>(theta: A) -> S { sin(theta).recip() } +#[inline] pub fn cot(theta: Rad) -> S { tan(theta).recip() } +#[inline] pub fn sec(theta: Rad) -> S { cos(theta).recip() } +#[inline] pub fn csc(theta: Rad) -> S { sin(theta).recip() } -#[inline] pub fn asin>(s: S) -> A { Angle::from(rad(s.asin())) } -#[inline] pub fn acos>(s: S) -> A { Angle::from(rad(s.acos())) } -#[inline] pub fn atan>(s: S) -> A { Angle::from(rad(s.atan())) } -#[inline] pub fn atan2>(a: S, b: S) -> A { Angle::from(rad(a.atan2(&b))) } +#[inline] pub fn asin(s: S) -> Rad { rad(s.asin()) } +#[inline] pub fn acos(s: S) -> Rad { rad(s.acos()) } +#[inline] pub fn atan(s: S) -> Rad { rad(s.atan()) } +#[inline] pub fn atan2(a: S, b: S) -> Rad { rad(a.atan2(&b)) } impl ToStr for Rad { fn to_str(&self) -> ~str { fmt!("%? rad", self.s) } } impl ToStr for Deg { fn to_str(&self) -> ~str { fmt!("%?°", self.s) } } diff --git a/src/cgmath/matrix.rs b/src/cgmath/matrix.rs index 9322f32..7d3642a 100644 --- a/src/cgmath/matrix.rs +++ b/src/cgmath/matrix.rs @@ -17,7 +17,7 @@ use std::num::{Zero, zero, One, one, cast, sqrt}; -use angle::{Angle, Rad, sin, cos, sin_cos}; +use angle::{Rad, sin, cos, sin_cos}; use array::{Array, build}; use quaternion::{Quat, ToQuat}; use vector::{Vector, EuclideanVector}; @@ -123,7 +123,7 @@ impl Mat3 { } /// Create a matrix from a rotation around the `x` axis (pitch). - pub fn from_angle_x>(theta: A) -> Mat3 { + pub fn from_angle_x(theta: Rad) -> Mat3 { // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations let (s, c) = sin_cos(theta); Mat3::new(one(), zero(), zero(), @@ -132,7 +132,7 @@ impl Mat3 { } /// Create a matrix from a rotation around the `y` axis (yaw). - pub fn from_angle_y>(theta: A) -> Mat3 { + pub fn from_angle_y(theta: Rad) -> Mat3 { // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations let (s, c) = sin_cos(theta); Mat3::new(c.clone(), zero(), -s.clone(), @@ -141,7 +141,7 @@ impl Mat3 { } /// Create a matrix from a rotation around the `z` axis (roll). - pub fn from_angle_z>(theta: A) -> Mat3 { + pub fn from_angle_z(theta: Rad) -> Mat3 { // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations let (s, c) = sin_cos(theta); Mat3::new(c.clone(), s.clone(), zero(), @@ -156,7 +156,7 @@ impl Mat3 { /// - `x`: the angular rotation around the `x` axis (pitch). /// - `y`: the angular rotation around the `y` axis (yaw). /// - `z`: the angular rotation around the `z` axis (roll). - pub fn from_euler>(x: A, y: A, z: A) -> Mat3 { + pub fn from_euler(x: Rad, y: Rad, z: Rad) -> Mat3 { // http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations let (sx, cx) = sin_cos(x); let (sy, cy) = sin_cos(y); @@ -168,7 +168,7 @@ impl Mat3 { } /// Create a matrix from a rotation around an arbitrary axis - pub fn from_axis_angle>(axis: &Vec3, angle: A) -> Mat3 { + pub fn from_axis_angle(axis: &Vec3, angle: Rad) -> Mat3 { let (s, c) = sin_cos(angle); let _1subc = one::() - c; diff --git a/src/cgmath/projection.rs b/src/cgmath/projection.rs index 98f931f..c308e26 100644 --- a/src/cgmath/projection.rs +++ b/src/cgmath/projection.rs @@ -79,7 +79,7 @@ pub struct PerspectiveFov { impl> PerspectiveFov { pub fn to_perspective(&self) -> Perspective { let angle = self.fovy.div_s(cast(2).unwrap()); - let ymax = self.near * tan(angle); + let ymax = self.near * tan(angle.to_rad()); let xmax = ymax * self.aspect; Perspective { @@ -111,7 +111,7 @@ impl> ToMat4 for PerspectiveFov { assert!(self.far > zero(), "The far plane distance cannot be below zero, found: {:?}", self.far); assert!(self.far > self.near, "The far plane cannot be closer than the near plane, found: far: {:?}, near: {:?}", self.far, self.near); - let f = cot(self.fovy.div_s(cast(2).unwrap())); + let f = cot(self.fovy.div_s(cast(2).unwrap()).to_rad()); let two: S = cast(2).unwrap(); let c0r0 = f / self.aspect; diff --git a/src/cgmath/quaternion.rs b/src/cgmath/quaternion.rs index 4d99872..3407011 100644 --- a/src/cgmath/quaternion.rs +++ b/src/cgmath/quaternion.rs @@ -52,19 +52,19 @@ impl Quat { /// Create a matrix from a rotation around the `x` axis (pitch). #[inline] - pub fn from_angle_x>(theta: A) -> Quat { + pub fn from_angle_x(theta: Rad) -> Quat { Quat::new(cos(theta.mul_s(cast(0.5).unwrap())), sin(theta), zero(), zero()) } /// Create a matrix from a rotation around the `y` axis (yaw). #[inline] - pub fn from_angle_y>(theta: A) -> Quat { + pub fn from_angle_y(theta: Rad) -> Quat { Quat::new(cos(theta.mul_s(cast(0.5).unwrap())), zero(), sin(theta), zero()) } /// Create a matrix from a rotation around the `z` axis (roll). #[inline] - pub fn from_angle_z>(theta: A) -> Quat { + pub fn from_angle_z(theta: Rad) -> Quat { Quat::new(cos(theta.mul_s(cast(0.5).unwrap())), zero(), zero(), sin(theta)) } @@ -75,7 +75,7 @@ impl Quat { /// - `x`: the angular rotation around the `x` axis (pitch). /// - `y`: the angular rotation around the `y` axis (yaw). /// - `z`: the angular rotation around the `z` axis (roll). - pub fn from_euler>(x: A, y: A, z: A) -> Quat { + pub fn from_euler(x: Rad, y: Rad, z: Rad) -> Quat { // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Conversion let (sx2, cx2) = sin_cos(x.mul_s(cast(0.5).unwrap())); let (sy2, cy2) = sin_cos(y.mul_s(cast(0.5).unwrap())); @@ -89,7 +89,7 @@ impl Quat { /// Create a quaternion from a rotation around an arbitrary axis #[inline] - pub fn from_axis_angle>(axis: &Vec3, angle: A) -> Quat { + pub fn from_axis_angle(axis: &Vec3, angle: Rad) -> Quat { let half = angle.mul_s(cast(0.5).unwrap()); Quat::from_sv(cos(half.clone()), axis.mul_s(sin(half))) diff --git a/src/cgmath/rotation.rs b/src/cgmath/rotation.rs index 64193db..699a43b 100644 --- a/src/cgmath/rotation.rs +++ b/src/cgmath/rotation.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use angle::Angle; +use angle::Rad; use matrix::Matrix; use matrix::{Mat2, ToMat2}; use matrix::{Mat3, ToMat3}; @@ -154,17 +154,17 @@ impl Rot3 { } /// Create a rotation matrix from a rotation around the `x` axis (pitch). - pub fn from_angle_x>(theta: A) -> Rot3 { + pub fn from_angle_x(theta: Rad) -> Rot3 { Rot3 { mat: Mat3::from_angle_x(theta) } } /// Create a rotation matrix from a rotation around the `y` axis (yaw). - pub fn from_angle_y>(theta: A) -> Rot3 { + pub fn from_angle_y(theta: Rad) -> Rot3 { Rot3 { mat: Mat3::from_angle_y(theta) } } /// Create a rotation matrix from a rotation around the `z` axis (roll). - pub fn from_angle_z>(theta: A) -> Rot3 { + pub fn from_angle_z(theta: Rad) -> Rot3 { Rot3 { mat: Mat3::from_angle_z(theta) } } @@ -175,12 +175,12 @@ impl Rot3 { /// - `x`: the angular rotation around the `x` axis (pitch). /// - `y`: the angular rotation around the `y` axis (yaw). /// - `z`: the angular rotation around the `z` axis (roll). - pub fn from_euler>(x: A, y: A, z: A) -> Rot3 { + pub fn from_euler(x: Rad, y: Rad, z: Rad) -> Rot3 { Rot3 { mat: Mat3::from_euler(x, y ,z) } } /// Create a rotation matrix from a rotation around an arbitrary axis. - pub fn from_axis_angle>(axis: &Vec3, angle: A) -> Rot3 { + pub fn from_axis_angle(axis: &Vec3, angle: Rad) -> Rot3 { Rot3 { mat: Mat3::from_axis_angle(axis, angle) } } From 77aeff07851b0d98fcdeaf046752a87082853f2d Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 13 Oct 2013 11:00:07 +1100 Subject: [PATCH 05/10] Rename Rot->Basis --- src/cgmath/rotation.rs | 90 +++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/cgmath/rotation.rs b/src/cgmath/rotation.rs index 699a43b..28dc015 100644 --- a/src/cgmath/rotation.rs +++ b/src/cgmath/rotation.rs @@ -30,7 +30,7 @@ pub trait Rotation2 : Eq + ApproxEq + ToMat2 -+ ToRot2 ++ ToBasis2 { fn rotate_point2(&self, point: &Point2) -> Point2; fn rotate_vec2(&self, vec: &Vec2) -> Vec2; @@ -49,7 +49,7 @@ pub trait Rotation3 : Eq + ApproxEq + ToMat3 -+ ToRot3 ++ ToBasis3 + ToQuat { fn rotate_point3(&self, point: &Point3) -> Point3; @@ -68,30 +68,30 @@ pub trait Rotation3 /// enforce orthogonality at the type level the operations have been restricted /// to a subeset of those implemented on `Mat2`. #[deriving(Eq, Clone)] -pub struct Rot2 { +pub struct Basis2 { priv mat: Mat2 } -impl Rot2 { +impl Basis2 { #[inline] pub fn as_mat2<'a>(&'a self) -> &'a Mat2 { &'a self.mat } } -pub trait ToRot2 { - fn to_rot2(&self) -> Rot2; +pub trait ToBasis2 { + fn to_rot2(&self) -> Basis2; } -impl ToRot2 for Rot2 { +impl ToBasis2 for Basis2 { #[inline] - fn to_rot2(&self) -> Rot2 { self.clone() } + fn to_rot2(&self) -> Basis2 { self.clone() } } -impl ToMat2 for Rot2 { +impl ToMat2 for Basis2 { #[inline] fn to_mat2(&self) -> Mat2 { self.mat.clone() } } -impl Rotation2 for Rot2 { +impl Rotation2 for Basis2 { #[inline] fn rotate_point2(&self, _point: &Point2) -> Point2 { fail!("Not yet implemented") } @@ -102,15 +102,15 @@ impl Rotation2 for Rot2 { fn rotate_ray2(&self, _ray: &Ray2) -> Ray2 { fail!("Not yet implemented") } #[inline] - fn concat(&self, other: &Rot2) -> Rot2 { Rot2 { mat: self.mat.mul_m(&other.mat) } } + fn concat(&self, other: &Basis2) -> Basis2 { Basis2 { mat: self.mat.mul_m(&other.mat) } } #[inline] - fn concat_self(&mut self, other: &Rot2) { self.mat.mul_self_m(&other.mat); } + fn concat_self(&mut self, other: &Basis2) { self.mat.mul_self_m(&other.mat); } // TODO: we know the matrix is orthogonal, so this could be re-written // to be faster #[inline] - fn invert(&self) -> Rot2 { Rot2 { mat: self.mat.invert().unwrap() } } + fn invert(&self) -> Basis2 { Basis2 { mat: self.mat.invert().unwrap() } } // TODO: we know the matrix is orthogonal, so this could be re-written // to be faster @@ -118,7 +118,7 @@ impl Rotation2 for Rot2 { fn invert_self(&mut self) { self.mat.invert_self(); } } -impl ApproxEq for Rot2 { +impl ApproxEq for Basis2 { #[inline] fn approx_epsilon() -> S { // TODO: fix this after static methods are fixed in rustc @@ -126,12 +126,12 @@ impl ApproxEq for Rot2 { } #[inline] - fn approx_eq(&self, other: &Rot2) -> bool { + fn approx_eq(&self, other: &Basis2) -> bool { self.mat.approx_eq(&other.mat) } #[inline] - fn approx_eq_eps(&self, other: &Rot2, approx_epsilon: &S) -> bool { + fn approx_eq_eps(&self, other: &Basis2, approx_epsilon: &S) -> bool { self.mat.approx_eq_eps(&other.mat, approx_epsilon) } } @@ -143,29 +143,29 @@ impl ApproxEq for Rot2 { /// `math::Mat3`. To ensure orthogonality is maintained, the operations have /// been restricted to a subeset of those implemented on `Mat3`. #[deriving(Eq, Clone)] -pub struct Rot3 { +pub struct Basis3 { priv mat: Mat3 } -impl Rot3 { +impl Basis3 { #[inline] - pub fn look_at(dir: &Vec3, up: &Vec3) -> Rot3 { - Rot3 { mat: Mat3::look_at(dir, up) } + pub fn look_at(dir: &Vec3, up: &Vec3) -> Basis3 { + Basis3 { mat: Mat3::look_at(dir, up) } } /// Create a rotation matrix from a rotation around the `x` axis (pitch). - pub fn from_angle_x(theta: Rad) -> Rot3 { - Rot3 { mat: Mat3::from_angle_x(theta) } + pub fn from_angle_x(theta: Rad) -> Basis3 { + Basis3 { mat: Mat3::from_angle_x(theta) } } /// Create a rotation matrix from a rotation around the `y` axis (yaw). - pub fn from_angle_y(theta: Rad) -> Rot3 { - Rot3 { mat: Mat3::from_angle_y(theta) } + pub fn from_angle_y(theta: Rad) -> Basis3 { + Basis3 { mat: Mat3::from_angle_y(theta) } } /// Create a rotation matrix from a rotation around the `z` axis (roll). - pub fn from_angle_z(theta: Rad) -> Rot3 { - Rot3 { mat: Mat3::from_angle_z(theta) } + pub fn from_angle_z(theta: Rad) -> Basis3 { + Basis3 { mat: Mat3::from_angle_z(theta) } } /// Create a rotation matrix from a set of euler angles. @@ -175,39 +175,39 @@ impl Rot3 { /// - `x`: the angular rotation around the `x` axis (pitch). /// - `y`: the angular rotation around the `y` axis (yaw). /// - `z`: the angular rotation around the `z` axis (roll). - pub fn from_euler(x: Rad, y: Rad, z: Rad) -> Rot3 { - Rot3 { mat: Mat3::from_euler(x, y ,z) } + pub fn from_euler(x: Rad, y: Rad, z: Rad) -> Basis3 { + Basis3 { mat: Mat3::from_euler(x, y ,z) } } /// Create a rotation matrix from a rotation around an arbitrary axis. - pub fn from_axis_angle(axis: &Vec3, angle: Rad) -> Rot3 { - Rot3 { mat: Mat3::from_axis_angle(axis, angle) } + pub fn from_axis_angle(axis: &Vec3, angle: Rad) -> Basis3 { + Basis3 { mat: Mat3::from_axis_angle(axis, angle) } } #[inline] pub fn as_mat3<'a>(&'a self) -> &'a Mat3 { &'a self.mat } } -pub trait ToRot3 { - fn to_rot3(&self) -> Rot3; +pub trait ToBasis3 { + fn to_rot3(&self) -> Basis3; } -impl ToRot3 for Rot3 { +impl ToBasis3 for Basis3 { #[inline] - fn to_rot3(&self) -> Rot3 { self.clone() } + fn to_rot3(&self) -> Basis3 { self.clone() } } -impl ToMat3 for Rot3 { +impl ToMat3 for Basis3 { #[inline] fn to_mat3(&self) -> Mat3 { self.mat.clone() } } -impl ToQuat for Rot3 { +impl ToQuat for Basis3 { #[inline] fn to_quat(&self) -> Quat { self.mat.to_quat() } } -impl Rotation3 for Rot3 { +impl Rotation3 for Basis3 { #[inline] fn rotate_point3(&self, _point: &Point3) -> Point3 { fail!("Not yet implemented") } @@ -218,15 +218,15 @@ impl Rotation3 for Rot3 { fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { fail!("Not yet implemented") } #[inline] - fn concat(&self, other: &Rot3) -> Rot3 { Rot3 { mat: self.mat.mul_m(&other.mat) } } + fn concat(&self, other: &Basis3) -> Basis3 { Basis3 { mat: self.mat.mul_m(&other.mat) } } #[inline] - fn concat_self(&mut self, other: &Rot3) { self.mat.mul_self_m(&other.mat); } + fn concat_self(&mut self, other: &Basis3) { self.mat.mul_self_m(&other.mat); } // TODO: we know the matrix is orthogonal, so this could be re-written // to be faster #[inline] - fn invert(&self) -> Rot3 { Rot3 { mat: self.mat.invert().unwrap() } } + fn invert(&self) -> Basis3 { Basis3 { mat: self.mat.invert().unwrap() } } // TODO: we know the matrix is orthogonal, so this could be re-written // to be faster @@ -234,7 +234,7 @@ impl Rotation3 for Rot3 { fn invert_self(&mut self) { self.mat.invert_self(); } } -impl ApproxEq for Rot3 { +impl ApproxEq for Basis3 { #[inline] fn approx_epsilon() -> S { // TODO: fix this after static methods are fixed in rustc @@ -242,21 +242,21 @@ impl ApproxEq for Rot3 { } #[inline] - fn approx_eq(&self, other: &Rot3) -> bool { + fn approx_eq(&self, other: &Basis3) -> bool { self.mat.approx_eq(&other.mat) } #[inline] - fn approx_eq_eps(&self, other: &Rot3, approx_epsilon: &S) -> bool { + fn approx_eq_eps(&self, other: &Basis3, approx_epsilon: &S) -> bool { self.mat.approx_eq_eps(&other.mat, approx_epsilon) } } // Quaternion Rotation impls -impl ToRot3 for Quat { +impl ToBasis3 for Quat { #[inline] - fn to_rot3(&self) -> Rot3 { Rot3 { mat: self.to_mat3() } } + fn to_rot3(&self) -> Basis3 { Basis3 { mat: self.to_mat3() } } } impl ToQuat for Quat { From 66a329c5913176015852fb1276aaa839c2965d7a Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 13 Oct 2013 11:00:51 +1100 Subject: [PATCH 06/10] Initial commit of transform module --- src/cgmath/transform.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/cgmath/transform.rs diff --git a/src/cgmath/transform.rs b/src/cgmath/transform.rs new file mode 100644 index 0000000..5e30dac --- /dev/null +++ b/src/cgmath/transform.rs @@ -0,0 +1,40 @@ +// Copyright 2013 The CGMath Developers. For a full listing of the authors, +// refer to the AUTHORS file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub trait Transform { + fn transform_vec(&self, point: Point3) -> Point3; + fn transform_point(&self, point: Point3) -> Point3; + fn transform_ray(&self, ray: Ray3) -> Ray3; +} + +/// A homogeneous transformation matrix. +pub struct AffineMatrix3 { + mat: Mat4, +} + +/// A transformation in three dimensions consisting of a rotation, +/// displacement vector and scale amount. +pub struct Transform3 { + rot: R, + disp: Vec3, + scale: S, +} + +impl> Transform3 { + #[inline] + pub fn new(rot: R, disp: Vec3, scale: S) -> Transform3 { + Transform3 { rot: rot, disp: disp, scale: S } + } +} From 7fd9f582b6f416ebe3dfa47984629c27ff6775ed Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 14 Oct 2013 22:48:45 +1100 Subject: [PATCH 07/10] Make point structs public --- src/cgmath/point.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cgmath/point.rs b/src/cgmath/point.rs index 91eb9dc..e611e00 100644 --- a/src/cgmath/point.rs +++ b/src/cgmath/point.rs @@ -24,11 +24,11 @@ use vector::*; /// A point in 2-dimensional space. #[deriving(Eq, Zero, Clone)] -struct Point2 { x: S, y: S } +pub struct Point2 { x: S, y: S } /// A point in 2-dimensional space. #[deriving(Eq, Zero, Clone)] -struct Point3 { x: S, y: S, z: S } +pub struct Point3 { x: S, y: S, z: S } approx_eq!(impl Point2) approx_eq!(impl Point3) From 977aed60b03b7909fdf8cf15899425217bf38ef9 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 14 Oct 2013 22:49:04 +1100 Subject: [PATCH 08/10] Add .travis.yml --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..fc4711d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +before_install: + - yes | sudo add-apt-repository ppa:hansjorg/rust + - sudo apt-get update +install: + - sudo apt-get install rust-nightly +script: + - rustpkg build cgmath \ No newline at end of file From ff3522a711f2f1b207abecb9215238083205b079 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 20 Oct 2013 01:00:44 +1100 Subject: [PATCH 09/10] Replace usages of fmt! with format! --- src/cgmath/angle.rs | 8 ++++---- src/cgmath/point.rs | 9 +++++---- src/cgmath/quaternion.rs | 5 +++-- src/cgmath/vector.rs | 13 +++++++------ 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/cgmath/angle.rs b/src/cgmath/angle.rs index 38a1ec9..9e23bfe 100644 --- a/src/cgmath/angle.rs +++ b/src/cgmath/angle.rs @@ -15,11 +15,11 @@ //! Angle units for type-safe, self-documenting code. -pub use std::num::{cast, zero}; pub use std::num::{sinh, cosh, tanh}; pub use std::num::{asinh, acosh, atanh}; -use std::num::Zero; +use std::fmt; +use std::num::{Zero, zero, cast}; #[deriving(Clone, Eq, Ord, Zero)] pub struct Rad { s: S } #[deriving(Clone, Eq, Ord, Zero)] pub struct Deg { s: S } @@ -180,8 +180,8 @@ impl Angle for Deg { #[inline] pub fn atan(s: S) -> Rad { rad(s.atan()) } #[inline] pub fn atan2(a: S, b: S) -> Rad { rad(a.atan2(&b)) } -impl ToStr for Rad { fn to_str(&self) -> ~str { fmt!("%? rad", self.s) } } -impl ToStr for Deg { fn to_str(&self) -> ~str { fmt!("%?°", self.s) } } +impl ToStr for Rad { fn to_str(&self) -> ~str { format!("{} rad", self.s) } } +impl ToStr for Deg { fn to_str(&self) -> ~str { format!("{}°", self.s) } } impl ApproxEq for Rad { #[inline] diff --git a/src/cgmath/point.rs b/src/cgmath/point.rs index e611e00..bc2cfb6 100644 --- a/src/cgmath/point.rs +++ b/src/cgmath/point.rs @@ -17,6 +17,7 @@ //! disinguishes them from vectors, which have a length and direction, but do //! not have a fixed position. +use std::fmt; use std::num::zero; use array::*; @@ -88,14 +89,14 @@ array!(impl Point3 -> [S, ..3] _3) impl Point, [S, ..2]> for Point2 {} impl Point, [S, ..3]> for Point3 {} -impl ToStr for Point2 { +impl ToStr for Point2 { fn to_str(&self) -> ~str { - fmt!("[%?, %?]", self.x, self.y) + format!("[{}, {}]", self.x, self.y) } } -impl ToStr for Point3 { +impl ToStr for Point3 { fn to_str(&self) -> ~str { - fmt!("[%?, %?, %?]", self.x, self.y, self.z) + format!("[{}, {}, {}]", self.x, self.y, self.z) } } diff --git a/src/cgmath/quaternion.rs b/src/cgmath/quaternion.rs index 3407011..0e94329 100644 --- a/src/cgmath/quaternion.rs +++ b/src/cgmath/quaternion.rs @@ -13,6 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::fmt; use std::num::{zero, one, cast, sqrt}; use angle::{Angle, Rad, acos, cos, sin, sin_cos}; @@ -296,8 +297,8 @@ impl Neg> for Quat { } } -impl ToStr for Quat { +impl ToStr for Quat { fn to_str(&self) -> ~str { - fmt!("%? + %?i + %?j + %?k", self.s, self.v.x, self.v.y, self.v.z) + format!("{} + {}i + {}j + {}k", self.s, self.v.x, self.v.y, self.v.z) } } diff --git a/src/cgmath/vector.rs b/src/cgmath/vector.rs index 713fb84..bc8f8b5 100644 --- a/src/cgmath/vector.rs +++ b/src/cgmath/vector.rs @@ -13,6 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::fmt; use std::num::{Zero, zero, One, one, sqrt}; use angle::{Rad, atan2, acos}; @@ -282,20 +283,20 @@ impl EuclideanVector for Vec4 { } } -impl ToStr for Vec2 { +impl ToStr for Vec2 { fn to_str(&self) -> ~str { - fmt!("[%?, %?]", self.x, self.y) + format!("[{}, {}]", self.x, self.y) } } -impl ToStr for Vec3 { +impl ToStr for Vec3 { fn to_str(&self) -> ~str { - fmt!("[%?, %?, %?]", self.x, self.y, self.z) + format!("[{}, {}, {}]", self.x, self.y, self.z) } } -impl ToStr for Vec4 { +impl ToStr for Vec4 { fn to_str(&self) -> ~str { - fmt!("[%?, %?, %?, %?]", self.x, self.y, self.z, self.w) + format!("[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } From c283c9d1e72f88dcc904db4bb4add111fc10320a Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 21 Oct 2013 11:30:30 +1100 Subject: [PATCH 10/10] Add trait for accessing the pointer to the first element of a type --- src/cgmath/lib.rs | 2 ++ src/cgmath/ptr.rs | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/cgmath/ptr.rs diff --git a/src/cgmath/lib.rs b/src/cgmath/lib.rs index 7842085..29f05db 100644 --- a/src/cgmath/lib.rs +++ b/src/cgmath/lib.rs @@ -44,3 +44,5 @@ pub mod frustum; pub mod intersect; pub mod obb; pub mod sphere; + +pub mod ptr; diff --git a/src/cgmath/ptr.rs b/src/cgmath/ptr.rs new file mode 100644 index 0000000..2810103 --- /dev/null +++ b/src/cgmath/ptr.rs @@ -0,0 +1,38 @@ +// Copyright 2013 The CGMath Developers. For a full listing of the authors, +// refer to the AUTHORS file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use array::Array; +use matrix::{Mat2, Mat3, Mat4}; +use point::{Point2, Point3}; +use vector::{Vec2, Vec3, Vec4}; + +pub trait Ptr { + fn ptr<'a>(&'a self) -> &'a T; +} + +impl Ptr for Vec2 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } } +impl Ptr for Vec3 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } } +impl Ptr for Vec4 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } } + +impl Ptr for Point2 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } } +impl Ptr for Point3 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } } + +impl Ptr for Mat2 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } } +impl Ptr for Mat3 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } } +impl Ptr for Mat4 { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } } + +impl<'self, T, P: Ptr> Ptr for &'self [P] { + #[inline] fn ptr<'a>(&'a self) -> &'a T { self[0].ptr() } +}