diff --git a/src/lmath.rs b/src/lmath.rs index c253378..c2fb1df 100644 --- a/src/lmath.rs +++ b/src/lmath.rs @@ -25,8 +25,6 @@ extern mod std; -pub mod num; - pub mod mat; pub mod quat; pub mod vec; diff --git a/src/mat.rs b/src/mat.rs index 49e84b4..dc5be50 100644 --- a/src/mat.rs +++ b/src/mat.rs @@ -15,462 +15,48 @@ use std::cast::transmute; use std::cmp::ApproxEq; -use std::num::{Zero, One, cast}; +use std::num::{Zero, One}; use std::uint; use vec::*; use quat::Quat; -use num::NumAssign; - -/// The base square matrix trait -/// -/// # Type parameters -/// -/// - `T`: The type of the elements of the matrix. Should be a floating point type. -/// - `V`: The type of the row and column vectors. Should have components of a -/// floating point type and have the same number of dimensions as the -/// number of rows and columns in the matrix. -pub trait BaseMat: Eq + Neg { - /// The column vector at `i` - fn col<'a>(&'a self, i: uint) -> &'a V; - - /// The row vector at `i` - fn row(&self, i: uint) -> V; - - /// The matrix element at `i`, `j` - fn elem<'a>(&'a self, i: uint, j: uint) -> &'a T; - - /// Construct a diagonal matrix with the major diagonal set to `value` - fn from_value(value: T) -> Self; - - /// The identity matrix - fn identity() -> Self; - - /// A matrix with all elements set to zero - fn zero() -> Self; - - /// The scalar multiplication of this matrix and `value` - fn mul_t(&self, value: T) -> Self; - - /// The matrix vector product of the matrix and `vec` - fn mul_v(&self, vec: &V) -> V; - - /// The matrix addition of the matrix and `other` - fn add_m(&self, other: &Self) -> Self; - - /// The difference between the matrix and `other` - fn sub_m(&self, other: &Self) -> Self; - - /// The matrix product of the matrix and `other` - fn mul_m(&self, other: &Self) -> Self; - - /// The matrix dot product of the matrix and `other` - fn dot(&self, other: &Self) -> T; - - /// The determinant of the matrix - fn determinant(&self) -> T; - - /// The sum of the main diagonal of the matrix - fn trace(&self) -> T; - - /// Returns the inverse of the matrix - /// - /// # Return value - /// - /// - `Some(m)`: if the inversion was successful, where `m` is the inverted matrix - /// - `None`: if the inversion was unsuccessful (because the matrix was not invertable) - fn inverse(&self) -> Option; - - /// The transposed matrix - fn transpose(&self) -> Self; - - /// A mutable reference to the column at `i` - fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut V; - - /// A mutable reference to the matrix element at `i`, `j` - fn elem_mut<'a>(&'a mut self, i: uint, j: uint) -> &'a mut T; - - /// Swap two columns of the matrix in place - fn swap_cols(&mut self, a: uint, b: uint); - - /// Swap two rows of the matrix in place - fn swap_rows(&mut self, a: uint, b: uint); - - /// Sets the matrix to `other` - fn set(&mut self, other: &Self); - - /// Sets the matrix to the identity matrix - fn to_identity(&mut self); - - /// Sets each element of the matrix to zero - fn to_zero(&mut self); - - /// Multiplies the matrix by a scalar - fn mul_self_t(&mut self, value: T); - - /// Add the matrix `other` to `self` - fn add_self_m(&mut self, other: &Self); - - /// Subtract the matrix `other` from `self` - fn sub_self_m(&mut self, other: &Self); - - /// Sets the matrix to its inverse - /// - /// # Failure - /// - /// Fails if the matrix is not invertable. Make sure you check with the - /// `is_invertible` method before you attempt this! - fn invert_self(&mut self); - - /// Sets the matrix to its transpose - fn transpose_self(&mut self); - - /// Check to see if the matrix is an identity matrix - /// - /// # Return value - /// - /// `true` if the matrix is approximately equal to the identity matrix - fn is_identity(&self) -> bool; - - /// Check to see if the matrix is diagonal - /// - /// # Return value - /// - /// `true` all the elements outside the main diagonal are approximately - /// equal to zero. - fn is_diagonal(&self) -> bool; - - /// Check to see if the matrix is rotated - /// - /// # Return value - /// - /// `true` if the matrix is not approximately equal to the identity matrix. - fn is_rotated(&self) -> bool; - - /// Check to see if the matrix is symmetric - /// - /// # Return value - /// - /// `true` if the matrix is approximately equal to its transpose). - fn is_symmetric(&self) -> bool; - - /// Check to see if the matrix is invertable - /// - /// # Return value - /// - /// `true` if the matrix is invertable - fn is_invertible(&self) -> bool; - - /// A pointer to the first element of the matrix - fn to_ptr(&self) -> *T; -} - -/// A 2 x 2 matrix -pub trait BaseMat2: BaseMat { - fn new(c0r0: T, c0r1: T, - c1r0: T, c1r1: T) -> Self; - - fn from_cols(c0: V, c1: V) -> Self; - - fn from_angle(radians: T) -> Self; - - fn to_mat3(&self) -> Mat3; - - fn to_mat4(&self) -> Mat4; -} - -/// A 3 x 3 matrix -pub trait BaseMat3: BaseMat { - fn new(c0r0:T, c0r1:T, c0r2:T, - c1r0:T, c1r1:T, c1r2:T, - c2r0:T, c2r1:T, c2r2:T) -> Self; - - fn from_cols(c0: V, c1: V, c2: V) -> Self; - - fn from_angle_x(radians: T) -> Self; - - fn from_angle_y(radians: T) -> Self; - - fn from_angle_z(radians: T) -> Self; - - fn from_angle_xyz(radians_x: T, radians_y: T, radians_z: T) -> Self; - - fn from_angle_axis(radians: T, axis: &Vec3) -> Self; - - fn from_axes(x: V, y: V, z: V) -> Self; - - fn look_at(dir: &Vec3, up: &Vec3) -> Self; - - fn to_mat4(&self) -> Mat4; - - fn to_quat(&self) -> Quat; -} - -/// A 4 x 4 matrix -pub trait BaseMat4: BaseMat { - fn new(c0r0: T, c0r1: T, c0r2: T, c0r3: T, - c1r0: T, c1r1: T, c1r2: T, c1r3: T, - c2r0: T, c2r1: T, c2r2: T, c2r3: T, - c3r0: T, c3r1: T, c3r2: T, c3r3: T) -> Self; - - fn from_cols(c0: V, c1: V, c2: V, c3: V) -> Self; -} - -/// A 2 x 2 column major matrix -/// -/// # Type parameters -/// -/// - `T`: The type of the elements of the matrix. Should be a floating point type. -/// -/// # Fields -/// -/// - `x`: the first column vector of the matrix -/// - `y`: the second column vector of the matrix -/// - `z`: the third column vector of the matrix #[deriving(Eq)] pub struct Mat2 { x: Vec2, y: Vec2 } -impl BaseMat> for Mat2 { +impl Mat2 { #[inline(always)] - fn col<'a>(&'a self, i: uint) -> &'a Vec2 { - unsafe { &'a transmute::<&'a Mat2, &'a [Vec2,..2]>(self)[i] } + pub fn col<'a>(&'a self, i: uint) -> &'a Vec2 { + &'a self.as_slice()[i] } #[inline(always)] - fn row(&self, i: uint) -> Vec2 { - BaseVec2::new(*self.col(0).index(i), - *self.col(1).index(i)) + pub fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec2 { + &'a mut self.as_mut_slice()[i] } #[inline(always)] - fn elem<'a>(&'a self, i: uint, j: uint) -> &'a T { + pub fn as_slice<'a>(&'a self) -> &'a [Vec2,..2] { + unsafe { transmute(self) } + } + + #[inline(always)] + pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Vec2,..2] { + unsafe { transmute(self) } + } + + #[inline(always)] + pub fn elem<'a>(&'a self, i: uint, j: uint) -> &'a T { self.col(i).index(j) } - /// Construct a 2 x 2 diagonal matrix with the major diagonal set to `value` - /// - /// # Arguments - /// - /// - `value`: the value to set the major diagonal to - /// - /// ~~~ - /// c0 c1 - /// +-----+-----+ - /// r0 | val | 0 | - /// +-----+-----+ - /// r1 | 0 | val | - /// +-----+-----+ - /// ~~~ #[inline(always)] - fn from_value(value: T) -> Mat2 { - BaseMat2::new(value, Zero::zero(), - Zero::zero(), value) - } - - /// Returns the multiplicative identity matrix - /// ~~~ - /// c0 c1 - /// +----+----+ - /// r0 | 1 | 0 | - /// +----+----+ - /// r1 | 0 | 1 | - /// +----+----+ - /// ~~~ - #[inline(always)] - fn identity() -> Mat2 { - BaseMat2::new( One::one::(), Zero::zero::(), - Zero::zero::(), One::one::()) - } - - /// Returns the additive identity matrix - /// ~~~ - /// c0 c1 - /// +----+----+ - /// r0 | 0 | 0 | - /// +----+----+ - /// r1 | 0 | 0 | - /// +----+----+ - /// ~~~ - #[inline(always)] - fn zero() -> Mat2 { - BaseMat2::new(Zero::zero::(), Zero::zero::(), - Zero::zero::(), Zero::zero::()) - } - - #[inline(always)] - fn mul_t(&self, value: T) -> Mat2 { - BaseMat2::from_cols(self.col(0).mul_t(value), - self.col(1).mul_t(value)) - } - - #[inline(always)] - fn mul_v(&self, vec: &Vec2) -> Vec2 { - BaseVec2::new(self.row(0).dot(vec), - self.row(1).dot(vec)) - } - - #[inline(always)] - fn add_m(&self, other: &Mat2) -> Mat2 { - BaseMat2::from_cols(self.col(0).add_v(other.col(0)), - self.col(1).add_v(other.col(1))) - } - - #[inline(always)] - fn sub_m(&self, other: &Mat2) -> Mat2 { - BaseMat2::from_cols(self.col(0).sub_v(other.col(0)), - self.col(1).sub_v(other.col(1))) - } - - #[inline(always)] - fn mul_m(&self, other: &Mat2) -> Mat2 { - BaseMat2::new(self.row(0).dot(other.col(0)), self.row(1).dot(other.col(0)), - self.row(0).dot(other.col(1)), self.row(1).dot(other.col(1))) - } - - fn dot(&self, other: &Mat2) -> T { - other.transpose().mul_m(self).trace() - } - - fn determinant(&self) -> T { - (*self.col(0).index(0)) * - (*self.col(1).index(1)) - - (*self.col(1).index(0)) * - (*self.col(0).index(1)) - } - - fn trace(&self) -> T { - (*self.col(0).index(0)) + - (*self.col(1).index(1)) - } - - #[inline(always)] - fn inverse(&self) -> Option> { - let d = self.determinant(); - if d.approx_eq(&Zero::zero()) { - None - } else { - Some(BaseMat2::new( self.elem(1, 1) / d, -self.elem(0, 1) / d, - -self.elem(1, 0) / d, self.elem(0, 0) / d)) - } - } - - #[inline(always)] - fn transpose(&self) -> Mat2 { - BaseMat2::new(*self.elem(0, 0), *self.elem(1, 0), - *self.elem(0, 1), *self.elem(1, 1)) - } - - #[inline(always)] - fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec2 { - unsafe { &'a mut transmute::<&'a mut Mat2, &'a mut [Vec2,..2]>(self)[i] } - } - - #[inline(always)] - fn elem_mut<'a>(&'a mut self, i: uint, j: uint) -> &'a mut T { + pub fn elem_mut<'a>(&'a mut self, i: uint, j: uint) -> &'a mut T { self.col_mut(i).index_mut(j) } - - #[inline(always)] - fn swap_cols(&mut self, a: uint, b: uint) { - let tmp = *self.col(a); - *self.col_mut(a) = *self.col(b); - *self.col_mut(b) = tmp; - } - - #[inline(always)] - fn swap_rows(&mut self, a: uint, b: uint) { - self.x.swap(a, b); - self.y.swap(a, b); - } - - #[inline(always)] - fn set(&mut self, other: &Mat2) { - (*self) = (*other); - } - - #[inline(always)] - fn to_identity(&mut self) { - (*self) = BaseMat::identity(); - } - - #[inline(always)] - fn to_zero(&mut self) { - (*self) = BaseMat::zero(); - } - - #[inline(always)] - fn mul_self_t(&mut self, value: T) { - self.x.mul_self_t(value); - self.y.mul_self_t(value); - } - - #[inline(always)] - fn add_self_m(&mut self, other: &Mat2) { - self.x.add_self_v(other.col(0)); - self.y.add_self_v(other.col(1)); - } - - #[inline(always)] - fn sub_self_m(&mut self, other: &Mat2) { - self.x.sub_self_v(other.col(0)); - self.y.sub_self_v(other.col(1)); - } - - #[inline(always)] - fn invert_self(&mut self) { - match self.inverse() { - Some(m) => (*self) = m, - None => fail!(~"Couldn't invert the matrix!") - } - } - - #[inline(always)] - fn transpose_self(&mut self) { - let tmp01 = *self.elem(0, 1); - let tmp10 = *self.elem(1, 0); - - *self.elem_mut(0, 1) = *self.elem(1, 0); - *self.elem_mut(1, 0) = *self.elem(0, 1); - - *self.elem_mut(1, 0) = tmp01; - *self.elem_mut(0, 1) = tmp10; - } - - #[inline(always)] - fn is_identity(&self) -> bool { - self.approx_eq(&BaseMat::identity()) - } - - #[inline(always)] - fn is_diagonal(&self) -> bool { - self.elem(0, 1).approx_eq(&Zero::zero()) && - self.elem(1, 0).approx_eq(&Zero::zero()) - } - - #[inline(always)] - fn is_rotated(&self) -> bool { - !self.approx_eq(&BaseMat::identity()) - } - - #[inline(always)] - fn is_symmetric(&self) -> bool { - self.elem(0, 1).approx_eq(self.elem(1, 0)) && - self.elem(1, 0).approx_eq(self.elem(0, 1)) - } - - #[inline(always)] - fn is_invertible(&self) -> bool { - !self.determinant().approx_eq(&Zero::zero()) - } - - #[inline(always)] - fn to_ptr(&self) -> *T { - unsafe { transmute(self) } - } } -impl BaseMat2> for Mat2 { +impl Mat2 { /// Construct a 2 x 2 matrix /// /// # Arguments @@ -487,10 +73,10 @@ impl BaseMat2> for Mat2 { /// +------+------+ /// ~~~ #[inline(always)] - fn new(c0r0: T, c0r1: T, - c1r0: T, c1r1: T) -> Mat2 { - BaseMat2::from_cols(BaseVec2::new::>(c0r0, c0r1), - BaseVec2::new::>(c1r0, c1r1)) + pub fn new(c0r0: T, c0r1: T, + c1r0: T, c1r1: T) -> Mat2 { + Mat2::from_cols(Vec2::new(c0r0, c0r1), + Vec2::new(c1r0, c1r1)) } /// Construct a 2 x 2 matrix from column vectors @@ -509,17 +95,167 @@ impl BaseMat2> for Mat2 { /// +------+------+ /// ~~~ #[inline(always)] - fn from_cols(c0: Vec2, c1: Vec2) -> Mat2 { + pub fn from_cols(c0: Vec2, + c1: Vec2) -> Mat2 { Mat2 { x: c0, y: c1 } } #[inline(always)] - fn from_angle(radians: T) -> Mat2 { - let cos_theta = radians.cos(); - let sin_theta = radians.sin(); + pub fn row(&self, i: uint) -> Vec2 { + Vec2::new(*self.elem(0, i), + *self.elem(1, i)) + } - BaseMat2::new(cos_theta, -sin_theta, - sin_theta, cos_theta) + #[inline(always)] + pub fn swap_cols(&mut self, a: uint, b: uint) { + let tmp = *self.col(a); + *self.col_mut(a) = *self.col(b); + *self.col_mut(b) = tmp; + } + + #[inline(always)] + pub fn swap_rows(&mut self, a: uint, b: uint) { + self.x.swap(a, b); + self.y.swap(a, b); + } + + #[inline(always)] + pub fn transpose(&self) -> Mat2 { + Mat2::new(*self.elem(0, 0), *self.elem(1, 0), + *self.elem(0, 1), *self.elem(1, 1)) + } + + #[inline(always)] + pub fn transpose_self(&mut self) { + let tmp01 = *self.elem(0, 1); + let tmp10 = *self.elem(1, 0); + + *self.elem_mut(0, 1) = *self.elem(1, 0); + *self.elem_mut(1, 0) = *self.elem(0, 1); + + *self.elem_mut(1, 0) = tmp01; + *self.elem_mut(0, 1) = tmp10; + } +} + +impl Mat2 { + /// Construct a 2 x 2 diagonal matrix with the major diagonal set to `value`. + /// ~~~ + /// c0 c1 + /// +-----+-----+ + /// r0 | val | 0 | + /// +-----+-----+ + /// r1 | 0 | val | + /// +-----+-----+ + /// ~~~ + #[inline(always)] + pub fn from_value(value: T) -> Mat2 { + Mat2::new(value, Zero::zero(), + Zero::zero(), value) + } + + /// Returns the multiplicative identity matrix + /// ~~~ + /// c0 c1 + /// +----+----+ + /// r0 | 1 | 0 | + /// +----+----+ + /// r1 | 0 | 1 | + /// +----+----+ + /// ~~~ + #[inline(always)] + pub fn identity() -> Mat2 { + Mat2::new(One::one::(), Zero::zero::(), + Zero::zero::(), One::one::()) + } + + /// Returns the additive identity matrix + /// ~~~ + /// c0 c1 + /// +----+----+ + /// r0 | 0 | 0 | + /// +----+----+ + /// r1 | 0 | 0 | + /// +----+----+ + /// ~~~ + #[inline(always)] + pub fn zero() -> Mat2 { + Mat2::new(Zero::zero::(), Zero::zero::(), + Zero::zero::(), Zero::zero::()) + } + + #[inline(always)] + pub fn mul_t(&self, value: T) -> Mat2 { + Mat2::from_cols(self.col(0).mul_t(value), + self.col(1).mul_t(value)) + } + + #[inline(always)] + pub fn mul_v(&self, vec: &Vec2) -> Vec2 { + Vec2::new(self.row(0).dot(vec), + self.row(1).dot(vec)) + } + + #[inline(always)] + pub fn add_m(&self, other: &Mat2) -> Mat2 { + Mat2::from_cols(self.col(0).add_v(other.col(0)), + self.col(1).add_v(other.col(1))) + } + + #[inline(always)] + pub fn sub_m(&self, other: &Mat2) -> Mat2 { + Mat2::from_cols(self.col(0).sub_v(other.col(0)), + self.col(1).sub_v(other.col(1))) + } + + #[inline(always)] + pub fn mul_m(&self, other: &Mat2) -> Mat2 { + Mat2::new(self.row(0).dot(other.col(0)), self.row(1).dot(other.col(0)), + self.row(0).dot(other.col(1)), self.row(1).dot(other.col(1))) + } + + #[inline(always)] + pub fn mul_self_t(&mut self, value: T) { + self.x.mul_self_t(value); + self.y.mul_self_t(value); + } + + #[inline(always)] + pub fn add_self_m(&mut self, other: &Mat2) { + self.x.add_self_v(other.col(0)); + self.y.add_self_v(other.col(1)); + } + + #[inline(always)] + pub fn sub_self_m(&mut self, other: &Mat2) { + self.x.sub_self_v(other.col(0)); + self.y.sub_self_v(other.col(1)); + } + + pub fn dot(&self, other: &Mat2) -> T { + other.transpose().mul_m(self).trace() + } + + pub fn determinant(&self) -> T { + *self.col(0).index(0) * + *self.col(1).index(1) - + *self.col(1).index(0) * + *self.col(0).index(1) + } + + pub fn trace(&self) -> T { + *self.col(0).index(0) + + *self.col(1).index(1) + } + + #[inline(always)] + pub fn to_identity(&mut self) { + *self = Mat2::identity(); + } + + #[inline(always)] + pub fn to_zero(&mut self) { + *self = Mat2::zero(); } /// Returns the the matrix with an extra row and column added @@ -534,10 +270,10 @@ impl BaseMat2> for Mat2 { /// +----+----+----+ /// ~~~ #[inline(always)] - fn to_mat3(&self) -> Mat3 { - BaseMat3::new(*self.elem(0, 0), *self.elem(0, 1), Zero::zero(), - *self.elem(1, 0), *self.elem(1, 1), Zero::zero(), - Zero::zero(), Zero::zero(), One::one()) + pub fn to_mat3(&self) -> Mat3 { + Mat3::new(*self.elem(0, 0), *self.elem(0, 1), Zero::zero(), + *self.elem(1, 0), *self.elem(1, 1), Zero::zero(), + Zero::zero(), Zero::zero(), One::one()) } /// Returns the the matrix with an extra two rows and columns added @@ -554,45 +290,97 @@ impl BaseMat2> for Mat2 { /// +----+----+----+----+ /// ~~~ #[inline(always)] - fn to_mat4(&self) -> Mat4 { - BaseMat4::new(*self.elem(0, 0), *self.elem(0, 1), Zero::zero(), Zero::zero(), - *self.elem(1, 0), *self.elem(1, 1), Zero::zero(), Zero::zero(), - Zero::zero(), Zero::zero(), One::one(), Zero::zero(), - Zero::zero(), Zero::zero(), Zero::zero(), One::one()) + pub fn to_mat4(&self) -> Mat4 { + Mat4::new(*self.elem(0, 0), *self.elem(0, 1), Zero::zero(), Zero::zero(), + *self.elem(1, 0), *self.elem(1, 1), Zero::zero(), Zero::zero(), + Zero::zero(), Zero::zero(), One::one(), Zero::zero(), + Zero::zero(), Zero::zero(), Zero::zero(), One::one()) } } -impl Neg> for Mat2 { +impl Neg> for Mat2 { #[inline(always)] - fn neg(&self) -> Mat2 { - BaseMat2::from_cols(-self.col(0), -self.col(1)) + pub fn neg(&self) -> Mat2 { + Mat2::from_cols(-self.col(0), -self.col(1)) } } -impl ApproxEq for Mat2 { +impl Mat2 { #[inline(always)] - fn approx_epsilon() -> T { + pub fn from_angle(radians: T) -> Mat2 { + let cos_theta = radians.cos(); + let sin_theta = radians.sin(); + + Mat2::new(cos_theta, -sin_theta, + sin_theta, cos_theta) + } +} + +impl> Mat2 { + #[inline(always)] + pub fn inverse(&self) -> Option> { + let d = self.determinant(); + if d.approx_eq(&Zero::zero()) { + None + } else { + Some(Mat2::new(self.elem(1, 1) / d, -self.elem(0, 1) / d, + -self.elem(1, 0) / d, self.elem(0, 0) / d)) + } + } + + #[inline(always)] + pub fn invert_self(&mut self) { + *self = self.inverse().expect("Couldn't invert the matrix!"); + } + + #[inline(always)] + pub fn is_identity(&self) -> bool { + self.approx_eq(&Mat2::identity()) + } + + #[inline(always)] + pub fn is_diagonal(&self) -> bool { + self.elem(0, 1).approx_eq(&Zero::zero()) && + self.elem(1, 0).approx_eq(&Zero::zero()) + } + + #[inline(always)] + pub fn is_rotated(&self) -> bool { + !self.approx_eq(&Mat2::identity()) + } + + #[inline(always)] + pub fn is_symmetric(&self) -> bool { + self.elem(0, 1).approx_eq(self.elem(1, 0)) && + self.elem(1, 0).approx_eq(self.elem(0, 1)) + } + + #[inline(always)] + pub fn is_invertible(&self) -> bool { + !self.determinant().approx_eq(&Zero::zero()) + } +} + +impl> ApproxEq for Mat2 { + #[inline(always)] + pub fn approx_epsilon() -> T { ApproxEq::approx_epsilon::() } #[inline(always)] - fn approx_eq(&self, other: &Mat2) -> bool { + pub fn approx_eq(&self, other: &Mat2) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } #[inline(always)] - fn approx_eq_eps(&self, other: &Mat2, epsilon: &T) -> bool { + pub fn approx_eq_eps(&self, other: &Mat2, epsilon: &T) -> bool { self.col(0).approx_eq_eps(other.col(0), epsilon) && self.col(1).approx_eq_eps(other.col(1), epsilon) } } -// GLSL-style type aliases, corresponding to Section 4.1.6 of the [GLSL 4.30.6 specification] -// (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). - -// a 2×2 single-precision floating-point matrix +// GLSL-style type aliases pub type mat2 = Mat2; -// a 2×2 double-precision floating-point matrix pub type dmat2 = Mat2; // Rust-style type aliases @@ -600,311 +388,42 @@ pub type Mat2f = Mat2; pub type Mat2f32 = Mat2; pub type Mat2f64 = Mat2; -/// A 3 x 3 column major matrix -/// -/// # Type parameters -/// -/// - `T`: The type of the elements of the matrix. Should be a floating point type. -/// -/// # Fields -/// -/// - `x`: the first column vector of the matrix -/// - `y`: the second column vector of the matrix -/// - `z`: the third column vector of the matrix #[deriving(Eq)] pub struct Mat3 { x: Vec3, y: Vec3, z: Vec3 } -impl BaseMat> for Mat3 { +impl Mat3 { #[inline(always)] - fn col<'a>(&'a self, i: uint) -> &'a Vec3 { - unsafe { &'a transmute::<&'a Mat3, &'a [Vec3,..3]>(self)[i] } + pub fn col<'a>(&'a self, i: uint) -> &'a Vec3 { + &'a self.as_slice()[i] } #[inline(always)] - fn row(&self, i: uint) -> Vec3 { - BaseVec3::new(*self.elem(0, i), - *self.elem(1, i), - *self.elem(2, i)) + pub fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec3 { + &'a mut self.as_mut_slice()[i] } #[inline(always)] - fn elem<'a>(&'a self, i: uint, j: uint) -> &'a T { + pub fn as_slice<'a>(&'a self) -> &'a [Vec3,..3] { + unsafe { transmute(self) } + } + + #[inline(always)] + pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Vec3,..3] { + unsafe { transmute(self) } + } + + #[inline(always)] + pub fn elem<'a>(&'a self, i: uint, j: uint) -> &'a T { self.col(i).index(j) } - /// Construct a 3 x 3 diagonal matrix with the major diagonal set to `value` - /// - /// # Arguments - /// - /// - `value`: the value to set the major diagonal to - /// - /// ~~~ - /// c0 c1 c2 - /// +-----+-----+-----+ - /// r0 | val | 0 | 0 | - /// +-----+-----+-----+ - /// r1 | 0 | val | 0 | - /// +-----+-----+-----+ - /// r2 | 0 | 0 | val | - /// +-----+-----+-----+ - /// ~~~ #[inline(always)] - fn from_value(value: T) -> Mat3 { - BaseMat3::new(value, Zero::zero(), Zero::zero(), - Zero::zero(), value, Zero::zero(), - Zero::zero(), Zero::zero(), value) - } - - /// Returns the multiplicative identity matrix - /// ~~~ - /// c0 c1 c2 - /// +----+----+----+ - /// r0 | 1 | 0 | 0 | - /// +----+----+----+ - /// r1 | 0 | 1 | 0 | - /// +----+----+----+ - /// r2 | 0 | 0 | 1 | - /// +----+----+----+ - /// ~~~ - #[inline(always)] - fn identity() -> Mat3 { - BaseMat3::new(One::one::(), Zero::zero::(), Zero::zero::(), - Zero::zero::(), One::one::(), Zero::zero::(), - Zero::zero::(), Zero::zero::(), One::one::()) - } - - /// Returns the additive identity matrix - /// ~~~ - /// c0 c1 c2 - /// +----+----+----+ - /// r0 | 0 | 0 | 0 | - /// +----+----+----+ - /// r1 | 0 | 0 | 0 | - /// +----+----+----+ - /// r2 | 0 | 0 | 0 | - /// +----+----+----+ - /// ~~~ - #[inline(always)] - fn zero() -> Mat3 { - BaseMat3::new(Zero::zero::(), Zero::zero::(), Zero::zero::(), - Zero::zero::(), Zero::zero::(), Zero::zero::(), - Zero::zero::(), Zero::zero::(), Zero::zero::()) - } - - #[inline(always)] - fn mul_t(&self, value: T) -> Mat3 { - BaseMat3::from_cols(self.col(0).mul_t(value), - self.col(1).mul_t(value), - self.col(2).mul_t(value)) - } - - #[inline(always)] - fn mul_v(&self, vec: &Vec3) -> Vec3 { - BaseVec3::new(self.row(0).dot(vec), - self.row(1).dot(vec), - self.row(2).dot(vec)) - } - - #[inline(always)] - fn add_m(&self, other: &Mat3) -> Mat3 { - BaseMat3::from_cols(self.col(0).add_v(other.col(0)), - self.col(1).add_v(other.col(1)), - self.col(2).add_v(other.col(2))) - } - - #[inline(always)] - fn sub_m(&self, other: &Mat3) -> Mat3 { - BaseMat3::from_cols(self.col(0).sub_v(other.col(0)), - self.col(1).sub_v(other.col(1)), - self.col(2).sub_v(other.col(2))) - } - - #[inline(always)] - fn mul_m(&self, other: &Mat3) -> Mat3 { - BaseMat3::new(self.row(0).dot(other.col(0)), - self.row(1).dot(other.col(0)), - self.row(2).dot(other.col(0)), - - self.row(0).dot(other.col(1)), - self.row(1).dot(other.col(1)), - self.row(2).dot(other.col(1)), - - self.row(0).dot(other.col(2)), - self.row(1).dot(other.col(2)), - self.row(2).dot(other.col(2))) - } - - fn dot(&self, other: &Mat3) -> T { - other.transpose().mul_m(self).trace() - } - - fn determinant(&self) -> T { - self.col(0).dot(&self.col(1).cross(self.col(2))) - } - - fn trace(&self) -> T { - *self.elem(0, 0) + - *self.elem(1, 1) + - *self.elem(2, 2) - } - - fn inverse(&self) -> Option> { - let d = self.determinant(); - if d.approx_eq(&Zero::zero()) { - None - } else { - let m: Mat3 = BaseMat3::from_cols(self.col(1).cross(self.col(2)).div_t(d), - self.col(2).cross(self.col(0)).div_t(d), - self.col(0).cross(self.col(1)).div_t(d)); - Some(m.transpose()) - } - } - - #[inline(always)] - fn transpose(&self) -> Mat3 { - BaseMat3::new(*self.elem(0, 0), *self.elem(1, 0), *self.elem(2, 0), - *self.elem(0, 1), *self.elem(1, 1), *self.elem(2, 1), - *self.elem(0, 2), *self.elem(1, 2), *self.elem(2, 2)) - } - - #[inline(always)] - fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec3 { - unsafe { &'a mut transmute::<&'a mut Mat3, &'a mut [Vec3,..3]>(self)[i] } - } - - #[inline(always)] - fn elem_mut<'a>(&'a mut self, i: uint, j: uint) -> &'a mut T { + pub fn elem_mut<'a>(&'a mut self, i: uint, j: uint) -> &'a mut T { self.col_mut(i).index_mut(j) } - - #[inline(always)] - fn swap_cols(&mut self, a: uint, b: uint) { - let tmp = *self.col(a); - *self.col_mut(a) = *self.col(b); - *self.col_mut(b) = tmp; - } - - #[inline(always)] - fn swap_rows(&mut self, a: uint, b: uint) { - self.x.swap(a, b); - self.y.swap(a, b); - self.z.swap(a, b); - } - - #[inline(always)] - fn set(&mut self, other: &Mat3) { - (*self) = (*other); - } - - #[inline(always)] - fn to_identity(&mut self) { - (*self) = BaseMat::identity(); - } - - #[inline(always)] - fn to_zero(&mut self) { - (*self) = BaseMat::zero(); - } - - #[inline(always)] - fn mul_self_t(&mut self, value: T) { - self.col_mut(0).mul_self_t(value); - self.col_mut(1).mul_self_t(value); - self.col_mut(2).mul_self_t(value); - } - - #[inline(always)] - fn add_self_m(&mut self, other: &Mat3) { - self.col_mut(0).add_self_v(other.col(0)); - self.col_mut(1).add_self_v(other.col(1)); - self.col_mut(2).add_self_v(other.col(2)); - } - - #[inline(always)] - fn sub_self_m(&mut self, other: &Mat3) { - self.col_mut(0).sub_self_v(other.col(0)); - self.col_mut(1).sub_self_v(other.col(1)); - self.col_mut(2).sub_self_v(other.col(2)); - } - - #[inline(always)] - fn invert_self(&mut self) { - match self.inverse() { - Some(m) => (*self) = m, - None => fail!(~"Couldn't invert the matrix!") - } - } - - #[inline(always)] - fn transpose_self(&mut self) { - let tmp01 = *self.elem(0, 1); - let tmp02 = *self.elem(0, 2); - let tmp10 = *self.elem(1, 0); - let tmp12 = *self.elem(1, 2); - let tmp20 = *self.elem(2, 0); - let tmp21 = *self.elem(2, 1); - - *self.elem_mut(0, 1) = *self.elem(1, 0); - *self.elem_mut(0, 2) = *self.elem(2, 0); - *self.elem_mut(1, 0) = *self.elem(0, 1); - *self.elem_mut(1, 2) = *self.elem(2, 1); - *self.elem_mut(2, 0) = *self.elem(0, 2); - *self.elem_mut(2, 1) = *self.elem(1, 2); - - *self.elem_mut(1, 0) = tmp01; - *self.elem_mut(2, 0) = tmp02; - *self.elem_mut(0, 1) = tmp10; - *self.elem_mut(2, 1) = tmp12; - *self.elem_mut(0, 2) = tmp20; - *self.elem_mut(1, 2) = tmp21; - } - - #[inline(always)] - fn is_identity(&self) -> bool { - self.approx_eq(&BaseMat::identity()) - } - - #[inline(always)] - fn is_diagonal(&self) -> bool { - self.elem(0, 1).approx_eq(&Zero::zero()) && - self.elem(0, 2).approx_eq(&Zero::zero()) && - - self.elem(1, 0).approx_eq(&Zero::zero()) && - self.elem(1, 2).approx_eq(&Zero::zero()) && - - self.elem(2, 0).approx_eq(&Zero::zero()) && - self.elem(2, 1).approx_eq(&Zero::zero()) - } - - #[inline(always)] - fn is_rotated(&self) -> bool { - !self.approx_eq(&BaseMat::identity()) - } - - #[inline(always)] - fn is_symmetric(&self) -> bool { - self.elem(0, 1).approx_eq(self.elem(1, 0)) && - self.elem(0, 2).approx_eq(self.elem(2, 0)) && - - self.elem(1, 0).approx_eq(self.elem(0, 1)) && - self.elem(1, 2).approx_eq(self.elem(2, 1)) && - - self.elem(2, 0).approx_eq(self.elem(0, 2)) && - self.elem(2, 1).approx_eq(self.elem(1, 2)) - } - - #[inline(always)] - fn is_invertible(&self) -> bool { - !self.determinant().approx_eq(&Zero::zero()) - } - - #[inline(always)] - fn to_ptr(&self) -> *T { - unsafe { transmute(self) } - } } -impl BaseMat3> for Mat3 { +impl Mat3 { /// Construct a 3 x 3 matrix /// /// # Arguments @@ -924,12 +443,12 @@ impl BaseMat3> for Mat3 { /// +------+------+------+ /// ~~~ #[inline(always)] - fn new(c0r0:T, c0r1:T, c0r2:T, - c1r0:T, c1r1:T, c1r2:T, - c2r0:T, c2r1:T, c2r2:T) -> Mat3 { - BaseMat3::from_cols(BaseVec3::new::>(c0r0, c0r1, c0r2), - BaseVec3::new::>(c1r0, c1r1, c1r2), - BaseVec3::new::>(c2r0, c2r1, c2r2)) + pub fn new(c0r0:T, c0r1:T, c0r2:T, + c1r0:T, c1r1:T, c1r2:T, + c2r0:T, c2r1:T, c2r2:T) -> Mat3 { + Mat3::from_cols(Vec3::new(c0r0, c0r1, c0r2), + Vec3::new(c1r0, c1r1, c1r2), + Vec3::new(c2r0, c2r1, c2r2)) } /// Construct a 3 x 3 matrix from column vectors @@ -951,96 +470,211 @@ impl BaseMat3> for Mat3 { /// +------+------+------+ /// ~~~ #[inline(always)] - fn from_cols(c0: Vec3, c1: Vec3, c2: Vec3) -> Mat3 { + pub fn from_cols(c0: Vec3, + c1: Vec3, + c2: Vec3) -> Mat3 { Mat3 { x: c0, y: c1, z: c2 } } - /// Construct a matrix from an angular rotation around the `x` axis #[inline(always)] - fn from_angle_x(radians: T) -> Mat3 { - // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations - let cos_theta = radians.cos(); - let sin_theta = radians.sin(); - - BaseMat3::new( One::one(), Zero::zero(), Zero::zero(), - Zero::zero(), cos_theta, sin_theta, - Zero::zero(), -sin_theta, cos_theta) + pub fn row(&self, i: uint) -> Vec3 { + Vec3::new(*self.elem(0, i), + *self.elem(1, i), + *self.elem(2, i)) } - /// Construct a matrix from an angular rotation around the `y` axis #[inline(always)] - fn from_angle_y(radians: T) -> Mat3 { - // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations - let cos_theta = radians.cos(); - let sin_theta = radians.sin(); - - BaseMat3::new( cos_theta, Zero::zero(), -sin_theta, - Zero::zero(), One::one(), Zero::zero(), - sin_theta, Zero::zero(), cos_theta) + pub fn swap_cols(&mut self, a: uint, b: uint) { + let tmp = *self.col(a); + *self.col_mut(a) = *self.col(b); + *self.col_mut(b) = tmp; } - /// Construct a matrix from an angular rotation around the `z` axis #[inline(always)] - fn from_angle_z(radians: T) -> Mat3 { - // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations - let cos_theta = radians.cos(); - let sin_theta = radians.sin(); - - BaseMat3::new( cos_theta, sin_theta, Zero::zero(), - -sin_theta, cos_theta, Zero::zero(), - Zero::zero(), Zero::zero(), One::one()) + pub fn swap_rows(&mut self, a: uint, b: uint) { + self.x.swap(a, b); + self.y.swap(a, b); + self.z.swap(a, b); } - /// Construct a matrix from Euler angles + #[inline(always)] + pub fn transpose(&self) -> Mat3 { + Mat3::new(*self.elem(0, 0), *self.elem(1, 0), *self.elem(2, 0), + *self.elem(0, 1), *self.elem(1, 1), *self.elem(2, 1), + *self.elem(0, 2), *self.elem(1, 2), *self.elem(2, 2)) + } + + #[inline(always)] + pub fn transpose_self(&mut self) { + let tmp01 = *self.elem(0, 1); + let tmp02 = *self.elem(0, 2); + let tmp10 = *self.elem(1, 0); + let tmp12 = *self.elem(1, 2); + let tmp20 = *self.elem(2, 0); + let tmp21 = *self.elem(2, 1); + + *self.elem_mut(0, 1) = *self.elem(1, 0); + *self.elem_mut(0, 2) = *self.elem(2, 0); + *self.elem_mut(1, 0) = *self.elem(0, 1); + *self.elem_mut(1, 2) = *self.elem(2, 1); + *self.elem_mut(2, 0) = *self.elem(0, 2); + *self.elem_mut(2, 1) = *self.elem(1, 2); + + *self.elem_mut(1, 0) = tmp01; + *self.elem_mut(2, 0) = tmp02; + *self.elem_mut(0, 1) = tmp10; + *self.elem_mut(2, 1) = tmp12; + *self.elem_mut(0, 2) = tmp20; + *self.elem_mut(1, 2) = tmp21; + } +} + +impl Mat3 { + /// Construct a 3 x 3 diagonal matrix with the major diagonal set to `value` /// /// # Arguments /// - /// - `theta_x`: the angular rotation around the `x` axis (pitch) - /// - `theta_y`: the angular rotation around the `y` axis (yaw) - /// - `theta_z`: the angular rotation around the `z` axis (roll) + /// - `value`: the value to set the major diagonal to + /// + /// ~~~ + /// c0 c1 c2 + /// +-----+-----+-----+ + /// r0 | val | 0 | 0 | + /// +-----+-----+-----+ + /// r1 | 0 | val | 0 | + /// +-----+-----+-----+ + /// r2 | 0 | 0 | val | + /// +-----+-----+-----+ + /// ~~~ #[inline(always)] - fn from_angle_xyz(radians_x: T, radians_y: T, radians_z: T) -> Mat3 { - // http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations - let cx = radians_x.cos(); - let sx = radians_x.sin(); - let cy = radians_y.cos(); - let sy = radians_y.sin(); - let cz = radians_z.cos(); - let sz = radians_z.sin(); - - BaseMat3::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) + pub fn from_value(value: T) -> Mat3 { + Mat3::new(value, Zero::zero(), Zero::zero(), + Zero::zero(), value, Zero::zero(), + Zero::zero(), Zero::zero(), value) } - /// Construct a matrix from an axis and an angular rotation + /// Returns the multiplicative identity matrix + /// ~~~ + /// c0 c1 c2 + /// +----+----+----+ + /// r0 | 1 | 0 | 0 | + /// +----+----+----+ + /// r1 | 0 | 1 | 0 | + /// +----+----+----+ + /// r2 | 0 | 0 | 1 | + /// +----+----+----+ + /// ~~~ #[inline(always)] - fn from_angle_axis(radians: T, axis: &Vec3) -> Mat3 { - let c = radians.cos(); - let s = radians.sin(); - let _1_c = One::one::() - c; + pub fn identity() -> Mat3 { + Mat3::new(One::one::(), Zero::zero::(), Zero::zero::(), + Zero::zero::(), One::one::(), Zero::zero::(), + Zero::zero::(), Zero::zero::(), One::one::()) + } - let x = axis.x; - let y = axis.y; - let z = axis.z; - - BaseMat3::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) + /// Returns the additive identity matrix + /// ~~~ + /// c0 c1 c2 + /// +----+----+----+ + /// r0 | 0 | 0 | 0 | + /// +----+----+----+ + /// r1 | 0 | 0 | 0 | + /// +----+----+----+ + /// r2 | 0 | 0 | 0 | + /// +----+----+----+ + /// ~~~ + #[inline(always)] + pub fn zero() -> Mat3 { + Mat3::new(Zero::zero::(), Zero::zero::(), Zero::zero::(), + Zero::zero::(), Zero::zero::(), Zero::zero::(), + Zero::zero::(), Zero::zero::(), Zero::zero::()) } #[inline(always)] - fn from_axes(x: Vec3, y: Vec3, z: Vec3) -> Mat3 { - BaseMat3::from_cols(x, y, z) + pub fn mul_t(&self, value: T) -> Mat3 { + Mat3::from_cols(self.col(0).mul_t(value), + self.col(1).mul_t(value), + self.col(2).mul_t(value)) } #[inline(always)] - fn look_at(dir: &Vec3, up: &Vec3) -> Mat3 { - let dir_ = dir.normalize(); - let side = dir_.cross(&up.normalize()); - let up_ = side.cross(&dir_).normalize(); + pub fn mul_v(&self, vec: &Vec3) -> Vec3 { + Vec3::new(self.row(0).dot(vec), + self.row(1).dot(vec), + self.row(2).dot(vec)) + } - BaseMat3::from_axes(up_, side, dir_) + #[inline(always)] + pub fn add_m(&self, other: &Mat3) -> Mat3 { + Mat3::from_cols(self.col(0).add_v(other.col(0)), + self.col(1).add_v(other.col(1)), + self.col(2).add_v(other.col(2))) + } + + #[inline(always)] + pub fn sub_m(&self, other: &Mat3) -> Mat3 { + Mat3::from_cols(self.col(0).sub_v(other.col(0)), + self.col(1).sub_v(other.col(1)), + self.col(2).sub_v(other.col(2))) + } + + #[inline(always)] + pub fn mul_m(&self, other: &Mat3) -> Mat3 { + Mat3::new(self.row(0).dot(other.col(0)), + self.row(1).dot(other.col(0)), + self.row(2).dot(other.col(0)), + + self.row(0).dot(other.col(1)), + self.row(1).dot(other.col(1)), + self.row(2).dot(other.col(1)), + + self.row(0).dot(other.col(2)), + self.row(1).dot(other.col(2)), + self.row(2).dot(other.col(2))) + } + + #[inline(always)] + pub fn mul_self_t(&mut self, value: T) { + self.col_mut(0).mul_self_t(value); + self.col_mut(1).mul_self_t(value); + self.col_mut(2).mul_self_t(value); + } + + #[inline(always)] + pub fn add_self_m(&mut self, other: &Mat3) { + self.col_mut(0).add_self_v(other.col(0)); + self.col_mut(1).add_self_v(other.col(1)); + self.col_mut(2).add_self_v(other.col(2)); + } + + #[inline(always)] + pub fn sub_self_m(&mut self, other: &Mat3) { + self.col_mut(0).sub_self_v(other.col(0)); + self.col_mut(1).sub_self_v(other.col(1)); + self.col_mut(2).sub_self_v(other.col(2)); + } + + pub fn dot(&self, other: &Mat3) -> T { + other.transpose().mul_m(self).trace() + } + + pub fn determinant(&self) -> T { + self.col(0).dot(&self.col(1).cross(self.col(2))) + } + + pub fn trace(&self) -> T { + *self.elem(0, 0) + + *self.elem(1, 1) + + *self.elem(2, 2) + } + + #[inline(always)] + pub fn to_identity(&mut self) { + *self = Mat3::identity(); + } + + #[inline(always)] + pub fn to_zero(&mut self) { + *self = Mat3::zero(); } /// Returns the the matrix with an extra row and column added @@ -1057,29 +691,126 @@ impl BaseMat3> for Mat3 { /// +----+----+----+----+ /// ~~~ #[inline(always)] - fn to_mat4(&self) -> Mat4 { - BaseMat4::new(*self.elem(0, 0), *self.elem(0, 1), *self.elem(0, 2), Zero::zero(), - *self.elem(1, 0), *self.elem(1, 1), *self.elem(1, 2), Zero::zero(), - *self.elem(2, 0), *self.elem(2, 1), *self.elem(2, 2), Zero::zero(), - Zero::zero(), Zero::zero(), Zero::zero(), One::one()) + pub fn to_mat4(&self) -> Mat4 { + Mat4::new(*self.elem(0, 0), *self.elem(0, 1), *self.elem(0, 2), Zero::zero(), + *self.elem(1, 0), *self.elem(1, 1), *self.elem(1, 2), Zero::zero(), + *self.elem(2, 0), *self.elem(2, 1), *self.elem(2, 2), Zero::zero(), + Zero::zero(), Zero::zero(), Zero::zero(), One::one()) + } +} + +impl Neg> for Mat3 { + #[inline(always)] + pub fn neg(&self) -> Mat3 { + Mat3::from_cols(-self.col(0), -self.col(1), -self.col(2)) + } +} + +impl Mat3 { + /// Construct a matrix from an angular rotation around the `x` axis + #[inline(always)] + pub fn from_angle_x(radians: T) -> Mat3 { + // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations + let cos_theta = radians.cos(); + let sin_theta = radians.sin(); + + Mat3::new(One::one(), Zero::zero(), Zero::zero(), + Zero::zero(), cos_theta, sin_theta, + Zero::zero(), -sin_theta, cos_theta) + } + + /// Construct a matrix from an angular rotation around the `y` axis + #[inline(always)] + pub fn from_angle_y(radians: T) -> Mat3 { + // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations + let cos_theta = radians.cos(); + let sin_theta = radians.sin(); + + Mat3::new(cos_theta, Zero::zero(), -sin_theta, + Zero::zero(), One::one(), Zero::zero(), + sin_theta, Zero::zero(), cos_theta) + } + + /// Construct a matrix from an angular rotation around the `z` axis + #[inline(always)] + pub fn from_angle_z(radians: T) -> Mat3 { + // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations + let cos_theta = radians.cos(); + let sin_theta = radians.sin(); + + Mat3::new(cos_theta, sin_theta, Zero::zero(), + -sin_theta, cos_theta, Zero::zero(), + Zero::zero(), Zero::zero(), One::one()) + } + + /// Construct a matrix from Euler angles + /// + /// # Arguments + /// + /// - `theta_x`: the angular rotation around the `x` axis (pitch) + /// - `theta_y`: the angular rotation around the `y` axis (yaw) + /// - `theta_z`: the angular rotation around the `z` axis (roll) + #[inline(always)] + pub fn from_angle_xyz(radians_x: T, radians_y: T, radians_z: T) -> Mat3 { + // http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations + let cx = radians_x.cos(); + let sx = radians_x.sin(); + let cy = radians_y.cos(); + let sy = radians_y.sin(); + let cz = radians_z.cos(); + let sz = radians_z.sin(); + + 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) + } + + /// Construct a matrix from an axis and an angular rotation + #[inline(always)] + pub fn from_angle_axis(radians: T, axis: &Vec3) -> Mat3 { + let c = radians.cos(); + let s = radians.sin(); + let _1_c = One::one::() - 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)] + pub fn from_axes(x: Vec3, y: Vec3, z: Vec3) -> Mat3 { + Mat3::from_cols(x, y, z) + } + + #[inline(always)] + pub fn look_at(dir: &Vec3, up: &Vec3) -> Mat3 { + let dir_ = dir.normalize(); + let side = dir_.cross(&up.normalize()); + let up_ = side.cross(&dir_).normalize(); + + Mat3::from_axes(up_, side, dir_) } /// Convert the matrix to a quaternion #[inline(always)] - fn to_quat(&self) -> Quat { + pub 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 w; let x; let y; let z; let trace = self.trace(); - let _1: T = cast(1.0); - let half: T = cast(0.5); + // FIXME: We don't have any numeric conversions in std yet :P + let half = One::one::() / (One::one::() + One::one::()); cond! ( (trace >= Zero::zero()) { - s = (_1 + trace).sqrt(); + s = (One::one::() + trace).sqrt(); w = half * s; s = half / s; x = (*self.elem(1, 2) - *self.elem(2, 1)) * s; @@ -1112,40 +843,88 @@ impl BaseMat3> for Mat3 { z = (*self.elem(0, 1) - *self.elem(1, 0)) * s; } ) - Quat::new(w, x, y, z) } } -impl Neg> for Mat3 { +impl> Mat3 { + pub fn inverse(&self) -> Option> { + let d = self.determinant(); + if d.approx_eq(&Zero::zero()) { + None + } else { + Some(Mat3::from_cols(self.col(1).cross(self.col(2)).div_t(d), + self.col(2).cross(self.col(0)).div_t(d), + self.col(0).cross(self.col(1)).div_t(d)).transpose()) + } + } + #[inline(always)] - fn neg(&self) -> Mat3 { - BaseMat3::from_cols(-self.col(0), -self.col(1), -self.col(2)) + pub fn invert_self(&mut self) { + *self = self.inverse().expect("Couldn't invert the matrix!"); + } + + #[inline(always)] + pub fn is_identity(&self) -> bool { + self.approx_eq(&Mat3::identity()) + } + + #[inline(always)] + pub fn is_diagonal(&self) -> bool { + self.elem(0, 1).approx_eq(&Zero::zero()) && + self.elem(0, 2).approx_eq(&Zero::zero()) && + + self.elem(1, 0).approx_eq(&Zero::zero()) && + self.elem(1, 2).approx_eq(&Zero::zero()) && + + self.elem(2, 0).approx_eq(&Zero::zero()) && + self.elem(2, 1).approx_eq(&Zero::zero()) + } + + #[inline(always)] + pub fn is_rotated(&self) -> bool { + !self.approx_eq(&Mat3::identity()) + } + + #[inline(always)] + pub fn is_symmetric(&self) -> bool { + self.elem(0, 1).approx_eq(self.elem(1, 0)) && + self.elem(0, 2).approx_eq(self.elem(2, 0)) && + + self.elem(1, 0).approx_eq(self.elem(0, 1)) && + self.elem(1, 2).approx_eq(self.elem(2, 1)) && + + self.elem(2, 0).approx_eq(self.elem(0, 2)) && + self.elem(2, 1).approx_eq(self.elem(1, 2)) + } + + #[inline(always)] + pub fn is_invertible(&self) -> bool { + !self.determinant().approx_eq(&Zero::zero()) } } -impl ApproxEq for Mat3 { +impl> ApproxEq for Mat3 { #[inline(always)] - fn approx_epsilon() -> T { + pub fn approx_epsilon() -> T { ApproxEq::approx_epsilon::() } #[inline(always)] - fn approx_eq(&self, other: &Mat3) -> bool { + pub fn approx_eq(&self, other: &Mat3) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } #[inline(always)] - fn approx_eq_eps(&self, other: &Mat3, epsilon: &T) -> bool { + pub fn approx_eq_eps(&self, other: &Mat3, epsilon: &T) -> bool { self.col(0).approx_eq_eps(other.col(0), epsilon) && self.col(1).approx_eq_eps(other.col(1), epsilon) && self.col(2).approx_eq_eps(other.col(2), epsilon) } } -// a 3×3 single-precision floating-point matrix +// GLSL-style type aliases pub type mat3 = Mat3; -// a 3×3 double-precision floating-point matrix pub type dmat3 = Mat3; // Rust-style type aliases @@ -1168,253 +947,117 @@ pub type Mat3f64 = Mat3; #[deriving(Eq)] pub struct Mat4 { x: Vec4, y: Vec4, z: Vec4, w: Vec4 } -impl BaseMat> for Mat4 { +impl Mat4 { #[inline(always)] - fn col<'a>(&'a self, i: uint) -> &'a Vec4 { - unsafe { &'a transmute::<&'a Mat4, &'a [Vec4,..4]>(self)[i] } + pub fn col<'a>(&'a self, i: uint) -> &'a Vec4 { + &'a self.as_slice()[i] } #[inline(always)] - fn row(&self, i: uint) -> Vec4 { - BaseVec4::new(*self.elem(0, i), - *self.elem(1, i), - *self.elem(2, i), - *self.elem(3, i)) + pub fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec4 { + &'a mut self.as_mut_slice()[i] } #[inline(always)] - fn elem<'a>(&'a self, i: uint, j: uint) -> &'a T { + pub fn as_slice<'a>(&'a self) -> &'a [Vec4,..4] { + unsafe { transmute(self) } + } + + #[inline(always)] + pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Vec4,..4] { + unsafe { transmute(self) } + } + + #[inline(always)] + pub fn elem<'a>(&'a self, i: uint, j: uint) -> &'a T { self.col(i).index(j) } - /// Construct a 4 x 4 diagonal matrix with the major diagonal set to `value` + #[inline(always)] + pub fn elem_mut<'a>(&'a mut self, i: uint, j: uint) -> &'a mut T { + self.col_mut(i).index_mut(j) + } +} + +impl Mat4 { + /// Construct a 4 x 4 matrix /// /// # Arguments /// - /// - `value`: the value to set the major diagonal to + /// - `c0r0`, `c0r1`, `c0r2`, `c0r3`: the first column of the matrix + /// - `c1r0`, `c1r1`, `c1r2`, `c1r3`: the second column of the matrix + /// - `c2r0`, `c2r1`, `c2r2`, `c2r3`: the third column of the matrix + /// - `c3r0`, `c3r1`, `c3r2`, `c3r3`: the fourth column of the matrix /// /// ~~~ - /// c0 c1 c2 c3 - /// +-----+-----+-----+-----+ - /// r0 | val | 0 | 0 | 0 | - /// +-----+-----+-----+-----+ - /// r1 | 0 | val | 0 | 0 | - /// +-----+-----+-----+-----+ - /// r2 | 0 | 0 | val | 0 | - /// +-----+-----+-----+-----+ - /// r3 | 0 | 0 | 0 | val | - /// +-----+-----+-----+-----+ + /// c0 c1 c2 c3 + /// +------+------+------+------+ + /// r0 | c0r0 | c1r0 | c2r0 | c3r0 | + /// +------+------+------+------+ + /// r1 | c0r1 | c1r1 | c2r1 | c3r1 | + /// +------+------+------+------+ + /// r2 | c0r2 | c1r2 | c2r2 | c3r2 | + /// +------+------+------+------+ + /// r3 | c0r3 | c1r3 | c2r3 | c3r3 | + /// +------+------+------+------+ /// ~~~ #[inline(always)] - fn from_value(value: T) -> Mat4 { - BaseMat4::new(value, Zero::zero(), Zero::zero(), Zero::zero(), - Zero::zero(), value, Zero::zero(), Zero::zero(), - Zero::zero(), Zero::zero(), value, Zero::zero(), - Zero::zero(), Zero::zero(), Zero::zero(), value) + pub fn new(c0r0: T, c0r1: T, c0r2: T, c0r3: T, + c1r0: T, c1r1: T, c1r2: T, c1r3: T, + c2r0: T, c2r1: T, c2r2: T, c2r3: T, + c3r0: T, c3r1: T, c3r2: T, c3r3: T) -> Mat4 { + Mat4::from_cols(Vec4::new(c0r0, c0r1, c0r2, c0r3), + Vec4::new(c1r0, c1r1, c1r2, c1r3), + Vec4::new(c2r0, c2r1, c2r2, c2r3), + Vec4::new(c3r0, c3r1, c3r2, c3r3)) } - /// Returns the multiplicative identity matrix + /// Construct a 4 x 4 matrix from column vectors + /// + /// # Arguments + /// + /// - `c0`: the first column vector of the matrix + /// - `c1`: the second column vector of the matrix + /// - `c2`: the third column vector of the matrix + /// - `c3`: the fourth column vector of the matrix + /// /// ~~~ - /// c0 c1 c2 c3 - /// +----+----+----+----+ - /// r0 | 1 | 0 | 0 | 0 | - /// +----+----+----+----+ - /// r1 | 0 | 1 | 0 | 0 | - /// +----+----+----+----+ - /// r2 | 0 | 0 | 1 | 0 | - /// +----+----+----+----+ - /// r3 | 0 | 0 | 0 | 1 | - /// +----+----+----+----+ + /// c0 c1 c2 c3 + /// +------+------+------+------+ + /// r0 | c0.x | c1.x | c2.x | c3.x | + /// +------+------+------+------+ + /// r1 | c0.y | c1.y | c2.y | c3.y | + /// +------+------+------+------+ + /// r2 | c0.z | c1.z | c2.z | c3.z | + /// +------+------+------+------+ + /// r3 | c0.w | c1.w | c2.w | c3.w | + /// +------+------+------+------+ /// ~~~ #[inline(always)] - fn identity() -> Mat4 { - BaseMat4::new(One::one::(), Zero::zero::(), Zero::zero::(), Zero::zero::(), - Zero::zero::(), One::one::(), Zero::zero::(), Zero::zero::(), - Zero::zero::(), Zero::zero::(), One::one::(), Zero::zero::(), - Zero::zero::(), Zero::zero::(), Zero::zero::(), One::one::()) - } - - /// Returns the additive identity matrix - /// ~~~ - /// c0 c1 c2 c3 - /// +----+----+----+----+ - /// r0 | 0 | 0 | 0 | 0 | - /// +----+----+----+----+ - /// r1 | 0 | 0 | 0 | 0 | - /// +----+----+----+----+ - /// r2 | 0 | 0 | 0 | 0 | - /// +----+----+----+----+ - /// r3 | 0 | 0 | 0 | 0 | - /// +----+----+----+----+ - /// ~~~ - #[inline(always)] - fn zero() -> Mat4 { - BaseMat4::new(Zero::zero::(), Zero::zero::(), Zero::zero::(), Zero::zero::(), - Zero::zero::(), Zero::zero::(), Zero::zero::(), Zero::zero::(), - Zero::zero::(), Zero::zero::(), Zero::zero::(), Zero::zero::(), - Zero::zero::(), Zero::zero::(), Zero::zero::(), Zero::zero::()) + pub fn from_cols(c0: Vec4, + c1: Vec4, + c2: Vec4, + c3: Vec4) -> Mat4 { + Mat4 { x: c0, y: c1, z: c2, w: c3 } } #[inline(always)] - fn mul_t(&self, value: T) -> Mat4 { - BaseMat4::from_cols(self.col(0).mul_t(value), - self.col(1).mul_t(value), - self.col(2).mul_t(value), - self.col(3).mul_t(value)) + pub fn row(&self, i: uint) -> Vec4 { + Vec4::new(*self.elem(0, i), + *self.elem(1, i), + *self.elem(2, i), + *self.elem(3, i)) } #[inline(always)] - fn mul_v(&self, vec: &Vec4) -> Vec4 { - BaseVec4::new(self.row(0).dot(vec), - self.row(1).dot(vec), - self.row(2).dot(vec), - self.row(3).dot(vec)) - } - - #[inline(always)] - fn add_m(&self, other: &Mat4) -> Mat4 { - BaseMat4::from_cols(self.col(0).add_v(other.col(0)), - self.col(1).add_v(other.col(1)), - self.col(2).add_v(other.col(2)), - self.col(3).add_v(other.col(3))) - } - - #[inline(always)] - fn sub_m(&self, other: &Mat4) -> Mat4 { - BaseMat4::from_cols(self.col(0).sub_v(other.col(0)), - self.col(1).sub_v(other.col(1)), - self.col(2).sub_v(other.col(2)), - self.col(3).sub_v(other.col(3))) - } - - #[inline(always)] - fn mul_m(&self, other: &Mat4) -> Mat4 { - BaseMat4::new(self.row(0).dot(other.col(0)), - self.row(1).dot(other.col(0)), - self.row(2).dot(other.col(0)), - self.row(3).dot(other.col(0)), - - self.row(0).dot(other.col(1)), - self.row(1).dot(other.col(1)), - self.row(2).dot(other.col(1)), - self.row(3).dot(other.col(1)), - - self.row(0).dot(other.col(2)), - self.row(1).dot(other.col(2)), - self.row(2).dot(other.col(2)), - self.row(3).dot(other.col(2)), - - self.row(0).dot(other.col(3)), - self.row(1).dot(other.col(3)), - self.row(2).dot(other.col(3)), - self.row(3).dot(other.col(3))) - - } - - fn dot(&self, other: &Mat4) -> T { - other.transpose().mul_m(self).trace() - } - - fn determinant(&self) -> T { - let m0: Mat3 = BaseMat3::new(*self.elem(1, 1), *self.elem(2, 1), *self.elem(3, 1), - *self.elem(1, 2), *self.elem(2, 2), *self.elem(3, 2), - *self.elem(1, 3), *self.elem(2, 3), *self.elem(3, 3)); - let m1: Mat3 = BaseMat3::new(*self.elem(0, 1), *self.elem(2, 1), *self.elem(3, 1), - *self.elem(0, 2), *self.elem(2, 2), *self.elem(3, 2), - *self.elem(0, 3), *self.elem(2, 3), *self.elem(3, 3)); - let m2: Mat3 = BaseMat3::new(*self.elem(0, 1), *self.elem(1, 1), *self.elem(3, 1), - *self.elem(0, 2), *self.elem(1, 2), *self.elem(3, 2), - *self.elem(0, 3), *self.elem(1, 3), *self.elem(3, 3)); - let m3: Mat3 = BaseMat3::new(*self.elem(0, 1), *self.elem(1, 1), *self.elem(2, 1), - *self.elem(0, 2), *self.elem(1, 2), *self.elem(2, 2), - *self.elem(0, 3), *self.elem(1, 3), *self.elem(2, 3)); - - self.elem(0, 0) * m0.determinant() - - self.elem(1, 0) * m1.determinant() + - self.elem(2, 0) * m2.determinant() - - self.elem(3, 0) * m3.determinant() - } - - fn trace(&self) -> T { - *self.elem(0, 0) + - *self.elem(1, 1) + - *self.elem(2, 2) + - *self.elem(3, 3) - } - - fn inverse(&self) -> Option> { - let d = self.determinant(); - if d.approx_eq(&Zero::zero()) { - None - } else { - // Gauss Jordan Elimination with partial pivoting - // So take this matrix, A, augmented with the identity - // and essentially reduce [A|I] - - let mut A = *self; - let mut I: Mat4 = BaseMat::identity(); - - for uint::range(0, 4) |j| { - // Find largest element in col j - let mut i1 = j; - for uint::range(j + 1, 4) |i| { - if A.elem(j, i).abs() > A.elem(j, i1).abs() { - i1 = i; - } - } - - // Swap columns i1 and j in A and I to - // put pivot on diagonal - A.swap_cols(i1, j); - I.swap_cols(i1, j); - - // Scale col j to have a unit diagonal - let ajj = *A.elem(j, j); - I.col_mut(j).div_self_t(ajj); - A.col_mut(j).div_self_t(ajj); - - // Eliminate off-diagonal elems in col j of A, - // doing identical ops to I - for uint::range(0, 4) |i| { - if i != j { - let ij_mul_aij = I.col(j).mul_t(*A.elem(i, j)); - let aj_mul_aij = A.col(j).mul_t(*A.elem(i, j)); - I.col_mut(i).sub_self_v(&ij_mul_aij); - A.col_mut(i).sub_self_v(&aj_mul_aij); - } - } - } - Some(I) - } - } - - #[inline(always)] - fn transpose(&self) -> Mat4 { - BaseMat4::new(*self.elem(0, 0), *self.elem(1, 0), *self.elem(2, 0), *self.elem(3, 0), - *self.elem(0, 1), *self.elem(1, 1), *self.elem(2, 1), *self.elem(3, 1), - *self.elem(0, 2), *self.elem(1, 2), *self.elem(2, 2), *self.elem(3, 2), - *self.elem(0, 3), *self.elem(1, 3), *self.elem(2, 3), *self.elem(3, 3)) - } - - #[inline(always)] - fn col_mut<'a>(&'a mut self, i: uint) -> &'a mut Vec4 { - unsafe { &'a mut transmute::<&'a mut Mat4, &'a mut [Vec4,..4]>(self)[i] } - } - - #[inline(always)] - fn elem_mut<'a>(&'a mut self, i: uint, j: uint) -> &'a mut T { - self.col_mut(i).index_mut(j) - } - - #[inline(always)] - fn swap_cols(&mut self, a: uint, b: uint) { + pub fn swap_cols(&mut self, a: uint, b: uint) { let tmp = *self.col(a); *self.col_mut(a) = *self.col(b); *self.col_mut(b) = tmp; } #[inline(always)] - fn swap_rows(&mut self, a: uint, b: uint) { + pub fn swap_rows(&mut self, a: uint, b: uint) { self.x.swap(a, b); self.y.swap(a, b); self.z.swap(a, b); @@ -1422,54 +1065,15 @@ impl BaseMat> for Mat4 { } #[inline(always)] - fn set(&mut self, other: &Mat4) { - (*self) = (*other); + pub fn transpose(&self) -> Mat4 { + Mat4::new(*self.elem(0, 0), *self.elem(1, 0), *self.elem(2, 0), *self.elem(3, 0), + *self.elem(0, 1), *self.elem(1, 1), *self.elem(2, 1), *self.elem(3, 1), + *self.elem(0, 2), *self.elem(1, 2), *self.elem(2, 2), *self.elem(3, 2), + *self.elem(0, 3), *self.elem(1, 3), *self.elem(2, 3), *self.elem(3, 3)) } #[inline(always)] - fn to_identity(&mut self) { - (*self) = BaseMat::identity(); - } - - #[inline(always)] - fn to_zero(&mut self) { - (*self) = BaseMat::zero(); - } - - #[inline(always)] - fn mul_self_t(&mut self, value: T) { - self.col_mut(0).mul_self_t(value); - self.col_mut(1).mul_self_t(value); - self.col_mut(2).mul_self_t(value); - self.col_mut(3).mul_self_t(value); - } - - #[inline(always)] - fn add_self_m(&mut self, other: &Mat4) { - self.col_mut(0).add_self_v(other.col(0)); - self.col_mut(1).add_self_v(other.col(1)); - self.col_mut(2).add_self_v(other.col(2)); - self.col_mut(3).add_self_v(other.col(3)); - } - - #[inline(always)] - fn sub_self_m(&mut self, other: &Mat4) { - self.col_mut(0).sub_self_v(other.col(0)); - self.col_mut(1).sub_self_v(other.col(1)); - self.col_mut(2).sub_self_v(other.col(2)); - self.col_mut(3).sub_self_v(other.col(3)); - } - - #[inline(always)] - fn invert_self(&mut self) { - match self.inverse() { - Some(m) => (*self) = m, - None => fail!(~"Couldn't invert the matrix!") - } - } - - #[inline(always)] - fn transpose_self(&mut self) { + pub fn transpose_self(&mut self) { let tmp01 = *self.elem(0, 1); let tmp02 = *self.elem(0, 2); let tmp03 = *self.elem(0, 3); @@ -1509,14 +1113,264 @@ impl BaseMat> for Mat4 { *self.elem_mut(1, 3) = tmp31; *self.elem_mut(2, 3) = tmp32; } +} +impl Mat4 { + /// Construct a 4 x 4 diagonal matrix with the major diagonal set to `value` + /// + /// # Arguments + /// + /// - `value`: the value to set the major diagonal to + /// + /// ~~~ + /// c0 c1 c2 c3 + /// +-----+-----+-----+-----+ + /// r0 | val | 0 | 0 | 0 | + /// +-----+-----+-----+-----+ + /// r1 | 0 | val | 0 | 0 | + /// +-----+-----+-----+-----+ + /// r2 | 0 | 0 | val | 0 | + /// +-----+-----+-----+-----+ + /// r3 | 0 | 0 | 0 | val | + /// +-----+-----+-----+-----+ + /// ~~~ #[inline(always)] - fn is_identity(&self) -> bool { - self.approx_eq(&BaseMat::identity()) + pub fn from_value(value: T) -> Mat4 { + Mat4::new(value, Zero::zero(), Zero::zero(), Zero::zero(), + Zero::zero(), value, Zero::zero(), Zero::zero(), + Zero::zero(), Zero::zero(), value, Zero::zero(), + Zero::zero(), Zero::zero(), Zero::zero(), value) + } + + /// Returns the multiplicative identity matrix + /// ~~~ + /// c0 c1 c2 c3 + /// +----+----+----+----+ + /// r0 | 1 | 0 | 0 | 0 | + /// +----+----+----+----+ + /// r1 | 0 | 1 | 0 | 0 | + /// +----+----+----+----+ + /// r2 | 0 | 0 | 1 | 0 | + /// +----+----+----+----+ + /// r3 | 0 | 0 | 0 | 1 | + /// +----+----+----+----+ + /// ~~~ + #[inline(always)] + pub fn identity() -> Mat4 { + Mat4::new(One::one::(), Zero::zero::(), Zero::zero::(), Zero::zero::(), + Zero::zero::(), One::one::(), Zero::zero::(), Zero::zero::(), + Zero::zero::(), Zero::zero::(), One::one::(), Zero::zero::(), + Zero::zero::(), Zero::zero::(), Zero::zero::(), One::one::()) + } + + /// Returns the additive identity matrix + /// ~~~ + /// c0 c1 c2 c3 + /// +----+----+----+----+ + /// r0 | 0 | 0 | 0 | 0 | + /// +----+----+----+----+ + /// r1 | 0 | 0 | 0 | 0 | + /// +----+----+----+----+ + /// r2 | 0 | 0 | 0 | 0 | + /// +----+----+----+----+ + /// r3 | 0 | 0 | 0 | 0 | + /// +----+----+----+----+ + /// ~~~ + #[inline(always)] + pub fn zero() -> Mat4 { + Mat4::new(Zero::zero::(), Zero::zero::(), Zero::zero::(), Zero::zero::(), + Zero::zero::(), Zero::zero::(), Zero::zero::(), Zero::zero::(), + Zero::zero::(), Zero::zero::(), Zero::zero::(), Zero::zero::(), + Zero::zero::(), Zero::zero::(), Zero::zero::(), Zero::zero::()) } #[inline(always)] - fn is_diagonal(&self) -> bool { + pub fn mul_t(&self, value: T) -> Mat4 { + Mat4::from_cols(self.col(0).mul_t(value), + self.col(1).mul_t(value), + self.col(2).mul_t(value), + self.col(3).mul_t(value)) + } + + #[inline(always)] + pub fn mul_v(&self, vec: &Vec4) -> Vec4 { + Vec4::new(self.row(0).dot(vec), + self.row(1).dot(vec), + self.row(2).dot(vec), + self.row(3).dot(vec)) + } + + #[inline(always)] + pub fn add_m(&self, other: &Mat4) -> Mat4 { + Mat4::from_cols(self.col(0).add_v(other.col(0)), + self.col(1).add_v(other.col(1)), + self.col(2).add_v(other.col(2)), + self.col(3).add_v(other.col(3))) + } + + #[inline(always)] + pub fn sub_m(&self, other: &Mat4) -> Mat4 { + Mat4::from_cols(self.col(0).sub_v(other.col(0)), + self.col(1).sub_v(other.col(1)), + self.col(2).sub_v(other.col(2)), + self.col(3).sub_v(other.col(3))) + } + + #[inline(always)] + pub fn mul_m(&self, other: &Mat4) -> Mat4 { + Mat4::new(self.row(0).dot(other.col(0)), + self.row(1).dot(other.col(0)), + self.row(2).dot(other.col(0)), + self.row(3).dot(other.col(0)), + + self.row(0).dot(other.col(1)), + self.row(1).dot(other.col(1)), + self.row(2).dot(other.col(1)), + self.row(3).dot(other.col(1)), + + self.row(0).dot(other.col(2)), + self.row(1).dot(other.col(2)), + self.row(2).dot(other.col(2)), + self.row(3).dot(other.col(2)), + + self.row(0).dot(other.col(3)), + self.row(1).dot(other.col(3)), + self.row(2).dot(other.col(3)), + self.row(3).dot(other.col(3))) + } + + #[inline(always)] + pub fn mul_self_t(&mut self, value: T) { + self.col_mut(0).mul_self_t(value); + self.col_mut(1).mul_self_t(value); + self.col_mut(2).mul_self_t(value); + self.col_mut(3).mul_self_t(value); + } + + #[inline(always)] + pub fn add_self_m(&mut self, other: &Mat4) { + self.col_mut(0).add_self_v(other.col(0)); + self.col_mut(1).add_self_v(other.col(1)); + self.col_mut(2).add_self_v(other.col(2)); + self.col_mut(3).add_self_v(other.col(3)); + } + + #[inline(always)] + pub fn sub_self_m(&mut self, other: &Mat4) { + self.col_mut(0).sub_self_v(other.col(0)); + self.col_mut(1).sub_self_v(other.col(1)); + self.col_mut(2).sub_self_v(other.col(2)); + self.col_mut(3).sub_self_v(other.col(3)); + } + + pub fn dot(&self, other: &Mat4) -> T { + other.transpose().mul_m(self).trace() + } + + pub fn determinant(&self) -> T { + let m0 = Mat3::new(*self.elem(1, 1), *self.elem(2, 1), *self.elem(3, 1), + *self.elem(1, 2), *self.elem(2, 2), *self.elem(3, 2), + *self.elem(1, 3), *self.elem(2, 3), *self.elem(3, 3)); + let m1 = Mat3::new(*self.elem(0, 1), *self.elem(2, 1), *self.elem(3, 1), + *self.elem(0, 2), *self.elem(2, 2), *self.elem(3, 2), + *self.elem(0, 3), *self.elem(2, 3), *self.elem(3, 3)); + let m2 = Mat3::new(*self.elem(0, 1), *self.elem(1, 1), *self.elem(3, 1), + *self.elem(0, 2), *self.elem(1, 2), *self.elem(3, 2), + *self.elem(0, 3), *self.elem(1, 3), *self.elem(3, 3)); + let m3 = Mat3::new(*self.elem(0, 1), *self.elem(1, 1), *self.elem(2, 1), + *self.elem(0, 2), *self.elem(1, 2), *self.elem(2, 2), + *self.elem(0, 3), *self.elem(1, 3), *self.elem(2, 3)); + + self.elem(0, 0) * m0.determinant() - + self.elem(1, 0) * m1.determinant() + + self.elem(2, 0) * m2.determinant() - + self.elem(3, 0) * m3.determinant() + } + + pub fn trace(&self) -> T { + *self.elem(0, 0) + + *self.elem(1, 1) + + *self.elem(2, 2) + + *self.elem(3, 3) + } + + #[inline(always)] + pub fn to_identity(&mut self) { + *self = Mat4::identity(); + } + + #[inline(always)] + pub fn to_zero(&mut self) { + *self = Mat4::zero(); + } +} + +impl Neg> for Mat4 { + #[inline(always)] + pub fn neg(&self) -> Mat4 { + Mat4::from_cols(-self.col(0), -self.col(1), -self.col(2), -self.col(3)) + } +} + +impl> Mat4 { + pub fn inverse(&self) -> Option> { + let d = self.determinant(); + if d.approx_eq(&Zero::zero()) { + None + } else { + // Gauss Jordan Elimination with partial pivoting + // So take this matrix, A, augmented with the identity + // and essentially reduce [A|I] + + let mut A = *self; + let mut I = Mat4::identity::(); + + for uint::range(0, 4) |j| { + // Find largest element in col j + let mut i1 = j; + for uint::range(j + 1, 4) |i| { + if A.elem(j, i).abs() > A.elem(j, i1).abs() { + i1 = i; + } + } + + // Swap columns i1 and j in A and I to + // put pivot on diagonal + A.swap_cols(i1, j); + I.swap_cols(i1, j); + + // Scale col j to have a unit diagonal + let ajj = *A.elem(j, j); + I.col_mut(j).div_self_t(ajj); + A.col_mut(j).div_self_t(ajj); + + // Eliminate off-diagonal elems in col j of A, + // doing identical ops to I + for uint::range(0, 4) |i| { + if i != j { + let ij_mul_aij = I.col(j).mul_t(*A.elem(i, j)); + let aj_mul_aij = A.col(j).mul_t(*A.elem(i, j)); + I.col_mut(i).sub_self_v(&ij_mul_aij); + A.col_mut(i).sub_self_v(&aj_mul_aij); + } + } + } + Some(I) + } + } + + #[inline(always)] + pub fn invert_self(&mut self) { + *self = self.inverse().expect("Couldn't invert the matrix!"); + } + + #[inline(always)] + pub fn is_identity(&self) -> bool { + self.approx_eq(&Mat4::identity()) + } + + #[inline(always)] + pub fn is_diagonal(&self) -> bool { self.elem(0, 1).approx_eq(&Zero::zero()) && self.elem(0, 2).approx_eq(&Zero::zero()) && self.elem(0, 3).approx_eq(&Zero::zero()) && @@ -1535,12 +1389,12 @@ impl BaseMat> for Mat4 { } #[inline(always)] - fn is_rotated(&self) -> bool { - !self.approx_eq(&BaseMat::identity()) + pub fn is_rotated(&self) -> bool { + !self.approx_eq(&Mat4::identity()) } #[inline(always)] - fn is_symmetric(&self) -> bool { + pub fn is_symmetric(&self) -> bool { self.elem(0, 1).approx_eq(self.elem(1, 0)) && self.elem(0, 2).approx_eq(self.elem(2, 0)) && self.elem(0, 3).approx_eq(self.elem(3, 0)) && @@ -1559,96 +1413,24 @@ impl BaseMat> for Mat4 { } #[inline(always)] - fn is_invertible(&self) -> bool { + pub fn is_invertible(&self) -> bool { !self.determinant().approx_eq(&Zero::zero()) } - - #[inline(always)] - fn to_ptr(&self) -> *T { - unsafe { transmute(self) } - } } -impl BaseMat4> for Mat4 { - /// Construct a 4 x 4 matrix - /// - /// # Arguments - /// - /// - `c0r0`, `c0r1`, `c0r2`, `c0r3`: the first column of the matrix - /// - `c1r0`, `c1r1`, `c1r2`, `c1r3`: the second column of the matrix - /// - `c2r0`, `c2r1`, `c2r2`, `c2r3`: the third column of the matrix - /// - `c3r0`, `c3r1`, `c3r2`, `c3r3`: the fourth column of the matrix - /// - /// ~~~ - /// c0 c1 c2 c3 - /// +------+------+------+------+ - /// r0 | c0r0 | c1r0 | c2r0 | c3r0 | - /// +------+------+------+------+ - /// r1 | c0r1 | c1r1 | c2r1 | c3r1 | - /// +------+------+------+------+ - /// r2 | c0r2 | c1r2 | c2r2 | c3r2 | - /// +------+------+------+------+ - /// r3 | c0r3 | c1r3 | c2r3 | c3r3 | - /// +------+------+------+------+ - /// ~~~ +impl> ApproxEq for Mat4 { #[inline(always)] - fn new(c0r0: T, c0r1: T, c0r2: T, c0r3: T, - c1r0: T, c1r1: T, c1r2: T, c1r3: T, - c2r0: T, c2r1: T, c2r2: T, c2r3: T, - c3r0: T, c3r1: T, c3r2: T, c3r3: T) -> Mat4 { - BaseMat4::from_cols(BaseVec4::new::>(c0r0, c0r1, c0r2, c0r3), - BaseVec4::new::>(c1r0, c1r1, c1r2, c1r3), - BaseVec4::new::>(c2r0, c2r1, c2r2, c2r3), - BaseVec4::new::>(c3r0, c3r1, c3r2, c3r3)) - } - - /// Construct a 4 x 4 matrix from column vectors - /// - /// # Arguments - /// - /// - `c0`: the first column vector of the matrix - /// - `c1`: the second column vector of the matrix - /// - `c2`: the third column vector of the matrix - /// - `c3`: the fourth column vector of the matrix - /// - /// ~~~ - /// c0 c1 c2 c3 - /// +------+------+------+------+ - /// r0 | c0.x | c1.x | c2.x | c3.x | - /// +------+------+------+------+ - /// r1 | c0.y | c1.y | c2.y | c3.y | - /// +------+------+------+------+ - /// r2 | c0.z | c1.z | c2.z | c3.z | - /// +------+------+------+------+ - /// r3 | c0.w | c1.w | c2.w | c3.w | - /// +------+------+------+------+ - /// ~~~ - #[inline(always)] - fn from_cols(c0: Vec4, c1: Vec4, c2: Vec4, c3: Vec4) -> Mat4 { - Mat4 { x: c0, y: c1, z: c2, w: c3 } - } -} - -impl Neg> for Mat4 { - #[inline(always)] - fn neg(&self) -> Mat4 { - BaseMat4::from_cols(-self.col(0), -self.col(1), -self.col(2), -self.col(3)) - } -} - -impl ApproxEq for Mat4 { - #[inline(always)] - fn approx_epsilon() -> T { + pub fn approx_epsilon() -> T { ApproxEq::approx_epsilon::() } #[inline(always)] - fn approx_eq(&self, other: &Mat4) -> bool { + pub fn approx_eq(&self, other: &Mat4) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } #[inline(always)] - fn approx_eq_eps(&self, other: &Mat4, epsilon: &T) -> bool { + pub fn approx_eq_eps(&self, other: &Mat4, epsilon: &T) -> bool { self.col(0).approx_eq_eps(other.col(0), epsilon) && self.col(1).approx_eq_eps(other.col(1), epsilon) && self.col(2).approx_eq_eps(other.col(2), epsilon) && diff --git a/src/num.rs b/src/num.rs deleted file mode 100644 index 75dc337..0000000 --- a/src/num.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2013 The Lmath 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 NumAssign { - fn add_assign(&mut self, other: &Self); - fn sub_assign(&mut self, other: &Self); - fn mul_assign(&mut self, other: &Self); - fn div_assign(&mut self, other: &Self); - fn rem_assign(&mut self, other: &Self); -} - -macro_rules! impl_NumAssign( - ($T:ty) => ( - impl NumAssign for $T { - #[inline(always)] fn add_assign(&mut self, other: &$T) { *self += *other } - #[inline(always)] fn sub_assign(&mut self, other: &$T) { *self -= *other } - #[inline(always)] fn mul_assign(&mut self, other: &$T) { *self *= *other } - #[inline(always)] fn div_assign(&mut self, other: &$T) { *self /= *other } - #[inline(always)] fn rem_assign(&mut self, other: &$T) { *self %= *other } - } - ) -) - -impl_NumAssign!(float) -impl_NumAssign!(f32) -impl_NumAssign!(f64) - -impl_NumAssign!(int) -impl_NumAssign!(i8) -impl_NumAssign!(i16) -impl_NumAssign!(i32) -impl_NumAssign!(i64) - -impl_NumAssign!(uint) -impl_NumAssign!(u8) -impl_NumAssign!(u16) -impl_NumAssign!(u32) -impl_NumAssign!(u64) \ No newline at end of file diff --git a/src/projection.rs b/src/projection.rs index fa5c222..7fd50ba 100644 --- a/src/projection.rs +++ b/src/projection.rs @@ -13,100 +13,95 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::num::cast; -use mat::{Mat4, BaseMat4}; -use num::NumAssign; +use std::num::{Zero, One}; +use mat::Mat4; -/** - * Create a perspective projection matrix - * - * Note: the fovy parameter should be specified in degrees. - * - * This is the equivalent of the gluPerspective function, the algorithm of which - * can be found [here](http://www.opengl.org/wiki/GluPerspective_code). - */ +// FIXME: We can remove this once we have numeric conversions in std #[inline(always)] -pub fn perspective(fovy: T, aspectRatio: T, near: T, far: T) -> Mat4 { - let _2: T = cast(2); +priv fn two() -> T { + One::one::() + One::one::() +} - let ymax = near * (fovy / _2).to_radians().tan(); +/// +/// Create a perspective projection matrix +/// +/// Note: the fovy parameter should be specified in degrees. +/// +/// This is the equivalent of the gluPerspective function, the algorithm of which +/// can be found [here](http://www.opengl.org/wiki/GluPerspective_code). +/// +#[inline(always)] +pub fn perspective(fovy: T, aspectRatio: T, near: T, far: T) -> Mat4 { + let ymax = near * (fovy / two::()).to_radians().tan(); let xmax = ymax * aspectRatio; frustum(-xmax, xmax, -ymax, ymax, near, far) } -/** - * Define a view frustrum - * - * This is the equivalent of the now deprecated [glFrustrum] - * (http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) function. - */ +/// +/// Define a view frustrum +/// +/// This is the equivalent of the now deprecated [glFrustrum] +/// (http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) function. +/// #[inline(always)] -pub fn frustum(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { - let _0: T = cast(0); - let _1: T = cast(1); - let _2: T = cast(2); +pub fn frustum(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { + let c0r0 = (two::() * near) / (right - left); + let c0r1 = Zero::zero(); + let c0r2 = Zero::zero(); + let c0r3 = Zero::zero(); - let c0r0 = (_2 * near) / (right - left); - let c0r1 = _0; - let c0r2 = _0; - let c0r3 = _0; - - let c1r0 = _0; - let c1r1 = (_2 * near) / (top - bottom); - let c1r2 = _0; - let c1r3 = _0; + let c1r0 = Zero::zero(); + let c1r1 = (two::() * near) / (top - bottom); + let c1r2 = Zero::zero(); + let c1r3 = Zero::zero(); let c2r0 = (right + left) / (right - left); let c2r1 = (top + bottom) / (top - bottom); let c2r2 = -(far + near) / (far - near); - let c2r3 = -_1; + let c2r3 = -One::one::(); - let c3r0 = _0; - let c3r1 = _0; - let c3r2 = -(_2 * far * near) / (far - near); - let c3r3 = _0; + let c3r0 = Zero::zero(); + let c3r1 = Zero::zero(); + let c3r2 = -(two::() * far * near) / (far - near); + let c3r3 = Zero::zero(); - BaseMat4::new(c0r0, c0r1, c0r2, c0r3, - c1r0, c1r1, c1r2, c1r3, - c2r0, c2r1, c2r2, c2r3, - c3r0, c3r1, c3r2, c3r3) + Mat4::new(c0r0, c0r1, c0r2, c0r3, + c1r0, c1r1, c1r2, c1r3, + c2r0, c2r1, c2r2, c2r3, + c3r0, c3r1, c3r2, c3r3) } -/** - * Create an orthographic projection matrix - * - * This is the equivalent of the now deprecated [glOrtho] - * (http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) function. - */ +/// +/// Create an orthographic projection matrix +/// +/// This is the equivalent of the now deprecated [glOrtho] +/// (http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) function. +/// #[inline(always)] -pub fn ortho(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { - let _0: T = cast(0); - let _1: T = cast(1); - let _2: T = cast(2); +pub fn ortho(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { + let c0r0 = two::() / (right - left); + let c0r1 = Zero::zero(); + let c0r2 = Zero::zero(); + let c0r3 = Zero::zero(); - let c0r0 = _2 / (right - left); - let c0r1 = _0; - let c0r2 = _0; - let c0r3 = _0; + let c1r0 = Zero::zero(); + let c1r1 = two::() / (top - bottom); + let c1r2 = Zero::zero(); + let c1r3 = Zero::zero(); - let c1r0 = _0; - let c1r1 = _2 / (top - bottom); - let c1r2 = _0; - let c1r3 = _0; - - let c2r0 = _0; - let c2r1 = _0; - let c2r2 = -_2 / (far - near); - let c2r3 = _0; + let c2r0 = Zero::zero(); + let c2r1 = Zero::zero(); + let c2r2 = -two::() / (far - near); + let c2r3 = Zero::zero(); let c3r0 = -(right + left) / (right - left); let c3r1 = -(top + bottom) / (top - bottom); let c3r2 = -(far + near) / (far - near); - let c3r3 = _1; + let c3r3 = One::one(); - BaseMat4::new(c0r0, c0r1, c0r2, c0r3, - c1r0, c1r1, c1r2, c1r3, - c2r0, c2r1, c2r2, c2r3, - c3r0, c3r1, c3r2, c3r3) + Mat4::new(c0r0, c0r1, c0r2, c0r3, + c1r0, c1r1, c1r2, c1r3, + c2r0, c2r1, c2r2, c2r3, + c3r0, c3r1, c3r2, c3r3) } diff --git a/src/quat.rs b/src/quat.rs index 034b587..bac1886 100644 --- a/src/quat.rs +++ b/src/quat.rs @@ -17,10 +17,14 @@ use std::cast::transmute; use std::cmp::ApproxEq; use std::num::{Zero, One, cast}; -use mat::{Mat3, BaseMat3}; -use vec::{Vec3, BaseVec3, AffineVec, NumVec, NumVec3}; +use mat::Mat3; +use vec::Vec3; -use num::NumAssign; +// FIXME: We can remove this once we have numeric conversions in std +#[inline(always)] +priv fn two() -> T { + One::one::() + One::one::() +} /// A quaternion in scalar/vector form /// @@ -35,7 +39,29 @@ use num::NumAssign; #[deriving(Eq)] pub struct Quat { s: T, v: Vec3 } -pub impl Quat { +impl Quat { + #[inline(always)] + pub fn index<'a>(&'a self, i: uint) -> &'a T { + &'a self.as_slice()[i] + } + + #[inline(always)] + pub fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { + &'a mut self.as_mut_slice()[i] + } + + #[inline(always)] + pub fn as_slice<'a>(&'a self) -> &'a [T,..4] { + unsafe { transmute(self) } + } + + #[inline(always)] + pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T,..4] { + unsafe { transmute(self) } + } +} + +impl Quat { /// Construct the quaternion from one scalar component and three /// imaginary components /// @@ -46,8 +72,8 @@ pub impl Quat { /// - `yj`: the second imaginary component /// - `zk`: the third imaginary component #[inline(always)] - fn new(w: T, xi: T, yj: T, zk: T) -> Quat { - Quat::from_sv(w, BaseVec3::new(xi, yj, zk)) + pub fn new(w: T, xi: T, yj: T, zk: T) -> Quat { + Quat::from_sv(w, Vec3::new(xi, yj, zk)) } /// Construct the quaternion from a scalar and a vector @@ -57,13 +83,30 @@ pub impl Quat { /// - `s`: the scalar component /// - `v`: a vector containing the three imaginary components #[inline(always)] - fn from_sv(s: T, v: Vec3) -> Quat { + pub fn from_sv(s: T, v: Vec3) -> Quat { Quat { s: s, v: v } } + #[inline(always)] + pub fn swap(&mut self, a: uint, b: uint) { + let tmp = *self.index(a); + *self.index_mut(a) = *self.index(b); + *self.index_mut(b) = tmp; + } + + #[inline(always)] + pub fn map(&self, f: &fn(&T) -> T) -> Quat { + Quat::new(f(self.index(0)), + f(self.index(1)), + f(self.index(2)), + f(self.index(3))) + } +} + +impl Quat { /// The multiplicative identity, ie: `q = 1 + 0i + 0j + 0i` #[inline(always)] - fn identity() -> Quat { + pub fn identity() -> Quat { Quat::new(One::one(), Zero::zero(), Zero::zero(), @@ -72,7 +115,7 @@ pub impl Quat { /// The additive identity, ie: `q = 0 + 0i + 0j + 0i` #[inline(always)] - fn zero() -> Quat { + pub fn zero() -> Quat { Quat::new(Zero::zero(), Zero::zero(), Zero::zero(), @@ -80,39 +123,35 @@ pub impl Quat { } #[inline(always)] - fn from_angle_x(radians: T) -> Quat { - let _2 = cast(2); - Quat::new((radians / _2).cos(), + pub fn from_angle_x(radians: T) -> Quat { + Quat::new((radians / two()).cos(), radians.sin(), Zero::zero(), Zero::zero()) } #[inline(always)] - fn from_angle_y(radians: T) -> Quat { - let _2 = cast(2); - Quat::new((radians / _2).cos(), + pub fn from_angle_y(radians: T) -> Quat { + Quat::new((radians / two()).cos(), Zero::zero(), radians.sin(), Zero::zero()) } #[inline(always)] - fn from_angle_z(radians: T) -> Quat { - let _2 = cast(2); - Quat::new((radians / _2).cos(), + pub fn from_angle_z(radians: T) -> Quat { + Quat::new((radians / two()).cos(), Zero::zero(), Zero::zero(), radians.sin()) } #[inline(always)] - fn from_angle_xyz(radians_x: T, radians_y: T, radians_z: T) -> Quat { + pub fn from_angle_xyz(radians_x: T, radians_y: T, radians_z: T) -> Quat { // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Conversion - let _2 = cast(2); - let xdiv2 = radians_x / _2; - let ydiv2 = radians_y / _2; - let zdiv2 = radians_z / _2; + let xdiv2 = radians_x / two(); + let ydiv2 = radians_y / two(); + let zdiv2 = radians_z / two(); Quat::new(zdiv2.cos() * xdiv2.cos() * ydiv2.cos() + zdiv2.sin() * xdiv2.sin() * ydiv2.sin(), zdiv2.sin() * xdiv2.cos() * ydiv2.cos() - zdiv2.cos() * xdiv2.sin() * ydiv2.sin(), zdiv2.cos() * xdiv2.sin() * ydiv2.cos() + zdiv2.sin() * xdiv2.cos() * ydiv2.sin(), @@ -120,38 +159,18 @@ pub impl Quat { } #[inline(always)] - fn from_angle_axis(radians: T, axis: &Vec3) -> Quat { - let half = radians / cast(2); + pub fn from_angle_axis(radians: T, axis: &Vec3) -> Quat { + let half = radians / two(); Quat::from_sv(half.cos(), axis.mul_t(half.sin())) } - #[inline(always)] - fn from_axes(x: Vec3, y: Vec3, z: Vec3) -> Quat { - let m: Mat3 = BaseMat3::from_axes(x, y, z); m.to_quat() - } - - #[inline(always)] - fn index<'a>(&'a self, i: uint) -> &'a T { - unsafe { &'a transmute::<&'a Quat, &'a [T,..4]>(self)[i] } - } - - #[inline(always)] - fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { - unsafe { &'a mut transmute::< &'a mut Quat, &'a mut [T,..4]>(self)[i] } - } - - fn get_angle_axis(&self) -> (T, Vec3) { + pub fn get_angle_axis(&self) -> (T, Vec3) { fail!(~"Not yet implemented.") } - #[inline(always)] - fn look_at(dir: &Vec3, up: &Vec3) -> Quat { - let m: Mat3 = BaseMat3::look_at(dir, up); m.to_quat() - } - /// The result of multiplying the quaternion a scalar #[inline(always)] - fn mul_t(&self, value: T) -> Quat { + pub fn mul_t(&self, value: T) -> Quat { Quat::new(*self.index(0) * value, *self.index(1) * value, *self.index(2) * value, @@ -160,7 +179,7 @@ pub impl Quat { /// The result of dividing the quaternion a scalar #[inline(always)] - fn div_t(&self, value: T) -> Quat { + pub fn div_t(&self, value: T) -> Quat { Quat::new(*self.index(0) / value, *self.index(1) / value, *self.index(2) / value, @@ -169,14 +188,14 @@ pub impl Quat { /// The result of multiplying the quaternion by a vector #[inline(always)] - fn mul_v(&self, vec: &Vec3) -> Vec3 { + pub fn mul_v(&self, vec: &Vec3) -> Vec3 { let tmp = self.v.cross(vec).add_v(&vec.mul_t(self.s)); - self.v.cross(&tmp).mul_t(cast(2)).add_v(vec) + self.v.cross(&tmp).mul_t(two()).add_v(vec) } /// The sum of this quaternion and `other` #[inline(always)] - fn add_q(&self, other: &Quat) -> Quat { + pub fn add_q(&self, other: &Quat) -> Quat { Quat::new(*self.index(0) + *other.index(0), *self.index(1) + *other.index(1), *self.index(2) + *other.index(2), @@ -185,7 +204,7 @@ pub impl Quat { /// The sum of this quaternion and `other` #[inline(always)] - fn sub_q(&self, other: &Quat) -> Quat { + pub fn sub_q(&self, other: &Quat) -> Quat { Quat::new(*self.index(0) - *other.index(0), *self.index(1) - *other.index(1), *self.index(2) - *other.index(2), @@ -194,28 +213,28 @@ pub impl Quat { /// The the result of multipliplying the quaternion by `other` #[inline(always)] - fn mul_q(&self, other: &Quat) -> Quat { - Quat::new(self.s * other.s - self.v.x * other.v.x - self.v.y * other.v.y - self.v.z * other.v.z, - self.s * other.v.x + self.v.x * other.s + self.v.y * other.v.z - self.v.z * other.v.y, - self.s * other.v.y + self.v.y * other.s + self.v.z * other.v.x - self.v.x * other.v.z, - self.s * other.v.z + self.v.z * other.s + self.v.x * other.v.y - self.v.y * other.v.x) + pub fn mul_q(&self, other: &Quat) -> Quat { + Quat::new(self.s * other.s - self.v.x * other.v.x - self.v.y * other.v.y - self.v.z * other.v.z, + self.s * other.v.x + self.v.x * other.s + self.v.y * other.v.z - self.v.z * other.v.y, + self.s * other.v.y + self.v.y * other.s + self.v.z * other.v.x - self.v.x * other.v.z, + self.s * other.v.z + self.v.z * other.s + self.v.x * other.v.y - self.v.y * other.v.x) } /// The dot product of the quaternion and `other` #[inline(always)] - fn dot(&self, other: &Quat) -> T { + pub fn dot(&self, other: &Quat) -> T { self.s * other.s + self.v.dot(&other.v) } /// The conjugate of the quaternion #[inline(always)] - fn conjugate(&self) -> Quat { + pub fn conjugate(&self) -> Quat { Quat::from_sv(self.s, -self.v) } /// The multiplicative inverse of the quaternion #[inline(always)] - fn inverse(&self) -> Quat { + pub fn inverse(&self) -> Quat { self.conjugate().div_t(self.magnitude2()) } @@ -223,7 +242,7 @@ pub impl Quat { /// magnitude comparisons where the exact magnitude does not need to be /// calculated. #[inline(always)] - fn magnitude2(&self) -> T { + pub fn magnitude2(&self) -> T { self.s * self.s + self.v.length2() } @@ -235,14 +254,40 @@ pub impl Quat { /// to be known, for example for quaternion-quaternion magnitude comparisons, /// it is advisable to use the `magnitude2` method instead. #[inline(always)] - fn magnitude(&self) -> T { + pub fn magnitude(&self) -> T { self.magnitude2().sqrt() } /// The normalized quaternion #[inline(always)] - fn normalize(&self) -> Quat { - self.mul_t(One::one::()/self.magnitude()) + pub fn normalize(&self) -> Quat { + self.mul_t(One::one::() / self.magnitude()) + } + + /// Convert the quaternion to a 3 x 3 rotation matrix + #[inline(always)] + pub fn to_mat3(&self) -> Mat3 { + let x2 = self.v.x + self.v.x; + let y2 = self.v.y + self.v.y; + let z2 = self.v.z + self.v.z; + + let xx2 = x2 * self.v.x; + let xy2 = x2 * self.v.y; + let xz2 = x2 * self.v.z; + + let yy2 = y2 * self.v.y; + let yz2 = y2 * self.v.z; + let zz2 = z2 * self.v.z; + + let sy2 = y2 * self.s; + let sz2 = z2 * self.s; + let sx2 = x2 * self.s; + + let _1: T = One::one(); + + Mat3::new(_1 - yy2 - zz2, xy2 + sz2, xz2 - sy2, + xy2 - sz2, _1 - xx2 - zz2, yz2 + sx2, + xz2 + sy2, yz2 - sx2, _1 - xx2 - yy2) } /// Normalised linear interpolation @@ -251,9 +296,31 @@ pub impl Quat { /// /// The intoperlated quaternion #[inline(always)] - fn nlerp(&self, other: &Quat, amount: T) -> Quat { + pub fn nlerp(&self, other: &Quat, amount: T) -> Quat { self.mul_t(One::one::() - amount).add_q(&other.mul_t(amount)).normalize() } +} + +impl Neg> for Quat { + #[inline(always)] + pub fn neg(&self) -> Quat { + Quat::new(-*self.index(0), + -*self.index(1), + -*self.index(2), + -*self.index(3)) + } +} + +impl Quat { + #[inline(always)] + pub fn look_at(dir: &Vec3, up: &Vec3) -> Quat { + Mat3::look_at(dir, up).to_quat() + } + + #[inline(always)] + pub fn from_axes(x: Vec3, y: Vec3, z: Vec3) -> Quat { + Mat3::from_axes(x, y, z).to_quat() + } /// Spherical Linear Intoperlation /// @@ -275,13 +342,12 @@ pub impl Quat { /// - [Arcsynthesis OpenGL tutorial] /// (http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Interpolation.html) #[inline(always)] - fn slerp(&self, other: &Quat, amount: T) -> Quat { + pub fn slerp(&self, other: &Quat, amount: T) -> Quat { let dot = self.dot(other); - let dot_threshold = cast(0.9995); if dot > dot_threshold { - return self.nlerp(other, amount); // if quaternions are close together use `nlerp` + self.nlerp(other, amount) // if quaternions are close together use `nlerp` } else { let robust_dot = dot.clamp(&-One::one::(), &One::one()); // stay within the domain of acos() @@ -292,67 +358,25 @@ pub impl Quat { let q = other.sub_q(&self.mul_t(robust_dot)) .normalize(); - return self.mul_t(theta.cos()) - .add_q(&q.mul_t(theta.sin())); + self.mul_t(theta.cos()) + .add_q(&q.mul_t(theta.sin())) } } - - /// A pointer to the first component of the quaternion - #[inline(always)] - fn to_ptr(&self) -> *T { - unsafe { transmute(self) } - } - - /// Convert the quaternion to a 3 x 3 rotation matrix - #[inline(always)] - fn to_mat3(&self) -> Mat3 { - let x2 = self.v.x + self.v.x; - let y2 = self.v.y + self.v.y; - let z2 = self.v.z + self.v.z; - - let xx2 = x2 * self.v.x; - let xy2 = x2 * self.v.y; - let xz2 = x2 * self.v.z; - - let yy2 = y2 * self.v.y; - let yz2 = y2 * self.v.z; - let zz2 = z2 * self.v.z; - - let sy2 = y2 * self.s; - let sz2 = z2 * self.s; - let sx2 = x2 * self.s; - - let _1: T = One::one(); - - BaseMat3::new(_1 - yy2 - zz2, xy2 + sz2, xz2 - sy2, - xy2 - sz2, _1 - xx2 - zz2, yz2 + sx2, - xz2 + sy2, yz2 - sx2, _1 - xx2 - yy2) - } } -impl Neg> for Quat { +impl> ApproxEq for Quat { #[inline(always)] - fn neg(&self) -> Quat { - Quat::new(-*self.index(0), - -*self.index(1), - -*self.index(2), - -*self.index(3)) - } -} - -impl ApproxEq for Quat { - #[inline(always)] - fn approx_epsilon() -> T { + pub fn approx_epsilon() -> T { ApproxEq::approx_epsilon::() } #[inline(always)] - fn approx_eq(&self, other: &Quat) -> bool { + pub fn approx_eq(&self, other: &Quat) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } #[inline(always)] - fn approx_eq_eps(&self, other: &Quat, epsilon: &T) -> bool { + pub fn approx_eq_eps(&self, other: &Quat, epsilon: &T) -> bool { self.index(0).approx_eq_eps(other.index(0), epsilon) && self.index(1).approx_eq_eps(other.index(1), epsilon) && self.index(2).approx_eq_eps(other.index(2), epsilon) && @@ -360,12 +384,8 @@ impl ApproxEq for Quat { } } -// GLSL-style type aliases for quaternions. These are not present in the GLSL -// specification, but they roughly follow the same nomenclature. - -/// a single-precision floating-point quaternion +// GLSL-style type aliases type quat = Quat; -/// a double-precision floating-point quaternion type dquat = Quat; // Rust-style type aliases diff --git a/src/test/test_mat.rs b/src/test/test_mat.rs index 314c536..943576a 100644 --- a/src/test/test_mat.rs +++ b/src/test/test_mat.rs @@ -16,8 +16,6 @@ use mat::*; use vec::*; -// TODO - #[test] fn test_mat2() { let a = Mat2 { x: Vec2 { x: 1.0, y: 3.0 }, @@ -25,62 +23,70 @@ fn test_mat2() { let b = Mat2 { x: Vec2 { x: 2.0, y: 4.0 }, y: Vec2 { x: 3.0, y: 5.0 } }; - let v1 = vec2::new(1.0, 2.0); + let v1 = Vec2::new::(1.0, 2.0); let f1 = 0.5; - assert_eq!(a, mat2::new(1.0, 3.0, - 2.0, 4.0)); + assert_eq!(a, Mat2::new::(1.0, 3.0, + 2.0, 4.0)); - assert_eq!(a, mat2::from_cols(vec2::new(1.0, 3.0), - vec2::new(2.0, 4.0))); + assert_eq!(a, Mat2::from_cols::(Vec2::new::(1.0, 3.0), + Vec2::new::(2.0, 4.0))); - assert_eq!(mat2::from_value(4.0), mat2::new(4.0, 0.0, - 0.0, 4.0)); + assert_eq!(Mat2::from_value::(4.0), + Mat2::new::(4.0, 0.0, + 0.0, 4.0)); - assert_eq!(*a.col(0), vec2::new(1.0, 3.0)); - assert_eq!(*a.col(1), vec2::new(2.0, 4.0)); + assert_eq!(*a.col(0), Vec2::new::(1.0, 3.0)); + assert_eq!(*a.col(1), Vec2::new::(2.0, 4.0)); - assert_eq!(a.row(0), vec2::new(1.0, 2.0)); - assert_eq!(a.row(1), vec2::new(3.0, 4.0)); + assert_eq!(a.row(0), Vec2::new::(1.0, 2.0)); + assert_eq!(a.row(1), Vec2::new::(3.0, 4.0)); - assert_eq!(*a.col(0), vec2::new(1.0, 3.0)); - assert_eq!(*a.col(1), vec2::new(2.0, 4.0)); + assert_eq!(*a.col(0), Vec2::new::(1.0, 3.0)); + assert_eq!(*a.col(1), Vec2::new::(2.0, 4.0)); - assert_eq!(mat2::identity(), mat2::new(1.0, 0.0, - 0.0, 1.0)); + assert_eq!(Mat2::identity::(), + Mat2::new::(1.0, 0.0, + 0.0, 1.0)); - assert_eq!(mat2::zero(), mat2::new(0.0, 0.0, - 0.0, 0.0)); + assert_eq!(Mat2::zero::(), + Mat2::new::(0.0, 0.0, + 0.0, 0.0)); assert_eq!(a.determinant(), -2.0); assert_eq!(a.trace(), 5.0); - assert_eq!(a.neg(), mat2::new(-1.0, -3.0, + assert_eq!(a.neg(), + Mat2::new::(-1.0, -3.0, -2.0, -4.0)); assert_eq!(-a, a.neg()); - - assert_eq!(a.mul_t(f1), mat2::new(0.5, 1.5, - 1.0, 2.0)); - assert_eq!(a.mul_v(&v1), vec2::new(5.0, 11.0)); - - assert_eq!(a.add_m(&b), mat2::new(3.0, 7.0, - 5.0, 9.0)); - assert_eq!(a.sub_m(&b), mat2::new(-1.0, -1.0, - -1.0, -1.0)); - assert_eq!(a.mul_m(&b), mat2::new(10.0, 22.0, - 13.0, 29.0)); + assert_eq!(a.mul_t(f1), + Mat2::new::(0.5, 1.5, + 1.0, 2.0)); + assert_eq!(a.mul_v(&v1), Vec2::new::(5.0, 11.0)); + assert_eq!(a.add_m(&b), + Mat2::new::(3.0, 7.0, + 5.0, 9.0)); + assert_eq!(a.sub_m(&b), + Mat2::new::(-1.0, -1.0, + -1.0, -1.0)); + assert_eq!(a.mul_m(&b), + Mat2::new::(10.0, 22.0, + 13.0, 29.0)); assert_eq!(a.dot(&b), 40.0); - assert_eq!(a.transpose(), mat2::new(1.0, 2.0, - 3.0, 4.0)); + assert_eq!(a.transpose(), + Mat2::new::(1.0, 2.0, + 3.0, 4.0)); - assert_eq!(a.inverse().unwrap(), mat2::new(-2.0, 1.5, - 1.0, -0.5)); + assert_eq!(a.inverse().unwrap(), + Mat2::new::(-2.0, 1.5, + 1.0, -0.5)); - assert!(mat2::new(0.0, 2.0, - 0.0, 5.0).inverse().is_none()); + assert!(Mat2::new::(0.0, 2.0, + 0.0, 5.0).inverse().is_none()); - let ident = mat2::identity(); + let ident = Mat2::identity::(); assert!(ident.is_identity()); assert!(ident.is_symmetric()); @@ -94,24 +100,26 @@ fn test_mat2() { assert!(a.is_rotated()); assert!(a.is_invertible()); - let c = mat2::new(2.0, 1.0, - 1.0, 2.0); + let c = Mat2::new::(2.0, 1.0, + 1.0, 2.0); assert!(!c.is_identity()); assert!(c.is_symmetric()); assert!(!c.is_diagonal()); assert!(c.is_rotated()); assert!(c.is_invertible()); - assert!(mat2::from_value(6.0).is_diagonal()); + assert!(Mat2::from_value::(6.0).is_diagonal()); - assert_eq!(a.to_mat3(), mat3::new(1.0, 3.0, 0.0, - 2.0, 4.0, 0.0, - 0.0, 0.0, 1.0)); + assert_eq!(a.to_mat3(), + Mat3::new::(1.0, 3.0, 0.0, + 2.0, 4.0, 0.0, + 0.0, 0.0, 1.0)); - assert_eq!(a.to_mat4(), mat4::new(1.0, 3.0, 0.0, 0.0, - 2.0, 4.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0)); + assert_eq!(a.to_mat4(), + Mat4::new::(1.0, 3.0, 0.0, 0.0, + 2.0, 4.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0)); } fn test_mat2_mut() { @@ -122,7 +130,7 @@ fn test_mat2_mut() { let f1 = 0.5; - let mut mut_a: mat2 = a; + let mut mut_a = a; mut_a.swap_cols(0, 1); assert_eq!(mut_a.col(0), a.col(1)); @@ -134,16 +142,12 @@ fn test_mat2_mut() { assert_eq!(mut_a.row(1), a.row(0)); mut_a = a; - mut_a.set(&b); - assert_eq!(mut_a, b); - mut_a = a; - mut_a.to_identity(); assert!(mut_a.is_identity()); mut_a = a; mut_a.to_zero(); - assert_eq!(mut_a, mat2::zero()); + assert_eq!(mut_a, Mat2::zero::()); mut_a = a; mut_a.mul_self_t(f1); @@ -169,10 +173,10 @@ fn test_mat2_mut() { #[test] fn test_mat2_approx_eq() { - assert!(!mat2::new(0.000001, 0.000001, - 0.000001, 0.000001).approx_eq(&mat2::zero())); - assert!(mat2::new(0.0000001, 0.0000001, - 0.0000001, 0.0000001).approx_eq(&mat2::zero())); + assert!(!Mat2::new::(0.000001, 0.000001, + 0.000001, 0.000001).approx_eq(&Mat2::zero::())); + assert!(Mat2::new::(0.0000001, 0.0000001, + 0.0000001, 0.0000001).approx_eq(&Mat2::zero::())); } #[test] @@ -184,75 +188,83 @@ fn test_mat3() { y: Vec3 { x: 3.0, y: 6.0, z: 9.0 }, z: Vec3 { x: 4.0, y: 7.0, z: 10.0 } }; - let v1 = vec3::new(1.0, 2.0, 3.0); + let v1 = Vec3::new::(1.0, 2.0, 3.0); let f1 = 0.5; - assert_eq!(a, mat3::new(1.0, 4.0, 7.0, - 2.0, 5.0, 8.0, - 3.0, 6.0, 9.0)); + assert_eq!(a, Mat3::new::(1.0, 4.0, 7.0, + 2.0, 5.0, 8.0, + 3.0, 6.0, 9.0)); - assert_eq!(a, mat3::from_cols(vec3::new(1.0, 4.0, 7.0), - vec3::new(2.0, 5.0, 8.0), - vec3::new(3.0, 6.0, 9.0))); + assert_eq!(a, Mat3::from_cols::(Vec3::new::(1.0, 4.0, 7.0), + Vec3::new::(2.0, 5.0, 8.0), + Vec3::new::(3.0, 6.0, 9.0))); - assert_eq!(*a.col(0), vec3::new(1.0, 4.0, 7.0)); - assert_eq!(*a.col(1), vec3::new(2.0, 5.0, 8.0)); - assert_eq!(*a.col(2), vec3::new(3.0, 6.0, 9.0)); + assert_eq!(*a.col(0), Vec3::new::(1.0, 4.0, 7.0)); + assert_eq!(*a.col(1), Vec3::new::(2.0, 5.0, 8.0)); + assert_eq!(*a.col(2), Vec3::new::(3.0, 6.0, 9.0)); - assert_eq!(a.row(0), vec3::new(1.0, 2.0, 3.0)); - assert_eq!(a.row(1), vec3::new(4.0, 5.0, 6.0)); - assert_eq!(a.row(2), vec3::new(7.0, 8.0, 9.0)); + assert_eq!(a.row(0), Vec3::new::(1.0, 2.0, 3.0)); + assert_eq!(a.row(1), Vec3::new::(4.0, 5.0, 6.0)); + assert_eq!(a.row(2), Vec3::new::(7.0, 8.0, 9.0)); - assert_eq!(*a.col(0), vec3::new(1.0, 4.0, 7.0)); - assert_eq!(*a.col(1), vec3::new(2.0, 5.0, 8.0)); - assert_eq!(*a.col(2), vec3::new(3.0, 6.0, 9.0)); + assert_eq!(*a.col(0), Vec3::new::(1.0, 4.0, 7.0)); + assert_eq!(*a.col(1), Vec3::new::(2.0, 5.0, 8.0)); + assert_eq!(*a.col(2), Vec3::new::(3.0, 6.0, 9.0)); - assert_eq!(mat3::identity(), mat3::new(1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0)); + assert_eq!(Mat3::identity::(), + Mat3::new::(1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0)); - assert_eq!(mat3::zero(), mat3::new(0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0)); + assert_eq!(Mat3::zero::(), + Mat3::new::(0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0)); assert_eq!(a.determinant(), 0.0); assert_eq!(a.trace(), 15.0); - assert_eq!(a.neg(), mat3::new(-1.0, -4.0, -7.0, + assert_eq!(a.neg(), + Mat3::new::(-1.0, -4.0, -7.0, -2.0, -5.0, -8.0, -3.0, -6.0, -9.0)); assert_eq!(-a, a.neg()); - assert_eq!(a.mul_t(f1), mat3::new(0.5, 2.0, 3.5, - 1.0, 2.5, 4.0, - 1.5, 3.0, 4.5)); - assert_eq!(a.mul_v(&v1), vec3::new(14.0, 32.0, 50.0)); + assert_eq!(a.mul_t(f1), + Mat3::new::(0.5, 2.0, 3.5, + 1.0, 2.5, 4.0, + 1.5, 3.0, 4.5)); + assert_eq!(a.mul_v(&v1), Vec3::new::(14.0, 32.0, 50.0)); - assert_eq!(a.add_m(&b), mat3::new(3.0, 9.0, 15.0, - 5.0, 11.0, 17.0, - 7.0, 13.0, 19.0)); - assert_eq!(a.sub_m(&b), mat3::new(-1.0, -1.0, -1.0, - -1.0, -1.0, -1.0, - -1.0, -1.0, -1.0)); - assert_eq!(a.mul_m(&b), mat3::new(36.0, 81.0, 126.0, - 42.0, 96.0, 150.0, - 48.0, 111.0, 174.0)); + assert_eq!(a.add_m(&b), + Mat3::new::(3.0, 9.0, 15.0, + 5.0, 11.0, 17.0, + 7.0, 13.0, 19.0)); + assert_eq!(a.sub_m(&b), + Mat3::new::(-1.0, -1.0, -1.0, + -1.0, -1.0, -1.0, + -1.0, -1.0, -1.0)); + assert_eq!(a.mul_m(&b), + Mat3::new::(36.0, 81.0, 126.0, + 42.0, 96.0, 150.0, + 48.0, 111.0, 174.0)); assert_eq!(a.dot(&b), 330.0); - assert_eq!(a.transpose(), mat3::new(1.0, 2.0, 3.0, - 4.0, 5.0, 6.0, - 7.0, 8.0, 9.0)); + assert_eq!(a.transpose(), + Mat3::new::(1.0, 2.0, 3.0, + 4.0, 5.0, 6.0, + 7.0, 8.0, 9.0)); assert!(a.inverse().is_none()); - assert_eq!(mat3::new(2.0, 4.0, 6.0, - 0.0, 2.0, 4.0, - 0.0, 0.0, 1.0).inverse().unwrap(), - mat3::new(0.5, -1.0, 1.0, - 0.0, 0.5, -2.0, - 0.0, 0.0, 1.0)); + assert_eq!(Mat3::new::(2.0, 4.0, 6.0, + 0.0, 2.0, 4.0, + 0.0, 0.0, 1.0).inverse().unwrap(), + Mat3::new::(0.5, -1.0, 1.0, + 0.0, 0.5, -2.0, + 0.0, 0.0, 1.0)); - let ident: Mat3 = BaseMat::identity(); + let ident = Mat3::identity::(); assert_eq!(ident.inverse().unwrap(), ident); @@ -268,21 +280,22 @@ fn test_mat3() { assert!(a.is_rotated()); assert!(!a.is_invertible()); - let c = mat3::new(3.0, 2.0, 1.0, - 2.0, 3.0, 2.0, - 1.0, 2.0, 3.0); + let c = Mat3::new::(3.0, 2.0, 1.0, + 2.0, 3.0, 2.0, + 1.0, 2.0, 3.0); assert!(!c.is_identity()); assert!(c.is_symmetric()); assert!(!c.is_diagonal()); assert!(c.is_rotated()); assert!(c.is_invertible()); - assert!(mat3::from_value(6.0).is_diagonal()); + assert!(Mat3::from_value::(6.0).is_diagonal()); - assert_eq!(a.to_mat4(), mat4::new(1.0, 4.0, 7.0, 0.0, - 2.0, 5.0, 8.0, 0.0, - 3.0, 6.0, 9.0, 0.0, - 0.0, 0.0, 0.0, 1.0)); + assert_eq!(a.to_mat4(), + Mat4::new::(1.0, 4.0, 7.0, 0.0, + 2.0, 5.0, 8.0, 0.0, + 3.0, 6.0, 9.0, 0.0, + 0.0, 0.0, 0.0, 1.0)); // to_Quaternion } @@ -300,8 +313,8 @@ fn test_mat3_mut() { let f1 = 0.5; - let mut mut_a: mat3 = a; - let mut mut_c: mat3 = c; + let mut mut_a = a; + let mut mut_c = c; mut_a.swap_cols(0, 2); assert_eq!(mut_a.col(0), a.col(2)); @@ -323,16 +336,12 @@ fn test_mat3_mut() { assert_eq!(mut_a.row(2), a.row(1)); mut_a = a; - mut_a.set(&b); - assert_eq!(mut_a, b); - mut_a = a; - mut_a.to_identity(); assert!(mut_a.is_identity()); mut_a = a; mut_a.to_zero(); - assert_eq!(mut_a, mat3::zero()); + assert_eq!(mut_a, Mat3::zero::()); mut_a = a; mut_a.mul_self_t(f1); @@ -358,114 +367,122 @@ fn test_mat3_mut() { #[test] fn test_mat3_approx_eq() { - assert!(!mat3::new(0.000001, 0.000001, 0.000001, - 0.000001, 0.000001, 0.000001, - 0.000001, 0.000001, 0.000001).approx_eq(&mat3::zero())); - assert!(mat3::new(0.0000001, 0.0000001, 0.0000001, - 0.0000001, 0.0000001, 0.0000001, - 0.0000001, 0.0000001, 0.0000001).approx_eq(&mat3::zero())); + assert!(!Mat3::new::(0.000001, 0.000001, 0.000001, + 0.000001, 0.000001, 0.000001, + 0.000001, 0.000001, 0.000001) + .approx_eq(&Mat3::zero::())); + assert!(Mat3::new::(0.0000001, 0.0000001, 0.0000001, + 0.0000001, 0.0000001, 0.0000001, + 0.0000001, 0.0000001, 0.0000001) + .approx_eq(&Mat3::zero::())); } #[test] fn test_mat4() { - let a: mat4 = Mat4 { x: Vec4 { x: 1.0, y: 5.0, z: 9.0, w: 13.0 }, + let a = Mat4 { x: Vec4 { x: 1.0, y: 5.0, z: 9.0, w: 13.0 }, y: Vec4 { x: 2.0, y: 6.0, z: 10.0, w: 14.0 }, z: Vec4 { x: 3.0, y: 7.0, z: 11.0, w: 15.0 }, w: Vec4 { x: 4.0, y: 8.0, z: 12.0, w: 16.0 } }; - let b: mat4 = Mat4 { x: Vec4 { x: 2.0, y: 6.0, z: 10.0, w: 14.0 }, + let b = Mat4 { x: Vec4 { x: 2.0, y: 6.0, z: 10.0, w: 14.0 }, y: Vec4 { x: 3.0, y: 7.0, z: 11.0, w: 15.0 }, z: Vec4 { x: 4.0, y: 8.0, z: 12.0, w: 16.0 }, w: Vec4 { x: 5.0, y: 9.0, z: 13.0, w: 17.0 } }; - let c: mat4 = Mat4 { x: Vec4 { x: 3.0, y: 2.0, z: 1.0, w: 1.0 }, + let c = Mat4 { x: Vec4 { x: 3.0, y: 2.0, z: 1.0, w: 1.0 }, y: Vec4 { x: 2.0, y: 3.0, z: 2.0, w: 2.0 }, z: Vec4 { x: 1.0, y: 2.0, z: 3.0, w: 3.0 }, w: Vec4 { x: 0.0, y: 1.0, z: 1.0, w: 0.0 } }; - let v1 = vec4::new(1.0, 2.0, 3.0, 4.0); + let v1 = Vec4::new::(1.0, 2.0, 3.0, 4.0); let f1 = 0.5; - assert_eq!(a, mat4::new(1.0, 5.0, 9.0, 13.0, - 2.0, 6.0, 10.0, 14.0, - 3.0, 7.0, 11.0, 15.0, - 4.0, 8.0, 12.0, 16.0)); + assert_eq!(a, Mat4::new::(1.0, 5.0, 9.0, 13.0, + 2.0, 6.0, 10.0, 14.0, + 3.0, 7.0, 11.0, 15.0, + 4.0, 8.0, 12.0, 16.0)); - assert_eq!(a, mat4::from_cols(vec4::new(1.0, 5.0, 9.0, 13.0), - vec4::new(2.0, 6.0, 10.0, 14.0), - vec4::new(3.0, 7.0, 11.0, 15.0), - vec4::new(4.0, 8.0, 12.0, 16.0))); + assert_eq!(a, Mat4::from_cols::(Vec4::new::(1.0, 5.0, 9.0, 13.0), + Vec4::new::(2.0, 6.0, 10.0, 14.0), + Vec4::new::(3.0, 7.0, 11.0, 15.0), + Vec4::new::(4.0, 8.0, 12.0, 16.0))); - assert_eq!(mat4::from_value(4.0), mat4::new(4.0, 0.0, 0.0, 0.0, - 0.0, 4.0, 0.0, 0.0, - 0.0, 0.0, 4.0, 0.0, - 0.0, 0.0, 0.0, 4.0)); + assert_eq!(Mat4::from_value::(4.0), + Mat4::new::(4.0, 0.0, 0.0, 0.0, + 0.0, 4.0, 0.0, 0.0, + 0.0, 0.0, 4.0, 0.0, + 0.0, 0.0, 0.0, 4.0)); - assert_eq!(*a.col(0), vec4::new(1.0, 5.0, 9.0, 13.0)); - assert_eq!(*a.col(1), vec4::new(2.0, 6.0, 10.0, 14.0)); - assert_eq!(*a.col(2), vec4::new(3.0, 7.0, 11.0, 15.0)); - assert_eq!(*a.col(3), vec4::new(4.0, 8.0, 12.0, 16.0)); + assert_eq!(*a.col(0), Vec4::new::(1.0, 5.0, 9.0, 13.0)); + assert_eq!(*a.col(1), Vec4::new::(2.0, 6.0, 10.0, 14.0)); + assert_eq!(*a.col(2), Vec4::new::(3.0, 7.0, 11.0, 15.0)); + assert_eq!(*a.col(3), Vec4::new::(4.0, 8.0, 12.0, 16.0)); - assert_eq!(a.row(0), vec4::new( 1.0, 2.0, 3.0, 4.0)); - assert_eq!(a.row(1), vec4::new( 5.0, 6.0, 7.0, 8.0)); - assert_eq!(a.row(2), vec4::new( 9.0, 10.0, 11.0, 12.0)); - assert_eq!(a.row(3), vec4::new(13.0, 14.0, 15.0, 16.0)); + assert_eq!(a.row(0), Vec4::new::( 1.0, 2.0, 3.0, 4.0)); + assert_eq!(a.row(1), Vec4::new::( 5.0, 6.0, 7.0, 8.0)); + assert_eq!(a.row(2), Vec4::new::( 9.0, 10.0, 11.0, 12.0)); + assert_eq!(a.row(3), Vec4::new::(13.0, 14.0, 15.0, 16.0)); - assert_eq!(*a.col(0), vec4::new(1.0, 5.0, 9.0, 13.0)); - assert_eq!(*a.col(1), vec4::new(2.0, 6.0, 10.0, 14.0)); - assert_eq!(*a.col(2), vec4::new(3.0, 7.0, 11.0, 15.0)); - assert_eq!(*a.col(3), vec4::new(4.0, 8.0, 12.0, 16.0)); + assert_eq!(*a.col(0), Vec4::new::(1.0, 5.0, 9.0, 13.0)); + assert_eq!(*a.col(1), Vec4::new::(2.0, 6.0, 10.0, 14.0)); + assert_eq!(*a.col(2), Vec4::new::(3.0, 7.0, 11.0, 15.0)); + assert_eq!(*a.col(3), Vec4::new::(4.0, 8.0, 12.0, 16.0)); - assert_eq!(mat4::identity(), mat4::new(1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0)); + assert_eq!(Mat4::identity::(), + Mat4::new::(1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0)); - assert_eq!(mat4::zero(), mat4::new(0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0)); + assert_eq!(Mat4::zero::(), + Mat4::new::(0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0)); assert_eq!(a.determinant(), 0.0); assert_eq!(a.trace(), 34.0); - assert_eq!(a.neg(), mat4::new(-1.0, -5.0, -9.0, -13.0, + assert_eq!(a.neg(), + Mat4::new::(-1.0, -5.0, -9.0, -13.0, -2.0, -6.0, -10.0, -14.0, -3.0, -7.0, -11.0, -15.0, -4.0, -8.0, -12.0, -16.0)); assert_eq!(-a, a.neg()); - - assert_eq!(a.mul_t(f1), mat4::new(0.5, 2.5, 4.5, 6.5, - 1.0, 3.0, 5.0, 7.0, - 1.5, 3.5, 5.5, 7.5, - 2.0, 4.0, 6.0, 8.0)); - assert_eq!(a.mul_v(&v1), vec4::new(30.0, 70.0, 110.0, 150.0)); - - assert_eq!(a.add_m(&b), mat4::new(3.0, 11.0, 19.0, 27.0, - 5.0, 13.0, 21.0, 29.0, - 7.0, 15.0, 23.0, 31.0, - 9.0, 17.0, 25.0, 33.0)); - assert_eq!(a.sub_m(&b), mat4::new(-1.0, -1.0, -1.0, -1.0, - -1.0, -1.0, -1.0, -1.0, - -1.0, -1.0, -1.0, -1.0, - -1.0, -1.0, -1.0, -1.0)); - assert_eq!(a.mul_m(&b), mat4::new(100.0, 228.0, 356.0, 484.0, - 110.0, 254.0, 398.0, 542.0, - 120.0, 280.0, 440.0, 600.0, - 130.0, 306.0, 482.0, 658.0)); + assert_eq!(a.mul_t(f1), + Mat4::new::(0.5, 2.5, 4.5, 6.5, + 1.0, 3.0, 5.0, 7.0, + 1.5, 3.5, 5.5, 7.5, + 2.0, 4.0, 6.0, 8.0)); + assert_eq!(a.mul_v(&v1), + Vec4::new::(30.0, 70.0, 110.0, 150.0)); + assert_eq!(a.add_m(&b), + Mat4::new::(3.0, 11.0, 19.0, 27.0, + 5.0, 13.0, 21.0, 29.0, + 7.0, 15.0, 23.0, 31.0, + 9.0, 17.0, 25.0, 33.0)); + assert_eq!(a.sub_m(&b), + Mat4::new::(-1.0, -1.0, -1.0, -1.0, + -1.0, -1.0, -1.0, -1.0, + -1.0, -1.0, -1.0, -1.0, + -1.0, -1.0, -1.0, -1.0)); + assert_eq!(a.mul_m(&b), + Mat4::new::(100.0, 228.0, 356.0, 484.0, + 110.0, 254.0, 398.0, 542.0, + 120.0, 280.0, 440.0, 600.0, + 130.0, 306.0, 482.0, 658.0)); assert_eq!(a.dot(&b), 1632.0); + assert_eq!(a.transpose(), + Mat4::new::( 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0)); - assert_eq!(a.transpose(), mat4::new( 1.0, 2.0, 3.0, 4.0, - 5.0, 6.0, 7.0, 8.0, - 9.0, 10.0, 11.0, 12.0, - 13.0, 14.0, 15.0, 16.0)); + assert_approx_eq!(c.inverse().unwrap(), + Mat4::new::( 5.0, -4.0, 1.0, 0.0, + -4.0, 8.0, -4.0, 0.0, + 4.0, -8.0, 4.0, 8.0, + -3.0, 4.0, 1.0, -8.0).mul_t(0.125)); - assert!(c.inverse().unwrap().approx_eq( - &mat4::new( 5.0, -4.0, 1.0, 0.0, - -4.0, 8.0, -4.0, 0.0, - 4.0, -8.0, 4.0, 8.0, - -3.0, 4.0, 1.0, -8.0).mul_t(0.125)) - ); - - let ident = mat4::identity(); + let ident = Mat4::identity::(); assert_eq!(ident.inverse().unwrap(), ident); @@ -481,17 +498,17 @@ fn test_mat4() { assert!(a.is_rotated()); assert!(!a.is_invertible()); - let c = mat4::new(4.0, 3.0, 2.0, 1.0, - 3.0, 4.0, 3.0, 2.0, - 2.0, 3.0, 4.0, 3.0, - 1.0, 2.0, 3.0, 4.0); + let c = Mat4::new::(4.0, 3.0, 2.0, 1.0, + 3.0, 4.0, 3.0, 2.0, + 2.0, 3.0, 4.0, 3.0, + 1.0, 2.0, 3.0, 4.0); assert!(!c.is_identity()); assert!(c.is_symmetric()); assert!(!c.is_diagonal()); assert!(c.is_rotated()); assert!(c.is_invertible()); - assert!(mat4::from_value(6.0).is_diagonal()); + assert!(Mat4::from_value::(6.0).is_diagonal()); } fn test_mat4_mut() { @@ -510,8 +527,8 @@ fn test_mat4_mut() { let f1 = 0.5; - let mut mut_a: mat4 = a; - let mut mut_c: mat4 = c; + let mut mut_a = a; + let mut mut_c = c; mut_a.swap_cols(0, 3); assert_eq!(mut_a.col(0), a.col(3)); @@ -533,16 +550,12 @@ fn test_mat4_mut() { assert_eq!(mut_a.row(2), a.row(1)); mut_a = a; - mut_a.set(&b); - assert_eq!(mut_a, b); - mut_a = a; - mut_a.to_identity(); assert!(mut_a.is_identity()); mut_a = a; mut_a.to_zero(); - assert_eq!(mut_a, mat4::zero()); + assert_eq!(mut_a, Mat4::zero::()); mut_a = a; mut_a.mul_self_t(f1); @@ -568,12 +581,14 @@ fn test_mat4_mut() { #[test] fn test_mat4_approx_eq() { - assert!(!mat4::new(0.000001, 0.000001, 0.000001, 0.000001, - 0.000001, 0.000001, 0.000001, 0.000001, - 0.000001, 0.000001, 0.000001, 0.000001, - 0.000001, 0.000001, 0.000001, 0.000001).approx_eq(&mat4::zero())); - assert!(mat4::new(0.0000001, 0.0000001, 0.0000001, 0.0000001, - 0.0000001, 0.0000001, 0.0000001, 0.0000001, - 0.0000001, 0.0000001, 0.0000001, 0.0000001, - 0.0000001, 0.0000001, 0.0000001, 0.0000001).approx_eq(&mat4::zero())); + assert!(!Mat4::new::(0.000001, 0.000001, 0.000001, 0.000001, + 0.000001, 0.000001, 0.000001, 0.000001, + 0.000001, 0.000001, 0.000001, 0.000001, + 0.000001, 0.000001, 0.000001, 0.000001) + .approx_eq(&Mat4::zero::())); + assert!(Mat4::new::(0.0000001, 0.0000001, 0.0000001, 0.0000001, + 0.0000001, 0.0000001, 0.0000001, 0.0000001, + 0.0000001, 0.0000001, 0.0000001, 0.0000001, + 0.0000001, 0.0000001, 0.0000001, 0.0000001) + .approx_eq(&Mat4::zero::())); } \ No newline at end of file diff --git a/src/test/test_quat.rs b/src/test/test_quat.rs index 673222a..83ab7f8 100644 --- a/src/test/test_quat.rs +++ b/src/test/test_quat.rs @@ -23,11 +23,11 @@ use vec::*; fn test_quat() { let a = Quat { s: 1.0, v: Vec3 { x: 2.0, y: 3.0, z: 4.0 } }; - assert_eq!(a, quat::from_sv(1.0, vec3::new(2.0, 3.0, 4.0))); - assert_eq!(a, quat::new(1.0, 2.0, 3.0, 4.0)); + assert_eq!(a, Quat::from_sv::(1.0, Vec3::new::(2.0, 3.0, 4.0))); + assert_eq!(a, Quat::new::(1.0, 2.0, 3.0, 4.0)); - assert_eq!(quat::zero(), quat::new(0.0, 0.0, 0.0, 0.0)); - assert_eq!(quat::identity(), quat::new(1.0, 0.0, 0.0, 0.0)); + assert_eq!(Quat::zero::(), Quat::new::(0.0, 0.0, 0.0, 0.0)); + assert_eq!(Quat::identity::(), Quat::new::(1.0, 0.0, 0.0, 0.0)); assert_eq!(a.s, 1.0); assert_eq!(a.v.x, 2.0); @@ -42,20 +42,22 @@ fn test_quat() { #[test] fn test_quat_2() { - let v = vec3::new(1f32, 0f32, 0f32); + let v = Vec3::new(1f32, 0f32, 0f32); - let q = quat::from_angle_axis((-45f32).to_radians(), &vec3::new(0f32, 0f32, -1f32)); + let q = Quat::from_angle_axis((-45f32).to_radians(), &Vec3::new(0f32, 0f32, -1f32)); // http://www.wolframalpha.com/input/?i={1,0}+rotate+-45+degrees - assert_approx_eq!(q.mul_v(&v), vec3::new(1f32/2f32.sqrt(), 1f32/2f32.sqrt(), 0f32)); + assert_approx_eq!(q.mul_v(&v), Vec3::new(1f32/2f32.sqrt(), 1f32/2f32.sqrt(), 0f32)); assert_eq!(q.mul_v(&v).length(), v.length()); - assert_approx_eq!(q.to_mat3(), mat3::new(1f32/2f32.sqrt(), 1f32/2f32.sqrt(), 0f32, + assert_approx_eq!(q.to_mat3(), Mat3::new( 1f32/2f32.sqrt(), 1f32/2f32.sqrt(), 0f32, -1f32/2f32.sqrt(), 1f32/2f32.sqrt(), 0f32, - 0f32, 0f32, 1f32)); + 0f32, 0f32, 1f32)); } #[test] fn test_quat_approx_eq() { - assert!(!quat::new(0.000001, 0.000001, 0.000001, 0.000001).approx_eq(&quat::new(0.0, 0.0, 0.0, 0.0))); - assert!(quat::new(0.0000001, 0.0000001, 0.0000001, 0.0000001).approx_eq(&quat::new(0.0, 0.0, 0.0, 0.0))); + assert!(!Quat::new::(0.000001, 0.000001, 0.000001, 0.000001) + .approx_eq(&Quat::new::(0.0, 0.0, 0.0, 0.0))); + assert!(Quat::new::(0.0000001, 0.0000001, 0.0000001, 0.0000001) + .approx_eq(&Quat::new::(0.0, 0.0, 0.0, 0.0))); } \ No newline at end of file diff --git a/src/test/test_vec.rs b/src/test/test_vec.rs index 94b7bd1..f2d0a87 100644 --- a/src/test/test_vec.rs +++ b/src/test/test_vec.rs @@ -19,8 +19,6 @@ use vec::*; #[test] fn test_vec2() { - // assert_eq!(vec2::dim, 2); - let a = Vec2 { x: 1.0, y: 2.0 }; let b = Vec2 { x: 3.0, y: 4.0 }; let f1 = 1.5; @@ -28,17 +26,17 @@ fn test_vec2() { let mut mut_a = a; - assert_eq!(vec2::new(1.0, 2.0), a); - assert_eq!(vec2::from_value(1.0), vec2::new(1.0, 1.0)); + assert_eq!(Vec2::new::(1.0, 2.0), a); + assert_eq!(Vec2::from_value(1.0), Vec2::new::(1.0, 1.0)); - assert_eq!(vec2::zero(), vec2::new(0.0, 0.0)); - assert_eq!(vec2::unit_x(), vec2::new(1.0, 0.0)); - assert_eq!(vec2::unit_y(), vec2::new(0.0, 1.0)); - assert_eq!(vec2::identity(), vec2::new(1.0, 1.0)); + assert_eq!(Vec2::zero(), Vec2::new::(0.0, 0.0)); + assert_eq!(Vec2::unit_x(), Vec2::new::(1.0, 0.0)); + assert_eq!(Vec2::unit_y(), Vec2::new::(0.0, 1.0)); + assert_eq!(Vec2::identity(), Vec2::new::(1.0, 1.0)); *mut_a.index_mut(0) = 42.0; *mut_a.index_mut(1) = 43.0; - assert_eq!(mut_a, vec2::new(42.0, 43.0)); + assert_eq!(mut_a, Vec2::new::(42.0, 43.0)); mut_a = a; mut_a.swap(0, 1); @@ -51,19 +49,19 @@ fn test_vec2() { assert_eq!(*a.index(0), 1.0); assert_eq!(*a.index(1), 2.0); - assert_eq!(-a, vec2::new(-1.0, -2.0)); - assert_eq!(a.neg(), vec2::new(-1.0, -2.0)); + assert_eq!(-a, Vec2::new::(-1.0, -2.0)); + assert_eq!(a.neg(), Vec2::new::(-1.0, -2.0)); - assert!(vec2::new(0.0, 0.0).is_zero()); - assert!(!vec2::new(1.0, 1.0).is_zero()); + assert!(Vec2::new::(0.0, 0.0).is_zero()); + assert!(!Vec2::new::(1.0, 1.0).is_zero()); - assert_eq!(a.mul_t(f1), vec2::new( 1.5, 3.0)); - assert_eq!(a.div_t(f2), vec2::new( 2.0, 4.0)); + assert_eq!(a.mul_t(f1), Vec2::new::( 1.5, 3.0)); + assert_eq!(a.div_t(f2), Vec2::new::( 2.0, 4.0)); - assert_eq!(a.add_v(&b), vec2::new( 4.0, 6.0)); - assert_eq!(a.sub_v(&b), vec2::new( -2.0, -2.0)); - assert_eq!(a.mul_v(&b), vec2::new( 3.0, 8.0)); - assert_eq!(a.div_v(&b), vec2::new(1.0/3.0, 2.0/4.0)); + assert_eq!(a.add_v(&b), Vec2::new::( 4.0, 6.0)); + assert_eq!(a.sub_v(&b), Vec2::new::( -2.0, -2.0)); + assert_eq!(a.mul_v(&b), Vec2::new::( 3.0, 8.0)); + assert_eq!(a.div_v(&b), Vec2::new::(1.0/3.0, 2.0/4.0)); mut_a.neg_self(); assert_eq!(mut_a, -a); @@ -91,23 +89,18 @@ fn test_vec2() { mut_a.div_self_v(&b); assert_eq!(mut_a, a.div_v(&b)); - // mut_a = a; - - // assert_eq!(c.abs(), vec2::new( 2.0, 1.0)); - // assert_eq!(c.min(&d), vec2::new(-2.0, -1.0)); - // assert_eq!(c.max(&d), vec2::new( 1.0, 0.0)); } #[test] fn test_vec2_approx_eq() { - assert!(!vec2::new(0.000001, 0.000001).approx_eq(&vec2::new(0.0, 0.0))); - assert!(vec2::new(0.0000001, 0.0000001).approx_eq(&vec2::new(0.0, 0.0))); + assert!(!Vec2::new::(0.000001, 0.000001).approx_eq(&Vec2::new::(0.0, 0.0))); + assert!(Vec2::new::(0.0000001, 0.0000001).approx_eq(&Vec2::new::(0.0, 0.0))); } #[test] fn test_vec2_euclidean() { - let a = vec2::new(5.0, 12.0); // (5, 12, 13) Pythagorean triple - let b0 = vec2::new(3.0, 4.0); // (3, 4, 5) Pythagorean triple + let a = Vec2::new::(5.0, 12.0); // (5, 12, 13) Pythagorean triple + let b0 = Vec2::new::(3.0, 4.0); // (3, 4, 5) Pythagorean triple let b = a.add_v(&b0); assert_eq!(a.length(), 13.0); @@ -119,17 +112,17 @@ fn test_vec2_euclidean() { assert_eq!(a.distance(&b), 5.0); assert_eq!(a.distance2(&b), 5.0 * 5.0); - assert!(vec2::new(1.0, 0.0).angle(&vec2::new(0.0, 1.0)).approx_eq(&Real::frac_pi_2())); - assert!(vec2::new(10.0, 0.0).angle(&vec2::new(0.0, 5.0)).approx_eq(&Real::frac_pi_2())); - assert!(vec2::new(-1.0, 0.0).angle(&vec2::new(0.0, 1.0)).approx_eq(&-Real::frac_pi_2::())); + assert!(Vec2::new::(1.0, 0.0).angle(&Vec2::new::(0.0, 1.0)).approx_eq(&Real::frac_pi_2())); + assert!(Vec2::new::(10.0, 0.0).angle(&Vec2::new::(0.0, 5.0)).approx_eq(&Real::frac_pi_2())); + assert!(Vec2::new::(-1.0, 0.0).angle(&Vec2::new::(0.0, 1.0)).approx_eq(&-Real::frac_pi_2::())); - assert!(vec2::new(3.0, 4.0).normalize().approx_eq(&vec2::new(3.0/5.0, 4.0/5.0))); + assert!(Vec2::new::(3.0, 4.0).normalize().approx_eq(&Vec2::new::(3.0/5.0, 4.0/5.0))); // TODO: test normalize_to, normalize_self, and normalize_self_to - let c = vec2::new(-2.0, -1.0); - let d = vec2::new( 1.0, 0.0); + let c = Vec2::new::(-2.0, -1.0); + let d = Vec2::new::( 1.0, 0.0); - assert_eq!(c.lerp(&d, 0.75), vec2::new(0.250, -0.250)); + assert_eq!(c.lerp(&d, 0.75), Vec2::new::(0.250, -0.250)); let mut mut_c = c; mut_c.lerp_self(&d, 0.75); @@ -138,27 +131,25 @@ fn test_vec2_euclidean() { #[test] fn test_vec2_boolean() { - let tf = bvec2::new(true, false); - let ff = bvec2::new(false, false); - let tt = bvec2::new(true, true); + let tf = Vec2::new(true, false); + let ff = Vec2::new(false, false); + let tt = Vec2::new(true, true); assert_eq!(tf.any(), true); assert_eq!(tf.all(), false); - assert_eq!(tf.not(), bvec2::new(false, true)); + assert_eq!(tf.not(), Vec2::new(false, true)); assert_eq!(ff.any(), false); assert_eq!(ff.all(), false); - assert_eq!(ff.not(), bvec2::new(true, true)); + assert_eq!(ff.not(), Vec2::new(true, true)); assert_eq!(tt.any(), true); assert_eq!(tt.all(), true); - assert_eq!(tt.not(), bvec2::new(false, false)); + assert_eq!(tt.not(), Vec2::new(false, false)); } #[test] fn test_vec3() { - // assert_eq!(Vec3::dim, 3); - let a = Vec3 { x: 1.0, y: 2.0, z: 3.0 }; let b = Vec3 { x: 4.0, y: 5.0, z: 6.0 }; let f1 = 1.5; @@ -166,19 +157,19 @@ fn test_vec3() { let mut mut_a = a; - assert_eq!(vec3::new(1.0, 2.0, 3.0), a); - assert_eq!(vec3::from_value(1.0), vec3::new(1.0, 1.0, 1.0)); + assert_eq!(Vec3::new::(1.0, 2.0, 3.0), a); + assert_eq!(Vec3::from_value(1.0), Vec3::new::(1.0, 1.0, 1.0)); - assert_eq!(vec3::zero(), vec3::new(0.0, 0.0, 0.0)); - assert_eq!(vec3::unit_x(), vec3::new(1.0, 0.0, 0.0)); - assert_eq!(vec3::unit_y(), vec3::new(0.0, 1.0, 0.0)); - assert_eq!(vec3::unit_z(), vec3::new(0.0, 0.0, 1.0)); - assert_eq!(vec3::identity(), vec3::new(1.0, 1.0, 1.0)); + assert_eq!(Vec3::zero(), Vec3::new::(0.0, 0.0, 0.0)); + assert_eq!(Vec3::unit_x(), Vec3::new::(1.0, 0.0, 0.0)); + assert_eq!(Vec3::unit_y(), Vec3::new::(0.0, 1.0, 0.0)); + assert_eq!(Vec3::unit_z(), Vec3::new::(0.0, 0.0, 1.0)); + assert_eq!(Vec3::identity(), Vec3::new::(1.0, 1.0, 1.0)); *mut_a.index_mut(0) = 42.0; *mut_a.index_mut(1) = 43.0; *mut_a.index_mut(2) = 44.0; - assert_eq!(mut_a, vec3::new(42.0, 43.0, 44.0)); + assert_eq!(mut_a, Vec3::new::(42.0, 43.0, 44.0)); mut_a = a; mut_a.swap(0, 2); @@ -198,25 +189,25 @@ fn test_vec3() { assert_eq!(*a.index(1), 2.0); assert_eq!(*a.index(2), 3.0); - assert_eq!(a.cross(&b), vec3::new(-3.0, 6.0, -3.0)); + assert_eq!(a.cross(&b), Vec3::new::(-3.0, 6.0, -3.0)); mut_a.cross_self(&b); assert_eq!(mut_a, a.cross(&b)); mut_a = a; - assert_eq!(-a, vec3::new(-1.0, -2.0, -3.0)); - assert_eq!(a.neg(), vec3::new(-1.0, -2.0, -3.0)); + assert_eq!(-a, Vec3::new::(-1.0, -2.0, -3.0)); + assert_eq!(a.neg(), Vec3::new::(-1.0, -2.0, -3.0)); - assert!(vec3::new(0.0, 0.0, 0.0).is_zero()); - assert!(!vec3::new(1.0, 1.0, 1.0).is_zero()); + assert!(Vec3::new::(0.0, 0.0, 0.0).is_zero()); + assert!(!Vec3::new::(1.0, 1.0, 1.0).is_zero()); - assert_eq!(a.mul_t(f1), vec3::new( 1.5, 3.0, 4.5)); - assert_eq!(a.div_t(f2), vec3::new( 2.0, 4.0, 6.0)); + assert_eq!(a.mul_t(f1), Vec3::new::( 1.5, 3.0, 4.5)); + assert_eq!(a.div_t(f2), Vec3::new::( 2.0, 4.0, 6.0)); - assert_eq!(a.add_v(&b), vec3::new( 5.0, 7.0, 9.0)); - assert_eq!(a.sub_v(&b), vec3::new( -3.0, -3.0, -3.0)); - assert_eq!(a.mul_v(&b), vec3::new( 4.0, 10.0, 18.0)); - assert_eq!(a.div_v(&b), vec3::new(1.0/4.0, 2.0/5.0, 3.0/6.0)); + assert_eq!(a.add_v(&b), Vec3::new::( 5.0, 7.0, 9.0)); + assert_eq!(a.sub_v(&b), Vec3::new::( -3.0, -3.0, -3.0)); + assert_eq!(a.mul_v(&b), Vec3::new::( 4.0, 10.0, 18.0)); + assert_eq!(a.div_v(&b), Vec3::new::(1.0/4.0, 2.0/5.0, 3.0/6.0)); mut_a.neg_self(); assert_eq!(mut_a, -a); @@ -244,27 +235,18 @@ fn test_vec3() { mut_a.div_self_v(&b); assert_eq!(mut_a, a.div_v(&b)); - // mut_a = a; - - // exact_eq - // approx_eq - // eq - - // assert_eq!(c.abs(), vec3::new( 2.0, 1.0, 1.0)); - // assert_eq!(c.min(&d), vec3::new(-2.0, -1.0, 0.5)); - // assert_eq!(c.max(&d), vec3::new( 1.0, 0.0, 1.0)); } #[test] fn test_vec3_approx_eq() { - assert!(!vec3::new(0.000001, 0.000001, 0.000001).approx_eq(&vec3::new(0.0, 0.0, 0.0))); - assert!(vec3::new(0.0000001, 0.0000001, 0.0000001).approx_eq(&vec3::new(0.0, 0.0, 0.0))); + assert!(!Vec3::new::(0.000001, 0.000001, 0.000001).approx_eq(&Vec3::new::(0.0, 0.0, 0.0))); + assert!(Vec3::new::(0.0000001, 0.0000001, 0.0000001).approx_eq(&Vec3::new::(0.0, 0.0, 0.0))); } #[test] fn test_vec3_euclidean() { - let a = vec3::new(2.0, 3.0, 6.0); // (2, 3, 6, 7) Pythagorean quadruple - let b0 = vec3::new(1.0, 4.0, 8.0); // (1, 4, 8, 9) Pythagorean quadruple + let a = Vec3::new::(2.0, 3.0, 6.0); // (2, 3, 6, 7) Pythagorean quadruple + let b0 = Vec3::new::(1.0, 4.0, 8.0); // (1, 4, 8, 9) Pythagorean quadruple let b = a.add_v(&b0); assert_eq!(a.length(), 7.0); @@ -276,17 +258,17 @@ fn test_vec3_euclidean() { assert_eq!(a.distance(&b), 9.0); assert_eq!(a.distance2(&b), 9.0 * 9.0); - assert!(vec3::new(1.0, 0.0, 1.0).angle(&vec3::new(1.0, 1.0, 0.0)).approx_eq(&Real::frac_pi_3())); - assert!(vec3::new(10.0, 0.0, 10.0).angle(&vec3::new(5.0, 5.0, 0.0)).approx_eq(&Real::frac_pi_3())); - assert!(vec3::new(-1.0, 0.0, -1.0).angle(&vec3::new(1.0, -1.0, 0.0)).approx_eq(&(2.0 * Real::frac_pi_3()))); + assert!(Vec3::new::(1.0, 0.0, 1.0).angle(&Vec3::new::(1.0, 1.0, 0.0)).approx_eq(&Real::frac_pi_3())); + assert!(Vec3::new::(10.0, 0.0, 10.0).angle(&Vec3::new::(5.0, 5.0, 0.0)).approx_eq(&Real::frac_pi_3())); + assert!(Vec3::new::(-1.0, 0.0, -1.0).angle(&Vec3::new::(1.0, -1.0, 0.0)).approx_eq(&(2.0 * Real::frac_pi_3()))); - assert!(vec3::new(2.0, 3.0, 6.0).normalize().approx_eq(&vec3::new(2.0/7.0, 3.0/7.0, 6.0/7.0))); + assert!(Vec3::new::(2.0, 3.0, 6.0).normalize().approx_eq(&Vec3::new::(2.0/7.0, 3.0/7.0, 6.0/7.0))); // TODO: test normalize_to, normalize_self, and normalize_self_to - let c = vec3::new(-2.0, -1.0, 1.0); - let d = vec3::new( 1.0, 0.0, 0.5); + let c = Vec3::new::(-2.0, -1.0, 1.0); + let d = Vec3::new::( 1.0, 0.0, 0.5); - assert_eq!(c.lerp(&d, 0.75), vec3::new(0.250, -0.250, 0.625)); + assert_eq!(c.lerp(&d, 0.75), Vec3::new::(0.250, -0.250, 0.625)); let mut mut_c = c; mut_c.lerp_self(&d, 0.75); @@ -295,27 +277,25 @@ fn test_vec3_euclidean() { #[test] fn test_vec3_boolean() { - let tft = bvec3::new(true, false, true); - let fff = bvec3::new(false, false, false); - let ttt = bvec3::new(true, true, true); + let tft = Vec3::new(true, false, true); + let fff = Vec3::new(false, false, false); + let ttt = Vec3::new(true, true, true); assert_eq!(tft.any(), true); assert_eq!(tft.all(), false); - assert_eq!(tft.not(), bvec3::new(false, true, false)); + assert_eq!(tft.not(), Vec3::new(false, true, false)); assert_eq!(fff.any(), false); assert_eq!(fff.all(), false); - assert_eq!(fff.not(), bvec3::new(true, true, true)); + assert_eq!(fff.not(), Vec3::new(true, true, true)); assert_eq!(ttt.any(), true); assert_eq!(ttt.all(), true); - assert_eq!(ttt.not(), bvec3::new(false, false, false)); + assert_eq!(ttt.not(), Vec3::new(false, false, false)); } #[test] fn test_vec4() { - // assert_eq!(Vec4::dim, 4); - let a = Vec4 { x: 1.0, y: 2.0, z: 3.0, w: 4.0 }; let b = Vec4 { x: 5.0, y: 6.0, z: 7.0, w: 8.0 }; let f1 = 1.5; @@ -323,14 +303,14 @@ fn test_vec4() { let mut mut_a = a; - assert_eq!(vec4::new(1.0, 2.0, 3.0, 4.0), a); - assert_eq!(vec4::from_value(1.0), vec4::new(1.0, 1.0, 1.0, 1.0)); + assert_eq!(Vec4::new::(1.0, 2.0, 3.0, 4.0), a); + assert_eq!(Vec4::from_value(1.0), Vec4::new::(1.0, 1.0, 1.0, 1.0)); *mut_a.index_mut(0) = 42.0; *mut_a.index_mut(1) = 43.0; *mut_a.index_mut(2) = 44.0; *mut_a.index_mut(3) = 45.0; - assert_eq!(mut_a, vec4::new(42.0, 43.0, 44.0, 45.0)); + assert_eq!(mut_a, Vec4::new::(42.0, 43.0, 44.0, 45.0)); mut_a = a; mut_a.swap(0, 3); @@ -343,12 +323,12 @@ fn test_vec4() { assert_eq!(*mut_a.index(2), *a.index(1)); mut_a = a; - assert_eq!(vec4::zero(), vec4::new(0.0, 0.0, 0.0, 0.0)); - assert_eq!(vec4::unit_x(), vec4::new(1.0, 0.0, 0.0, 0.0)); - assert_eq!(vec4::unit_y(), vec4::new(0.0, 1.0, 0.0, 0.0)); - assert_eq!(vec4::unit_z(), vec4::new(0.0, 0.0, 1.0, 0.0)); - assert_eq!(vec4::unit_w(), vec4::new(0.0, 0.0, 0.0, 1.0)); - assert_eq!(vec4::identity(), vec4::new(1.0, 1.0, 1.0, 1.0)); + assert_eq!(Vec4::zero(), Vec4::new::(0.0, 0.0, 0.0, 0.0)); + assert_eq!(Vec4::unit_x(), Vec4::new::(1.0, 0.0, 0.0, 0.0)); + assert_eq!(Vec4::unit_y(), Vec4::new::(0.0, 1.0, 0.0, 0.0)); + assert_eq!(Vec4::unit_z(), Vec4::new::(0.0, 0.0, 1.0, 0.0)); + assert_eq!(Vec4::unit_w(), Vec4::new::(0.0, 0.0, 0.0, 1.0)); + assert_eq!(Vec4::identity(), Vec4::new::(1.0, 1.0, 1.0, 1.0)); assert_eq!(a.x, 1.0); assert_eq!(a.y, 2.0); @@ -359,19 +339,19 @@ fn test_vec4() { assert_eq!(*a.index(2), 3.0); assert_eq!(*a.index(3), 4.0); - assert_eq!(-a, vec4::new(-1.0, -2.0, -3.0, -4.0)); - assert_eq!(a.neg(), vec4::new(-1.0, -2.0, -3.0, -4.0)); + assert_eq!(-a, Vec4::new::(-1.0, -2.0, -3.0, -4.0)); + assert_eq!(a.neg(), Vec4::new::(-1.0, -2.0, -3.0, -4.0)); - assert!(vec4::new(0.0, 0.0, 0.0, 0.0).is_zero()); - assert!(!vec4::new(1.0, 1.0, 1.0, 1.0).is_zero()); + assert!(Vec4::new::(0.0, 0.0, 0.0, 0.0).is_zero()); + assert!(!Vec4::new::(1.0, 1.0, 1.0, 1.0).is_zero()); - assert_eq!(a.mul_t(f1), vec4::new( 1.5, 3.0, 4.5, 6.0)); - assert_eq!(a.div_t(f2), vec4::new( 2.0, 4.0, 6.0, 8.0)); + assert_eq!(a.mul_t(f1), Vec4::new::( 1.5, 3.0, 4.5, 6.0)); + assert_eq!(a.div_t(f2), Vec4::new::( 2.0, 4.0, 6.0, 8.0)); - assert_eq!(a.add_v(&b), vec4::new( 6.0, 8.0, 10.0, 12.0)); - assert_eq!(a.sub_v(&b), vec4::new( -4.0, -4.0, -4.0, -4.0)); - assert_eq!(a.mul_v(&b), vec4::new( 5.0, 12.0, 21.0, 32.0)); - assert_eq!(a.div_v(&b), vec4::new(1.0/5.0, 2.0/6.0, 3.0/7.0, 4.0/8.0)); + assert_eq!(a.add_v(&b), Vec4::new::( 6.0, 8.0, 10.0, 12.0)); + assert_eq!(a.sub_v(&b), Vec4::new::( -4.0, -4.0, -4.0, -4.0)); + assert_eq!(a.mul_v(&b), Vec4::new::( 5.0, 12.0, 21.0, 32.0)); + assert_eq!(a.div_v(&b), Vec4::new::(1.0/5.0, 2.0/6.0, 3.0/7.0, 4.0/8.0)); assert_eq!(a.dot(&b), 70.0); @@ -401,23 +381,18 @@ fn test_vec4() { mut_a.div_self_v(&b); assert_eq!(mut_a, a.div_v(&b)); - // mut_a = a; - - // assert_eq!(c.abs(), vec4::new( 2.0, 1.0, 1.0, 2.0)); - // assert_eq!(c.min(&d), vec4::new(-2.0, -1.0, 0.5, 1.0)); - // assert_eq!(c.max(&d), vec4::new( 1.0, 0.0, 1.0, 2.0)); } #[test] fn test_vec4_approx_eq() { - assert!(!vec4::new(0.000001, 0.000001, 0.000001, 0.000001).approx_eq(&vec4::new(0.0, 0.0, 0.0, 0.0))); - assert!(vec4::new(0.0000001, 0.0000001, 0.0000001, 0.0000001).approx_eq(&vec4::new(0.0, 0.0, 0.0, 0.0))); + assert!(!Vec4::new::(0.000001, 0.000001, 0.000001, 0.000001).approx_eq(&Vec4::new::(0.0, 0.0, 0.0, 0.0))); + assert!(Vec4::new::(0.0000001, 0.0000001, 0.0000001, 0.0000001).approx_eq(&Vec4::new::(0.0, 0.0, 0.0, 0.0))); } #[test] fn test_vec4_euclidean() { - let a = vec4::new(1.0, 2.0, 4.0, 10.0); // (1, 2, 4, 10, 11) Pythagorean quintuple - let b0 = vec4::new(1.0, 2.0, 8.0, 10.0); // (1, 2, 8, 10, 13) Pythagorean quintuple + let a = Vec4::new::(1.0, 2.0, 4.0, 10.0); // (1, 2, 4, 10, 11) Pythagorean quintuple + let b0 = Vec4::new::(1.0, 2.0, 8.0, 10.0); // (1, 2, 8, 10, 13) Pythagorean quintuple let b = a.add_v(&b0); assert_eq!(a.length(), 11.0); @@ -429,17 +404,17 @@ fn test_vec4_euclidean() { assert_eq!(a.distance(&b), 13.0); assert_eq!(a.distance2(&b), 13.0 * 13.0); - assert!(vec4::new(1.0, 0.0, 1.0, 0.0).angle(&vec4::new(0.0, 1.0, 0.0, 1.0)).approx_eq(&Real::frac_pi_2())); - assert!(vec4::new(10.0, 0.0, 10.0, 0.0).angle(&vec4::new(0.0, 5.0, 0.0, 5.0)).approx_eq(&Real::frac_pi_2())); - assert!(vec4::new(-1.0, 0.0, -1.0, 0.0).angle(&vec4::new(0.0, 1.0, 0.0, 1.0)).approx_eq(&Real::frac_pi_2())); + assert!(Vec4::new::(1.0, 0.0, 1.0, 0.0).angle(&Vec4::new::(0.0, 1.0, 0.0, 1.0)).approx_eq(&Real::frac_pi_2())); + assert!(Vec4::new::(10.0, 0.0, 10.0, 0.0).angle(&Vec4::new::(0.0, 5.0, 0.0, 5.0)).approx_eq(&Real::frac_pi_2())); + assert!(Vec4::new::(-1.0, 0.0, -1.0, 0.0).angle(&Vec4::new::(0.0, 1.0, 0.0, 1.0)).approx_eq(&Real::frac_pi_2())); - assert!(vec4::new(1.0, 2.0, 4.0, 10.0).normalize().approx_eq(&vec4::new(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0))); + assert!(Vec4::new::(1.0, 2.0, 4.0, 10.0).normalize().approx_eq(&Vec4::new::(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0))); // TODO: test normalize_to, normalize_self, and normalize_self_to - let c = vec4::new(-2.0, -1.0, 1.0, 2.0); - let d = vec4::new( 1.0, 0.0, 0.5, 1.0); + let c = Vec4::new::(-2.0, -1.0, 1.0, 2.0); + let d = Vec4::new::( 1.0, 0.0, 0.5, 1.0); - assert_eq!(c.lerp(&d, 0.75), vec4::new(0.250, -0.250, 0.625, 1.250)); + assert_eq!(c.lerp(&d, 0.75), Vec4::new::(0.250, -0.250, 0.625, 1.250)); let mut mut_c = c; mut_c.lerp_self(&d, 0.75); @@ -448,19 +423,19 @@ fn test_vec4_euclidean() { #[test] fn test_vec4_boolean() { - let tftf = bvec4::new(true, false, true, false); - let ffff = bvec4::new(false, false, false, false); - let tttt = bvec4::new(true, true, true, true); + let tftf = Vec4::new(true, false, true, false); + let ffff = Vec4::new(false, false, false, false); + let tttt = Vec4::new(true, true, true, true); assert_eq!(tftf.any(), true); assert_eq!(tftf.all(), false); - assert_eq!(tftf.not(), bvec4::new(false, true, false, true)); + assert_eq!(tftf.not(), Vec4::new(false, true, false, true)); assert_eq!(ffff.any(), false); assert_eq!(ffff.all(), false); - assert_eq!(ffff.not(), bvec4::new(true, true, true, true)); + assert_eq!(ffff.not(), Vec4::new(true, true, true, true)); assert_eq!(tttt.any(), true); assert_eq!(tttt.all(), true); - assert_eq!(tttt.not(), bvec4::new(false, false, false, false)); + assert_eq!(tttt.not(), Vec4::new(false, false, false, false)); } \ No newline at end of file diff --git a/src/vec.rs b/src/vec.rs index fe69e88..62d76c8 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -17,596 +17,288 @@ use std::cast::transmute; use std::cmp::ApproxEq; use std::num::{Zero, One}; -use num::NumAssign; - -/// The base generic vector trait. -/// -/// # Type parameters -/// -/// - `T`: The type of the components. This is intended to support boolean, -/// integer, unsigned integer, and floating point types. -pub trait BaseVec: Eq { - /// The component of the vector at the index `i` - fn index<'a>(&'a self, i: uint) -> &'a T; - - /// Construct the vector from a single value, copying it to each component - fn from_value(value: T) -> Self; - - /// A pointer to the first component of the vector - fn to_ptr(&self) -> *T; - - /// Get a mutable reference to the component at `i` - fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T; - - /// Swap two components of the vector in place - fn swap(&mut self, a: uint, b: uint); -} - -/// A generic 2-dimensional vector -pub trait BaseVec2: BaseVec { - fn new(x: T, y: T) -> Self; -} - -/// A generic 3-dimensional vector -pub trait BaseVec3: BaseVec { - fn new(x: T, y: T, z: T) -> Self; -} - -/// A generic 4-dimensional vector -pub trait BaseVec4: BaseVec { - fn new(x: T, y: T, z: T, w: T) -> Self; -} - -/// A vector with numeric components -pub trait NumVec: BaseVec + Neg { - /// The standard basis vector - /// - /// # Return value - /// - /// A vector with each component set to one - fn identity() -> Self; - - /// The null vector - /// - /// # Return value - /// - /// A vector with each component set to zero - fn zero() -> Self; - - /// True if the vector is equal to zero - fn is_zero(&self) -> bool; - - /// The scalar multiplication of the vector and `value` - fn mul_t(&self, value: T) -> Self; - - /// The scalar division of the vector and `value` - fn div_t(&self, value: T) -> Self; - - /// Component-wise vector addition - fn add_v(&self, other: &Self) -> Self; - - /// Component-wise vector subtraction - fn sub_v(&self, other: &Self) -> Self; - - /// Component-wise vector multiplication - fn mul_v(&self, other: &Self) -> Self; - - /// Component-wise vector division - fn div_v(&self, other: &Self) -> Self; - - /// The dot product of the vector and `other` - fn dot(&self, other: &Self) -> T; - - /// Negate the vector - fn neg_self(&mut self); - - /// Multiply the vector by a scalar - fn mul_self_t(&mut self, value: T); - - /// Divide the vector by a scalar - fn div_self_t(&mut self, value: T); - - /// Set the vector to the component-wise vector sum - fn add_self_v(&mut self, other: &Self); - - /// Set the vector to the component-wise vector difference - fn sub_self_v(&mut self, other: &Self); - - /// Set the vector to the component-wise vector product - fn mul_self_v(&mut self, other: &Self); - - /// Set the vector to the component-wise vector quotient - fn div_self_v(&mut self, other: &Self); -} - -/// A 2-dimensional vector with numeric components -pub trait NumVec2: NumVec { - fn unit_x() -> Self; - fn unit_y() -> Self; - - /// The perp dot product of the vector and `other` - fn perp_dot(&self, other: &Self) -> T; -} - -/// A 3-dimensional vector with numeric components -pub trait NumVec3: NumVec { - fn unit_x() -> Self; - fn unit_y() -> Self; - fn unit_z() -> Self; - - /// The cross product of the vector and `other` - fn cross(&self, other: &Self) -> Self; - - /// Set to the cross product of the vector and `other` - fn cross_self(&mut self, other: &Self); -} - -/// A 4-dimensional vector with numeric components -pub trait NumVec4: NumVec { - fn unit_x() -> Self; - fn unit_y() -> Self; - fn unit_z() -> Self; - fn unit_w() -> Self; -} - -pub trait ToHomogeneous { - /// Convert to a homogenous coordinate - fn to_homogeneous(&self) -> H; -} - -/// A Euclidean (or Affine) vector -/// -/// # Type parameters -/// -/// - `T`: The type of the components. This should be a floating point type. -pub trait AffineVec: NumVec { - /// The squared length of the vector. This is useful for comparisons where - /// the exact length does not need to be calculated. - fn length2(&self) -> T; - - /// The length of the vector - /// - /// # Performance notes - /// - /// For instances where the exact length of the vector does not need to be - /// known, for example for quaternion-quaternion length comparisons, - /// it is advisable to use the `length2` method instead. - fn length(&self) -> T; - - /// The squared distance between the vector and `other`. - fn distance2(&self, other: &Self) -> T; - - /// The distance between the vector and `other` - fn distance(&self, other: &Self) -> T; - - /// The angle between the vector and `other` in radians - fn angle(&self, other: &Self) -> T; - - /// The normalized vector - fn normalize(&self) -> Self; - - /// Set the length of the vector whilst preserving the direction - fn normalize_to(&self, length: T) -> Self; - - /// Linearly intoperlate between the vector and `other` - /// - /// # Return value - /// - /// The intoperlated vector - fn lerp(&self, other: &Self, amount: T) -> Self; - - /// Normalize the vector - fn normalize_self(&mut self); - - /// Set the vector to a specified length whilst preserving the direction - fn normalize_self_to(&mut self, length: T); - - /// Linearly intoperlate the vector towards `other` - fn lerp_self(&mut self, other: &Self, amount: T); -} - -/// Component-wise vector comparison methods -/// -/// The methods contained in this trait correspond to the relational functions -/// mentioned in Section 8.7 of the [GLSL 4.30.6 specification] -/// (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). -pub trait OrdVec: BaseVec { - /// Component-wise compare of `self < other` - fn less_than(&self, other: &Self) -> BoolVec; - - /// Component-wise compare of `self <= other` - fn less_than_equal(&self, other: &Self) -> BoolVec; - - /// Component-wise compare of `self > other` - fn greater_than(&self, other: &Self) -> BoolVec; - - /// Component-wise compare of `self >= other` - fn greater_than_equal(&self, other: &Self) -> BoolVec; -} - -/// Component-wise equality comparison methods -/// -/// The methods contained in this trait correspond to the relational functions -/// mentioned in Section 8.7 of the [GLSL 4.30.6 specification] -/// (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). -pub trait EqVec: BaseVec { - /// Component-wise compare of `self == other` - fn equal(&self, other: &Self) -> BoolVec; - - /// Component-wise compare of `self != other` - fn not_equal(&self, other: &Self) -> BoolVec; -} - -/// A vector with boolean components -/// -/// The methods contained in this trait correspond to the relational functions -/// mentioned in Section 8.7 of the [GLSL 4.30.6 specification] -/// (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). -pub trait BoolVec: BaseVec { - /// `true` if of any component is `true` - fn any(&self) -> bool; - - /// `true` only if all components are `true` - fn all(&self) -> bool; - - /// the component-wise logical complement - fn not(&self) -> Self; -} - -pub trait TrigVec: BaseVec { - fn radians(&self) -> Self; - fn degrees(&self) -> Self; - - // Triganometric functions - fn sin(&self) -> Self; - fn cos(&self) -> Self; - fn tan(&self) -> Self; - - // Inverse triganometric functions - fn asin(&self) -> Self; - fn acos(&self) -> Self; - fn atan(&self) -> Self; - fn atan2(&self, other: Self) -> Self; - - // Hyperbolic triganometric functions - fn sinh(&self) -> Self; - fn cosh(&self) -> Self; - fn tanh(&self) -> Self; - // fn asinh() -> Self; - // fn acosh() -> Self; - // fn atanh() -> Self; -} - -pub trait ExpVec: BaseVec { - // Exponential functions - fn pow_t(&self, n: Self) -> Self; - fn pow_v(&self, n: T) -> Self; - fn exp(&self) -> Self; - fn exp2(&self) -> Self; - fn ln(&self) -> Self; - fn ln2(&self) -> Self; - fn sqrt(&self) -> Self; - fn inv_sqrt(&self) -> Self; -} - -pub trait ApproxVec: BaseVec { - // Whole-number approximation functions - fn floor(&self) -> Self; - fn trunc(&self) -> Self; - fn round(&self) -> Self; - // fn round_even(&self) -> Self; - fn ceil(&self) -> Self; - fn fract(&self) -> Self; -} - -pub trait SignedVec: BaseVec { - fn is_positive(&self) -> BV; - fn is_negative(&self) -> BV; - fn is_nonpositive(&self) -> BV; - fn is_nonnegative(&self) -> BV; - - fn abs(&self) -> Self; - fn sign(&self) -> Self; - fn copysign(&self, other: Self) -> Self; -} - -pub trait ExtentVec: BaseVec { - fn min_v(&self, other: &Self) -> Self; - fn max_v(&self, other: &Self) -> Self; - fn clamp_v(&self, mn: &Self, mx: &Self) -> Self; - - fn min_t(&self, other: T) -> Self; - fn max_t(&self, other: T) -> Self; - fn clamp_t(&self, mn: T, mx: T) -> Self; -} - -pub trait MixVec: BaseVec { - // Functions for blending numbers together - fn mix(&self, other: Self, value: Self) -> Self; - fn smooth_step(&self, edge0: Self, edge1: Self) -> Self; - fn step(&self, edge: Self) -> Self; -} - -// Utility macros - -macro_rules! zip_vec2( - ($a:ident[] $method:ident $b:ident[]) => ( - BaseVec2::new($a.index(0).$method($b.index(0)), - $a.index(1).$method($b.index(1))) - ); - ($a:ident[] $method:ident $b:ident) => ( - BaseVec2::new($a.index(0).$method(&$b), - $a.index(1).$method(&$b)) - ); -) - -macro_rules! zip_vec3( - ($a:ident[] $method:ident $b:ident[]) => ( - BaseVec3::new($a.index(0).$method($b.index(0)), - $a.index(1).$method($b.index(1)), - $a.index(2).$method($b.index(2))) - ); - ($a:ident[] $method:ident $b:ident) => ( - BaseVec3::new($a.index(0).$method(&$b), - $a.index(1).$method(&$b), - $a.index(2).$method(&$b)) - ); -) - -macro_rules! zip_vec4( - ($a:ident[] $method:ident $b:ident[]) => ( - BaseVec4::new($a.index(0).$method($b.index(0)), - $a.index(1).$method($b.index(1)), - $a.index(2).$method($b.index(2)), - $a.index(3).$method($b.index(3))) - ); - ($a:ident[] $method:ident $b:ident) => ( - BaseVec4::new($a.index(0).$method(&$b), - $a.index(1).$method(&$b), - $a.index(2).$method(&$b), - $a.index(3).$method(&$b)) - ); -) - -macro_rules! zip_assign( - ($a:ident[] $method:ident $b:ident[] ..2) => ({ $a.index_mut(0).$method($b.index(0)); $a.index_mut(1).$method($b.index(1)); }); - ($a:ident[] $method:ident $b:ident[] ..3) => ({ zip_assign!($a[] $method $b[] ..2); $a.index_mut(2).$method($b.index(2)); }); - ($a:ident[] $method:ident $b:ident[] ..4) => ({ zip_assign!($a[] $method $b[] ..3); $a.index_mut(3).$method($b.index(3)); }); - - ($a:ident[] $method:ident $b:ident ..2) => ({ $a.index_mut(0).$method(&$b); $a.index_mut(1).$method(&$b); }); - ($a:ident[] $method:ident $b:ident ..3) => ({ zip_assign!($a[] $method $b ..2); $a.index_mut(2).$method(&$b); }); - ($a:ident[] $method:ident $b:ident ..4) => ({ zip_assign!($a[] $method $b ..3); $a.index_mut(3).$method(&$b); }); -) - -/// A 2-dimensional vector -/// -/// # Type parameters -/// -/// - `T`: The type of the components. This is intended to support boolean, -/// integer, unsigned integer, and floating point types. -/// -/// # Fields -/// -/// - `x`: the first component of the vector -/// - `y`: the second component of the vector #[deriving(Eq)] pub struct Vec2 { x: T, y: T } -impl BaseVec for Vec2 { +impl Vec2 { #[inline(always)] - fn index<'a>(&'a self, i: uint) -> &'a T { - unsafe { &'a transmute::<&'a Vec2, &'a [T,..2]>(self)[i] } + pub fn index<'a>(&'a self, i: uint) -> &'a T { + &'a self.as_slice()[i] } #[inline(always)] - fn from_value(value: T) -> Vec2 { - BaseVec2::new(value, value) + pub fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { + &'a mut self.as_mut_slice()[i] } #[inline(always)] - fn to_ptr(&self) -> *T { + pub fn as_slice<'a>(&'a self) -> &'a [T,..2] { unsafe { transmute(self) } } #[inline(always)] - fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { - unsafe { &'a mut transmute::<&'a mut Vec2, &'a mut [T,..2]>(self)[i] } + pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T,..2] { + unsafe { transmute(self) } + } +} + +impl Vec2 { + #[inline(always)] + pub fn new(x: T, y: T ) -> Vec2 { + Vec2 { x: x, y: y } } #[inline(always)] - fn swap(&mut self, a: uint, b: uint) { + pub fn from_value(value: T) -> Vec2 { + Vec2::new(value, value) + } + + #[inline(always)] + pub fn swap(&mut self, a: uint, b: uint) { let tmp = *self.index(a); *self.index_mut(a) = *self.index(b); *self.index_mut(b) = tmp; } -} -impl BaseVec2 for Vec2 { #[inline(always)] - fn new(x: T, y: T ) -> Vec2 { - Vec2 { x: x, y: y } + pub fn map(&self, f: &fn(&T) -> T) -> Vec2 { + Vec2::new(f(self.index(0)), + f(self.index(1))) } } -impl NumVec for Vec2 { +impl Vec2 { #[inline(always)] - fn identity() -> Vec2 { - BaseVec2::new(One::one::(), - One::one::()) + pub fn identity() -> Vec2 { + Vec2::new(One::one::(), One::one::()) } #[inline(always)] - fn zero() -> Vec2 { - BaseVec2::new(Zero::zero::(), - Zero::zero::()) + pub fn zero() -> Vec2 { + Vec2::new(Zero::zero::(), Zero::zero::()) } #[inline(always)] - fn is_zero(&self) -> bool { + pub fn unit_x() -> Vec2 { + Vec2::new(One::one::(), Zero::zero::()) + } + + #[inline(always)] + pub fn unit_y() -> Vec2 { + Vec2::new(Zero::zero::(), One::one::()) + } + + #[inline(always)] + pub fn is_zero(&self) -> bool { *self.index(0) == Zero::zero() && *self.index(1) == Zero::zero() } #[inline(always)] - fn mul_t(&self, value: T) -> Vec2 { - zip_vec2!(self[] mul value) + pub fn add_t(&self, value: T) -> Vec2 { + Vec2::new(*self.index(0) + value, + *self.index(1) + value) } #[inline(always)] - fn div_t(&self, value: T) -> Vec2 { - zip_vec2!(self[] div value) + pub fn sub_t(&self, value: T) -> Vec2 { + Vec2::new(*self.index(0) - value, + *self.index(1) - value) } #[inline(always)] - fn add_v(&self, other: &Vec2) -> Vec2 { - zip_vec2!(self[] add other[]) + pub fn mul_t(&self, value: T) -> Vec2 { + Vec2::new(*self.index(0) * value, + *self.index(1) * value) } #[inline(always)] - fn sub_v(&self, other: &Vec2) -> Vec2 { - zip_vec2!(self[] sub other[]) + pub fn div_t(&self, value: T) -> Vec2 { + Vec2::new(*self.index(0) / value, + *self.index(1) / value) } #[inline(always)] - fn mul_v(&self, other: &Vec2) -> Vec2 { - zip_vec2!(self[] mul other[]) + pub fn rem_t(&self, value: T) -> Vec2 { + Vec2::new(*self.index(0) % value, + *self.index(1) % value) } #[inline(always)] - fn div_v(&self, other: &Vec2) -> Vec2 { - zip_vec2!(self[] div other[]) + pub fn add_v(&self, other: &Vec2) -> Vec2 { + Vec2::new(*self.index(0) + *other.index(0), + *self.index(1) + *other.index(1)) } #[inline(always)] - fn dot(&self, other: &Vec2) -> T { - (*self.index(0)) * (*other.index(0)) + - (*self.index(1)) * (*other.index(1)) + pub fn sub_v(&self, other: &Vec2) -> Vec2 { + Vec2::new(*self.index(0) - *other.index(0), + *self.index(1) - *other.index(1)) } #[inline(always)] - fn neg_self(&mut self) { - *self.index_mut(0) = -self.index(0); - *self.index_mut(1) = -self.index(1); + pub fn mul_v(&self, other: &Vec2) -> Vec2 { + Vec2::new(*self.index(0) * *other.index(0), + *self.index(1) * *other.index(1)) } #[inline(always)] - fn mul_self_t(&mut self, value: T) { - zip_assign!(self[] mul_assign value ..2); + pub fn div_v(&self, other: &Vec2) -> Vec2 { + Vec2::new(*self.index(0) / *other.index(0), + *self.index(1) / *other.index(1)) } #[inline(always)] - fn div_self_t(&mut self, value: T) { - zip_assign!(self[] div_assign value ..2); + pub fn rem_v(&self, other: &Vec2) -> Vec2 { + Vec2::new(*self.index(0) % *other.index(0), + *self.index(1) % *other.index(1)) } #[inline(always)] - fn add_self_v(&mut self, other: &Vec2) { - zip_assign!(self[] add_assign other[] ..2); + pub fn neg_self(&mut self) { + *self.index_mut(0) = -*self.index(0); + *self.index_mut(1) = -*self.index(1); } #[inline(always)] - fn sub_self_v(&mut self, other: &Vec2) { - zip_assign!(self[] sub_assign other[] ..2); + pub fn add_self_t(&mut self, value: T) { + *self.index_mut(0) += value; + *self.index_mut(1) += value; } #[inline(always)] - fn mul_self_v(&mut self, other: &Vec2) { - zip_assign!(self[] mul_assign other[] ..2); + pub fn sub_self_t(&mut self, value: T) { + *self.index_mut(0) -= value; + *self.index_mut(1) -= value; } #[inline(always)] - fn div_self_v(&mut self, other: &Vec2) { - zip_assign!(self[] div_assign other[] ..2); + pub fn mul_self_t(&mut self, value: T) { + *self.index_mut(0) *= value; + *self.index_mut(1) *= value; + } + + #[inline(always)] + pub fn div_self_t(&mut self, value: T) { + *self.index_mut(0) /= value; + *self.index_mut(1) /= value; + } + + #[inline(always)] + pub fn rem_self_t(&mut self, value: T) { + *self.index_mut(0) %= value; + *self.index_mut(1) %= value; + } + + #[inline(always)] + pub fn add_self_v(&mut self, other: &Vec2) { + *self.index_mut(0) += *other.index(0); + *self.index_mut(1) += *other.index(1); + } + + #[inline(always)] + pub fn sub_self_v(&mut self, other: &Vec2) { + *self.index_mut(0) -= *other.index(0); + *self.index_mut(1) -= *other.index(1); + } + + #[inline(always)] + pub fn mul_self_v(&mut self, other: &Vec2) { + *self.index_mut(0) *= *other.index(0); + *self.index_mut(1) *= *other.index(1); + } + + #[inline(always)] + pub fn div_self_v(&mut self, other: &Vec2) { + *self.index_mut(0) /= *other.index(0); + *self.index_mut(1) /= *other.index(1); + } + + #[inline(always)] + pub fn rem_self_v(&mut self, other: &Vec2) { + *self.index_mut(0) /= *other.index(0); + *self.index_mut(1) /= *other.index(1); + } + + #[inline(always)] + pub fn dot(&self, other: &Vec2) -> T { + *self.index(0) * *other.index(0) + + *self.index(1) * *other.index(1) + } + + #[inline(always)] + pub fn perp_dot(&self, other: &Vec2) -> T { + (*self.index(0) * *other.index(1)) - + (*self.index(1) * *other.index(0)) + } + + #[inline(always)] + pub fn to_homogeneous(&self) -> Vec3 { + Vec3::new(self.x, self.y, Zero::zero()) } } impl Neg> for Vec2 { #[inline(always)] - fn neg(&self) -> Vec2 { - BaseVec2::new(-self.index(0), -self.index(1)) + pub fn neg(&self) -> Vec2 { + Vec2::new(-self.index(0), -self.index(1)) } } -impl NumVec2 for Vec2 { +impl Vec2 { #[inline(always)] - fn unit_x() -> Vec2 { - BaseVec2::new(One::one::(), - Zero::zero::()) - } - - #[inline(always)] - fn unit_y() -> Vec2 { - BaseVec2::new(Zero::zero::(), - One::one::()) - } - - #[inline(always)] - fn perp_dot(&self, other: &Vec2) ->T { - (*self.index(0) * *other.index(1)) - (*self.index(1) * *other.index(0)) - } -} - -impl ToHomogeneous> for Vec2 { - #[inline(always)] - fn to_homogeneous(&self) -> Vec3 { - BaseVec3::new(self.x, self.y, Zero::zero()) - } -} - -impl AffineVec for Vec2 { - #[inline(always)] - fn length2(&self) -> T { + pub fn length2(&self) -> T { self.dot(self) } #[inline(always)] - fn length(&self) -> T { + pub fn length(&self) -> T { self.length2().sqrt() } #[inline(always)] - fn distance2(&self, other: &Vec2) -> T { + pub fn distance2(&self, other: &Vec2) -> T { other.sub_v(self).length2() } #[inline(always)] - fn distance(&self, other: &Vec2) -> T { + pub fn distance(&self, other: &Vec2) -> T { other.distance2(self).sqrt() } #[inline(always)] - fn angle(&self, other: &Vec2) -> T { + pub fn angle(&self, other: &Vec2) -> T { self.perp_dot(other).atan2(self.dot(other)) } #[inline(always)] - fn normalize(&self) -> Vec2 { + pub fn normalize(&self) -> Vec2 { self.mul_t(One::one::()/self.length()) } #[inline(always)] - fn normalize_to(&self, length: T) -> Vec2 { + pub fn normalize_to(&self, length: T) -> Vec2 { self.mul_t(length / self.length()) } #[inline(always)] - fn lerp(&self, other: &Vec2, amount: T) -> Vec2 { + pub fn lerp(&self, other: &Vec2, amount: T) -> Vec2 { self.add_v(&other.sub_v(self).mul_t(amount)) } #[inline(always)] - fn normalize_self(&mut self) { + pub fn normalize_self(&mut self) { let n = One::one::() / self.length(); self.mul_self_t(n); } #[inline(always)] - fn normalize_self_to(&mut self, length: T) { + pub fn normalize_self_to(&mut self, length: T) { let n = length / self.length(); self.mul_self_t(n); } - fn lerp_self(&mut self, other: &Vec2, amount: T) { + pub fn lerp_self(&mut self, other: &Vec2, amount: T) { let v = other.sub_v(self).mul_t(amount); self.add_self_v(&v); } @@ -614,85 +306,120 @@ impl AffineVec for Vec2 { impl> ApproxEq for Vec2 { #[inline(always)] - fn approx_epsilon() -> T { + pub fn approx_epsilon() -> T { ApproxEq::approx_epsilon::() } #[inline(always)] - fn approx_eq(&self, other: &Vec2) -> bool { + pub fn approx_eq(&self, other: &Vec2) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } #[inline(always)] - fn approx_eq_eps(&self, other: &Vec2, epsilon: &T) -> bool { + pub fn approx_eq_eps(&self, other: &Vec2, epsilon: &T) -> bool { self.index(0).approx_eq_eps(other.index(0), epsilon) && self.index(1).approx_eq_eps(other.index(1), epsilon) } } -impl OrdVec> for Vec2 { +impl Vec2 { #[inline(always)] - fn less_than(&self, other: &Vec2) -> Vec2 { - zip_vec2!(self[] lt other[]) + pub fn lt_t(&self, value: T) -> Vec2 { + Vec2::new(*self.index(0) < value, + *self.index(1) < value) } #[inline(always)] - fn less_than_equal(&self, other: &Vec2) -> Vec2 { - zip_vec2!(self[] le other[]) + pub fn le_t(&self, value: T) -> Vec2 { + Vec2::new(*self.index(0) <= value, + *self.index(1) <= value) } #[inline(always)] - fn greater_than(&self, other: &Vec2) -> Vec2 { - zip_vec2!(self[] gt other[]) + pub fn ge_t(&self, value: T) -> Vec2 { + Vec2::new(*self.index(0) >= value, + *self.index(1) >= value) } #[inline(always)] - fn greater_than_equal(&self, other: &Vec2) -> Vec2 { - zip_vec2!(self[] ge other[]) + pub fn gt_t(&self, value: T) -> Vec2 { + Vec2::new(*self.index(0) > value, + *self.index(1) > value) + } + + #[inline(always)] + pub fn lt_v(&self, other: &Vec2) -> Vec2 { + Vec2::new(*self.index(0) < *other.index(0), + *self.index(1) < *other.index(1)) + } + + #[inline(always)] + pub fn le_v(&self, other: &Vec2) -> Vec2 { + Vec2::new(*self.index(0) <= *other.index(0), + *self.index(1) <= *other.index(1)) + } + + #[inline(always)] + pub fn ge_v(&self, other: &Vec2) -> Vec2 { + Vec2::new(*self.index(0) >= *other.index(0), + *self.index(1) >= *other.index(1)) + } + + #[inline(always)] + pub fn gt_v(&self, other: &Vec2) -> Vec2 { + Vec2::new(*self.index(0) > *other.index(0), + *self.index(1) > *other.index(1)) } } -impl EqVec> for Vec2 { +impl Vec2 { #[inline(always)] - fn equal(&self, other: &Vec2) -> Vec2 { - zip_vec2!(self[] eq other[]) + pub fn eq_t(&self, value: T) -> Vec2 { + Vec2::new(*self.index(0) == value, + *self.index(1) == value) } #[inline(always)] - fn not_equal(&self, other: &Vec2) -> Vec2 { - zip_vec2!(self[] ne other[]) + pub fn ne_t(&self, value: T) -> Vec2 { + Vec2::new(*self.index(0) != value, + *self.index(1) != value) + } + + #[inline(always)] + pub fn eq_v(&self, other: &Vec2) -> Vec2 { + Vec2::new(*self.index(0) == *other.index(0), + *self.index(1) == *other.index(1)) + } + + #[inline(always)] + pub fn ne_v(&self, other: &Vec2) -> Vec2 { + Vec2::new(*self.index(0) != *other.index(0), + *self.index(1) != *other.index(1)) } } -impl BoolVec for Vec2 { +impl Vec2 { #[inline(always)] - fn any(&self) -> bool { + pub fn any(&self) -> bool { *self.index(0) || *self.index(1) } #[inline(always)] - fn all(&self) -> bool { + pub fn all(&self) -> bool { *self.index(0) && *self.index(1) } #[inline(always)] - fn not(&self) -> Vec2 { - BaseVec2::new(!*self.index(0), !*self.index(1)) + pub fn not(&self) -> Vec2 { + Vec2::new(!*self.index(0), !*self.index(1)) } } -// GLSL-style type aliases, corresponding to Section 4.1.5 of the [GLSL 4.30.6 specification] -// (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). - -// a two-component single-precision floating-point vector +// GLSL-style type aliases pub type vec2 = Vec2; -// a two-component double-precision floating-point vector pub type dvec2 = Vec2; -// a two-component Boolean vector pub type bvec2 = Vec2; -// a two-component signed integer vector pub type ivec2 = Vec2; -// a two-component unsigned integer vector pub type uvec2 = Vec2; // Rust-style type aliases @@ -711,257 +438,323 @@ pub type Vec2u32 = Vec2; pub type Vec2u64 = Vec2; pub type Vec2b = Vec2; -/// A 3-dimensional vector -/// -/// # Type parameters -/// -/// - `T`: The type of the components. This is intended to support boolean, -/// integer, unsigned integer, and floating point types. -/// -/// # Fields -/// -/// - `x`: the first component of the vector -/// - `y`: the second component of the vector -/// - `z`: the third component of the vector #[deriving(Eq)] pub struct Vec3 { x: T, y: T, z: T } -impl BaseVec for Vec3 { +impl Vec3 { #[inline(always)] - fn index<'a>(&'a self, i: uint) -> &'a T { - unsafe { &'a transmute::<&'a Vec3, &'a [T,..3]>(self)[i] } + pub fn index<'a>(&'a self, i: uint) -> &'a T { + &'a self.as_slice()[i] } #[inline(always)] - fn from_value(value: T) -> Vec3 { - BaseVec3::new(value, value, value) + pub fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { + &'a mut self.as_mut_slice()[i] } #[inline(always)] - fn to_ptr(&self) -> *T { + pub fn as_slice<'a>(&'a self) -> &'a [T,..3] { unsafe { transmute(self) } } #[inline(always)] - fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { - unsafe { &mut transmute::<&'a mut Vec3, &'a mut [T,..3]>(self)[i] } + pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T,..3] { + unsafe { transmute(self) } + } +} + +impl Vec3 { + #[inline(always)] + pub fn new(x: T, y: T, z: T ) -> Vec3 { + Vec3 { x: x, y: y, z: z } } #[inline(always)] - fn swap(&mut self, a: uint, b: uint) { + pub fn from_value(value: T) -> Vec3 { + Vec3::new(value, value, value) + } + + #[inline(always)] + pub fn swap(&mut self, a: uint, b: uint) { let tmp = *self.index(a); *self.index_mut(a) = *self.index(b); *self.index_mut(b) = tmp; } -} -impl BaseVec3 for Vec3 { #[inline(always)] - fn new(x: T, y: T, z: T) -> Vec3 { - Vec3 { x: x, y: y, z: z } + pub fn map(&self, f: &fn(&T) -> T) -> Vec3 { + Vec3::new(f(self.index(0)), + f(self.index(1)), + f(self.index(2))) } } -impl NumVec for Vec3 { +impl Vec3 { #[inline(always)] - fn identity() -> Vec3 { - BaseVec3::new(One::one::(), - One::one::(), - One::one::()) + pub fn identity() -> Vec3 { + Vec3::new(One::one::(), One::one::(), One::one::()) } #[inline(always)] - fn zero() -> Vec3 { - BaseVec3::new(Zero::zero::(), - Zero::zero::(), - Zero::zero::()) + pub fn zero() -> Vec3 { + Vec3::new(Zero::zero::(), Zero::zero::(), Zero::zero::()) } #[inline(always)] - fn is_zero(&self) -> bool { + pub fn unit_x() -> Vec3 { + Vec3::new(One::one::(), Zero::zero::(), Zero::zero::()) + } + + #[inline(always)] + pub fn unit_y() -> Vec3 { + Vec3::new(Zero::zero::(), One::one::(), Zero::zero::()) + } + + #[inline(always)] + pub fn unit_z() -> Vec3 { + Vec3::new(Zero::zero::(), Zero::zero::(), One::one::()) + } + + #[inline(always)] + pub fn is_zero(&self) -> bool { *self.index(0) == Zero::zero() && *self.index(1) == Zero::zero() && *self.index(2) == Zero::zero() } #[inline(always)] - fn mul_t(&self, value: T) -> Vec3 { - zip_vec3!(self[] mul value) + pub fn add_t(&self, value: T) -> Vec3 { + Vec3::new(*self.index(0) + value, + *self.index(1) + value, + *self.index(2) + value) } #[inline(always)] - fn div_t(&self, value: T) -> Vec3 { - zip_vec3!(self[] div value) + pub fn sub_t(&self, value: T) -> Vec3 { + Vec3::new(*self.index(0) - value, + *self.index(1) - value, + *self.index(2) - value) } #[inline(always)] - fn add_v(&self, other: &Vec3) -> Vec3 { - zip_vec3!(self[] add other[]) + pub fn mul_t(&self, value: T) -> Vec3 { + Vec3::new(*self.index(0) * value, + *self.index(1) * value, + *self.index(2) * value) } #[inline(always)] - fn sub_v(&self, other: &Vec3) -> Vec3 { - zip_vec3!(self[] sub other[]) + pub fn div_t(&self, value: T) -> Vec3 { + Vec3::new(*self.index(0) / value, + *self.index(1) / value, + *self.index(2) / value) } #[inline(always)] - fn mul_v(&self, other: &Vec3) -> Vec3 { - zip_vec3!(self[] mul other[]) + pub fn rem_t(&self, value: T) -> Vec3 { + Vec3::new(*self.index(0) % value, + *self.index(1) % value, + *self.index(2) % value) } #[inline(always)] - fn div_v(&self, other: &Vec3) -> Vec3 { - zip_vec3!(self[] div other[]) + pub fn add_v(&self, other: &Vec3) -> Vec3 { + Vec3::new(*self.index(0) + *other.index(0), + *self.index(1) + *other.index(1), + *self.index(2) + *other.index(2)) } #[inline(always)] - fn dot(&self, other: &Vec3) -> T { - (*self.index(0)) * (*other.index(0)) + - (*self.index(1)) * (*other.index(1)) + - (*self.index(2)) * (*other.index(2)) + pub fn sub_v(&self, other: &Vec3) -> Vec3 { + Vec3::new(*self.index(0) - *other.index(0), + *self.index(1) - *other.index(1), + *self.index(2) - *other.index(2)) } #[inline(always)] - fn neg_self(&mut self) { - *self.index_mut(0) = -self.index(0); - *self.index_mut(1) = -self.index(1); - *self.index_mut(2) = -self.index(2); + pub fn mul_v(&self, other: &Vec3) -> Vec3 { + Vec3::new(*self.index(0) * *other.index(0), + *self.index(1) * *other.index(1), + *self.index(2) * *other.index(2)) } #[inline(always)] - fn mul_self_t(&mut self, value: T) { - zip_assign!(self[] mul_assign value ..3); + pub fn div_v(&self, other: &Vec3) -> Vec3 { + Vec3::new(*self.index(0) / *other.index(0), + *self.index(1) / *other.index(1), + *self.index(2) / *other.index(2)) } #[inline(always)] - fn div_self_t(&mut self, value: T) { - zip_assign!(self[] div_assign value ..3); + pub fn rem_v(&self, other: &Vec3) -> Vec3 { + Vec3::new(*self.index(0) % *other.index(0), + *self.index(1) % *other.index(1), + *self.index(2) % *other.index(2)) } #[inline(always)] - fn add_self_v(&mut self, other: &Vec3) { - zip_assign!(self[] add_assign other[] ..3); + pub fn neg_self(&mut self) { + *self.index_mut(0) = -*self.index(0); + *self.index_mut(1) = -*self.index(1); + *self.index_mut(2) = -*self.index(2); } #[inline(always)] - fn sub_self_v(&mut self, other: &Vec3) { - zip_assign!(self[] sub_assign other[] ..3); + pub fn add_self_t(&mut self, value: T) { + *self.index_mut(0) += value; + *self.index_mut(1) += value; + *self.index_mut(2) += value; } #[inline(always)] - fn mul_self_v(&mut self, other: &Vec3) { - zip_assign!(self[] mul_assign other[] ..3); + pub fn sub_self_t(&mut self, value: T) { + *self.index_mut(0) -= value; + *self.index_mut(1) -= value; + *self.index_mut(2) -= value; } #[inline(always)] - fn div_self_v(&mut self, other: &Vec3) { - zip_assign!(self[] div_assign other[] ..3); + pub fn mul_self_t(&mut self, value: T) { + *self.index_mut(0) *= value; + *self.index_mut(1) *= value; + *self.index_mut(2) *= value; + } + + #[inline(always)] + pub fn div_self_t(&mut self, value: T) { + *self.index_mut(0) /= value; + *self.index_mut(1) /= value; + *self.index_mut(2) /= value; + } + + #[inline(always)] + pub fn rem_self_t(&mut self, value: T) { + *self.index_mut(0) %= value; + *self.index_mut(1) %= value; + *self.index_mut(2) %= value; + } + + #[inline(always)] + pub fn add_self_v(&mut self, other: &Vec3) { + *self.index_mut(0) += *other.index(0); + *self.index_mut(1) += *other.index(1); + *self.index_mut(2) += *other.index(2); + } + + #[inline(always)] + pub fn sub_self_v(&mut self, other: &Vec3) { + *self.index_mut(0) -= *other.index(0); + *self.index_mut(1) -= *other.index(1); + *self.index_mut(2) -= *other.index(2); + } + + #[inline(always)] + pub fn mul_self_v(&mut self, other: &Vec3) { + *self.index_mut(0) *= *other.index(0); + *self.index_mut(1) *= *other.index(1); + *self.index_mut(2) *= *other.index(2); + } + + #[inline(always)] + pub fn div_self_v(&mut self, other: &Vec3) { + *self.index_mut(0) /= *other.index(0); + *self.index_mut(1) /= *other.index(1); + *self.index_mut(2) /= *other.index(2); + } + + #[inline(always)] + pub fn rem_self_v(&mut self, other: &Vec3) { + *self.index_mut(0) /= *other.index(0); + *self.index_mut(1) /= *other.index(1); + *self.index_mut(2) /= *other.index(2); + } + + #[inline(always)] + pub fn dot(&self, other: &Vec3) -> T { + *self.index(0) * *other.index(0) + + *self.index(1) * *other.index(1) + + *self.index(2) * *other.index(2) + } + + #[inline(always)] + pub fn cross(&self, other: &Vec3) -> Vec3 { + Vec3::new((*self.index(1) * *other.index(2)) - (*self.index(2) * *other.index(1)), + (*self.index(2) * *other.index(0)) - (*self.index(0) * *other.index(2)), + (*self.index(0) * *other.index(1)) - (*self.index(1) * *other.index(0))) + } + + #[inline(always)] + pub fn cross_self(&mut self, other: &Vec3) { + *self = self.cross(other) + } + + #[inline(always)] + pub fn to_homogeneous(&self) -> Vec4 { + Vec4::new(self.x, self.y, self.z, Zero::zero()) } } impl Neg> for Vec3 { #[inline(always)] - fn neg(&self) -> Vec3 { - BaseVec3::new(-self.index(0), -self.index(1), -self.index(2)) + pub fn neg(&self) -> Vec3 { + Vec3::new(-self.index(0), -self.index(1), -self.index(2)) } } -impl NumVec3 for Vec3 { +impl Vec3 { #[inline(always)] - fn unit_x() -> Vec3 { - BaseVec3::new(One::one::(), - Zero::zero::(), - Zero::zero::()) - } - - #[inline(always)] - fn unit_y() -> Vec3 { - BaseVec3::new(Zero::zero::(), - One::one::(), - Zero::zero::()) - } - - #[inline(always)] - fn unit_z() -> Vec3 { - BaseVec3::new(Zero::zero::(), - Zero::zero::(), - One::one::()) - } - - #[inline(always)] - fn cross(&self, other: &Vec3) -> Vec3 { - BaseVec3::new((*self.index(1) * *other.index(2)) - (*self.index(2) * *other.index(1)), - (*self.index(2) * *other.index(0)) - (*self.index(0) * *other.index(2)), - (*self.index(0) * *other.index(1)) - (*self.index(1) * *other.index(0))) - } - - #[inline(always)] - fn cross_self(&mut self, other: &Vec3) { - *self = self.cross(other); - } -} - -impl ToHomogeneous> for Vec3 { - #[inline(always)] - fn to_homogeneous(&self) -> Vec4 { - BaseVec4::new(self.x, self.y, self.z, Zero::zero()) - } -} - -impl AffineVec for Vec3 { - #[inline(always)] - fn length2(&self) -> T { + pub fn length2(&self) -> T { self.dot(self) } #[inline(always)] - fn length(&self) -> T { + pub fn length(&self) -> T { self.length2().sqrt() } #[inline(always)] - fn distance2(&self, other: &Vec3) -> T { + pub fn distance2(&self, other: &Vec3) -> T { other.sub_v(self).length2() } #[inline(always)] - fn distance(&self, other: &Vec3) -> T { + pub fn distance(&self, other: &Vec3) -> T { other.distance2(self).sqrt() } #[inline(always)] - fn angle(&self, other: &Vec3) -> T { + pub fn angle(&self, other: &Vec3) -> T { self.cross(other).length().atan2(self.dot(other)) } #[inline(always)] - fn normalize(&self) -> Vec3 { + pub fn normalize(&self) -> Vec3 { self.mul_t(One::one::()/self.length()) } #[inline(always)] - fn normalize_to(&self, length: T) -> Vec3 { + pub fn normalize_to(&self, length: T) -> Vec3 { self.mul_t(length / self.length()) } #[inline(always)] - fn lerp(&self, other: &Vec3, amount: T) -> Vec3 { + pub fn lerp(&self, other: &Vec3, amount: T) -> Vec3 { self.add_v(&other.sub_v(self).mul_t(amount)) } #[inline(always)] - fn normalize_self(&mut self) { + pub fn normalize_self(&mut self) { let n = One::one::() / self.length(); self.mul_self_t(n); } #[inline(always)] - fn normalize_self_to(&mut self, length: T) { + pub fn normalize_self_to(&mut self, length: T) { let n = length / self.length(); self.mul_self_t(n); } - fn lerp_self(&mut self, other: &Vec3, amount: T) { + pub fn lerp_self(&mut self, other: &Vec3, amount: T) { let v = other.sub_v(self).mul_t(amount); self.add_self_v(&v); } @@ -969,86 +762,133 @@ impl AffineVec for Vec3 { impl> ApproxEq for Vec3 { #[inline(always)] - fn approx_epsilon() -> T { + pub fn approx_epsilon() -> T { ApproxEq::approx_epsilon::() } #[inline(always)] - fn approx_eq(&self, other: &Vec3) -> bool { + pub fn approx_eq(&self, other: &Vec3) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } #[inline(always)] - fn approx_eq_eps(&self, other: &Vec3, epsilon: &T) -> bool { + pub fn approx_eq_eps(&self, other: &Vec3, epsilon: &T) -> bool { self.index(0).approx_eq_eps(other.index(0), epsilon) && self.index(1).approx_eq_eps(other.index(1), epsilon) && self.index(2).approx_eq_eps(other.index(2), epsilon) } } -impl OrdVec> for Vec3 { +impl Vec3 { #[inline(always)] - fn less_than(&self, other: &Vec3) -> Vec3 { - zip_vec3!(self[] lt other[]) + pub fn lt_t(&self, value: T) -> Vec3 { + Vec3::new(*self.index(0) < value, + *self.index(1) < value, + *self.index(2) < value) } #[inline(always)] - fn less_than_equal(&self, other: &Vec3) -> Vec3 { - zip_vec3!(self[] le other[]) + pub fn le_t(&self, value: T) -> Vec3 { + Vec3::new(*self.index(0) <= value, + *self.index(1) <= value, + *self.index(2) <= value) } #[inline(always)] - fn greater_than(&self, other: &Vec3) -> Vec3 { - zip_vec3!(self[] gt other[]) + pub fn ge_t(&self, value: T) -> Vec3 { + Vec3::new(*self.index(0) >= value, + *self.index(1) >= value, + *self.index(2) >= value) } #[inline(always)] - fn greater_than_equal(&self, other: &Vec3) -> Vec3 { - zip_vec3!(self[] ge other[]) + pub fn gt_t(&self, value: T) -> Vec3 { + Vec3::new(*self.index(0) > value, + *self.index(1) > value, + *self.index(2) > value) + } + + #[inline(always)] + pub fn lt_v(&self, other: &Vec3) -> Vec3 { + Vec3::new(*self.index(0) < *other.index(0), + *self.index(1) < *other.index(1), + *self.index(2) < *other.index(2)) + } + + #[inline(always)] + pub fn le_v(&self, other: &Vec3) -> Vec3 { + Vec3::new(*self.index(0) <= *other.index(0), + *self.index(1) <= *other.index(1), + *self.index(2) <= *other.index(2)) + } + + #[inline(always)] + pub fn ge_v(&self, other: &Vec3) -> Vec3 { + Vec3::new(*self.index(0) >= *other.index(0), + *self.index(1) >= *other.index(1), + *self.index(2) >= *other.index(2)) + } + + #[inline(always)] + pub fn gt_v(&self, other: &Vec3) -> Vec3 { + Vec3::new(*self.index(0) > *other.index(0), + *self.index(1) > *other.index(1), + *self.index(2) > *other.index(2)) } } -impl EqVec> for Vec3 { +impl Vec3 { #[inline(always)] - fn equal(&self, other: &Vec3) -> Vec3 { - zip_vec3!(self[] eq other[]) + pub fn eq_t(&self, value: T) -> Vec3 { + Vec3::new(*self.index(0) == value, + *self.index(1) == value, + *self.index(2) == value) } #[inline(always)] - fn not_equal(&self, other: &Vec3) -> Vec3 { - zip_vec3!(self[] ne other[]) + pub fn ne_t(&self, value: T) -> Vec3 { + Vec3::new(*self.index(0) != value, + *self.index(1) != value, + *self.index(2) != value) + } + + #[inline(always)] + pub fn eq_v(&self, other: &Vec3) -> Vec3 { + Vec3::new(*self.index(0) == *other.index(0), + *self.index(1) == *other.index(1), + *self.index(2) == *other.index(2)) + } + + #[inline(always)] + pub fn ne_v(&self, other: &Vec3) -> Vec3 { + Vec3::new(*self.index(0) != *other.index(0), + *self.index(1) != *other.index(1), + *self.index(2) != *other.index(2)) } } -impl BoolVec for Vec3 { +impl Vec3 { #[inline(always)] - fn any(&self) -> bool { + pub fn any(&self) -> bool { *self.index(0) || *self.index(1) || *self.index(2) } #[inline(always)] - fn all(&self) -> bool { + pub fn all(&self) -> bool { *self.index(0) && *self.index(1) && *self.index(2) } #[inline(always)] - fn not(&self) -> Vec3 { - BaseVec3::new(!*self.index(0), !*self.index(1), !*self.index(2)) + pub fn not(&self) -> Vec3 { + Vec3::new(!*self.index(0), !*self.index(1), !*self.index(2)) } } -// GLSL-style type aliases, corresponding to Section 4.1.5 of the [GLSL 4.30.6 specification] -// (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). - -// a three-component single-precision floating-point vector +// GLSL-style type aliases pub type vec3 = Vec3; -// a three-component double-precision floating-point vector pub type dvec3 = Vec3; -// a three-component Boolean vector pub type bvec3 = Vec3; -// a three-component signed integer vector pub type ivec3 = Vec3; -// a three-component unsigned integer vector pub type uvec3 = Vec3; // Rust-style type aliases @@ -1067,77 +907,91 @@ pub type Vec3u32 = Vec3; pub type Vec3u64 = Vec3; pub type Vec3b = Vec3; -/// A 4-dimensional vector -/// -/// # Type parameters -/// -/// - `T`: The type of the components. This is intended to support boolean, -/// integer, unsigned integer, and floating point types. -/// -/// # Fields -/// -/// - `x`: the first component of the vector -/// - `y`: the second component of the vector -/// - `z`: the third component of the vector -/// - `w`: the fourth component of the vector #[deriving(Eq)] pub struct Vec4 { x: T, y: T, z: T, w: T } -impl BaseVec for Vec4 { +impl Vec4 { #[inline(always)] - fn index<'a>(&'a self, i: uint) -> &'a T { - unsafe { &'a transmute::<&'a Vec4, &'a [T,..4]>(self)[i] } + pub fn index<'a>(&'a self, i: uint) -> &'a T { + &'a self.as_slice()[i] } #[inline(always)] - fn from_value(value: T) -> Vec4 { - BaseVec4::new(value, value, value, value) + pub fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { + &'a mut self.as_mut_slice()[i] } #[inline(always)] - fn to_ptr(&self) -> *T { + pub fn as_slice<'a>(&'a self) -> &'a [T,..4] { unsafe { transmute(self) } } #[inline(always)] - fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { - unsafe { &'a mut transmute::< &'a mut Vec4, &'a mut [T,..4]>(self)[i] } + pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T,..4] { + unsafe { transmute(self) } + } +} + +impl Vec4 { + #[inline(always)] + pub fn new(x: T, y: T, z: T, w: T ) -> Vec4 { + Vec4 { x: x, y: y, z: z, w: w } } #[inline(always)] - fn swap(&mut self, a: uint, b: uint) { + pub fn from_value(value: T) -> Vec4 { + Vec4::new(value, value, value, value) + } + + #[inline(always)] + pub fn swap(&mut self, a: uint, b: uint) { let tmp = *self.index(a); *self.index_mut(a) = *self.index(b); *self.index_mut(b) = tmp; } -} -impl BaseVec4 for Vec4 { #[inline(always)] - fn new(x: T, y: T, z: T, w: T) -> Vec4 { - Vec4 { x: x, y: y, z: z, w: w } + pub fn map(&self, f: &fn(&T) -> T) -> Vec4 { + Vec4::new(f(self.index(0)), + f(self.index(1)), + f(self.index(2)), + f(self.index(3))) } } -impl NumVec for Vec4 { +impl Vec4 { #[inline(always)] - fn identity() -> Vec4 { - BaseVec4::new(One::one::(), - One::one::(), - One::one::(), - One::one::()) + pub fn identity() -> Vec4 { + Vec4::new(One::one::(), One::one::(), One::one::(), One::one::()) } #[inline(always)] - fn zero() -> Vec4 { - BaseVec4::new(Zero::zero::(), - Zero::zero::(), - Zero::zero::(), - Zero::zero::()) + pub fn zero() -> Vec4 { + Vec4::new(Zero::zero::(), Zero::zero::(), Zero::zero::(), Zero::zero::()) } #[inline(always)] - fn is_zero(&self) -> bool { + pub fn unit_x() -> Vec4 { + Vec4::new(One::one::(), Zero::zero::(), Zero::zero::(), Zero::zero::()) + } + + #[inline(always)] + pub fn unit_y() -> Vec4 { + Vec4::new(Zero::zero::(), One::one::(), Zero::zero::(), Zero::zero::()) + } + + #[inline(always)] + pub fn unit_z() -> Vec4 { + Vec4::new(Zero::zero::(), Zero::zero::(), One::one::(), Zero::zero::()) + } + + #[inline(always)] + pub fn unit_w() -> Vec4 { + Vec4::new(Zero::zero::(), Zero::zero::(), Zero::zero::(), One::one::()) + } + + #[inline(always)] + pub fn is_zero(&self) -> bool { *self.index(0) == Zero::zero() && *self.index(1) == Zero::zero() && *self.index(2) == Zero::zero() && @@ -1145,177 +999,243 @@ impl NumVec for Vec4 { } #[inline(always)] - fn mul_t(&self, value: T) -> Vec4 { - zip_vec4!(self[] mul value) + pub fn add_t(&self, value: T) -> Vec4 { + Vec4::new(*self.index(0) + value, + *self.index(1) + value, + *self.index(2) + value, + *self.index(3) + value) } #[inline(always)] - fn div_t(&self, value: T) -> Vec4 { - zip_vec4!(self[] div value) + pub fn sub_t(&self, value: T) -> Vec4 { + Vec4::new(*self.index(0) - value, + *self.index(1) - value, + *self.index(2) - value, + *self.index(3) - value) } #[inline(always)] - fn add_v(&self, other: &Vec4) -> Vec4 { - zip_vec4!(self[] add other[]) + pub fn mul_t(&self, value: T) -> Vec4 { + Vec4::new(*self.index(0) * value, + *self.index(1) * value, + *self.index(2) * value, + *self.index(3) * value) } #[inline(always)] - fn sub_v(&self, other: &Vec4) -> Vec4 { - zip_vec4!(self[] sub other[]) + pub fn div_t(&self, value: T) -> Vec4 { + Vec4::new(*self.index(0) / value, + *self.index(1) / value, + *self.index(2) / value, + *self.index(3) / value) } #[inline(always)] - fn mul_v(&self, other: &Vec4) -> Vec4 { - zip_vec4!(self[] mul other[]) + pub fn rem_t(&self, value: T) -> Vec4 { + Vec4::new(*self.index(0) % value, + *self.index(1) % value, + *self.index(2) % value, + *self.index(3) % value) } #[inline(always)] - fn div_v(&self, other: &Vec4) -> Vec4 { - zip_vec4!(self[] div other[]) + pub fn add_v(&self, other: &Vec4) -> Vec4 { + Vec4::new(*self.index(0) + *other.index(0), + *self.index(1) + *other.index(1), + *self.index(2) + *other.index(2), + *self.index(3) + *other.index(3)) } #[inline(always)] - fn dot(&self, other: &Vec4) -> T { - (*self.index(0)) * (*other.index(0)) + - (*self.index(1)) * (*other.index(1)) + - (*self.index(2)) * (*other.index(2)) + - (*self.index(3)) * (*other.index(3)) + pub fn sub_v(&self, other: &Vec4) -> Vec4 { + Vec4::new(*self.index(0) - *other.index(0), + *self.index(1) - *other.index(1), + *self.index(2) - *other.index(2), + *self.index(3) - *other.index(3)) } #[inline(always)] - fn neg_self(&mut self) { - *self.index_mut(0) = -self.index(0); - *self.index_mut(1) = -self.index(1); - *self.index_mut(2) = -self.index(2); - *self.index_mut(3) = -self.index(3); + pub fn mul_v(&self, other: &Vec4) -> Vec4 { + Vec4::new(*self.index(0) * *other.index(0), + *self.index(1) * *other.index(1), + *self.index(2) * *other.index(2), + *self.index(3) * *other.index(3)) } #[inline(always)] - fn mul_self_t(&mut self, value: T) { - zip_assign!(self[] mul_assign value ..4); + pub fn div_v(&self, other: &Vec4) -> Vec4 { + Vec4::new(*self.index(0) / *other.index(0), + *self.index(1) / *other.index(1), + *self.index(2) / *other.index(2), + *self.index(3) / *other.index(3)) } #[inline(always)] - fn div_self_t(&mut self, value: T) { - zip_assign!(self[] div_assign value ..4); + pub fn rem_v(&self, other: &Vec4) -> Vec4 { + Vec4::new(*self.index(0) % *other.index(0), + *self.index(1) % *other.index(1), + *self.index(2) % *other.index(2), + *self.index(3) % *other.index(3)) } #[inline(always)] - fn add_self_v(&mut self, other: &Vec4) { - zip_assign!(self[] add_assign other[] ..4); + pub fn neg_self(&mut self) { + *self.index_mut(0) = -*self.index(0); + *self.index_mut(1) = -*self.index(1); + *self.index_mut(2) = -*self.index(2); + *self.index_mut(3) = -*self.index(3); } #[inline(always)] - fn sub_self_v(&mut self, other: &Vec4) { - zip_assign!(self[] sub_assign other[] ..4); + pub fn add_self_t(&mut self, value: T) { + *self.index_mut(0) += value; + *self.index_mut(1) += value; + *self.index_mut(2) += value; + *self.index_mut(3) += value; } #[inline(always)] - fn mul_self_v(&mut self, other: &Vec4) { - zip_assign!(self[] mul_assign other[] ..4); + pub fn sub_self_t(&mut self, value: T) { + *self.index_mut(0) -= value; + *self.index_mut(1) -= value; + *self.index_mut(2) -= value; + *self.index_mut(3) -= value; } #[inline(always)] - fn div_self_v(&mut self, other: &Vec4) { - zip_assign!(self[] div_assign other[] ..4); + pub fn mul_self_t(&mut self, value: T) { + *self.index_mut(0) *= value; + *self.index_mut(1) *= value; + *self.index_mut(2) *= value; + *self.index_mut(3) *= value; + } + + #[inline(always)] + pub fn div_self_t(&mut self, value: T) { + *self.index_mut(0) /= value; + *self.index_mut(1) /= value; + *self.index_mut(2) /= value; + *self.index_mut(3) /= value; + } + + #[inline(always)] + pub fn rem_self_t(&mut self, value: T) { + *self.index_mut(0) %= value; + *self.index_mut(1) %= value; + *self.index_mut(2) %= value; + *self.index_mut(3) %= value; + } + + #[inline(always)] + pub fn add_self_v(&mut self, other: &Vec4) { + *self.index_mut(0) += *other.index(0); + *self.index_mut(1) += *other.index(1); + *self.index_mut(2) += *other.index(2); + *self.index_mut(3) += *other.index(3); + } + + #[inline(always)] + pub fn sub_self_v(&mut self, other: &Vec4) { + *self.index_mut(0) -= *other.index(0); + *self.index_mut(1) -= *other.index(1); + *self.index_mut(2) -= *other.index(2); + *self.index_mut(3) -= *other.index(3); + } + + #[inline(always)] + pub fn mul_self_v(&mut self, other: &Vec4) { + *self.index_mut(0) *= *other.index(0); + *self.index_mut(1) *= *other.index(1); + *self.index_mut(2) *= *other.index(2); + *self.index_mut(3) *= *other.index(3); + } + + #[inline(always)] + pub fn div_self_v(&mut self, other: &Vec4) { + *self.index_mut(0) /= *other.index(0); + *self.index_mut(1) /= *other.index(1); + *self.index_mut(2) /= *other.index(2); + *self.index_mut(3) /= *other.index(3); + } + + #[inline(always)] + pub fn rem_self_v(&mut self, other: &Vec4) { + *self.index_mut(0) /= *other.index(0); + *self.index_mut(1) /= *other.index(1); + *self.index_mut(2) /= *other.index(2); + *self.index_mut(3) /= *other.index(3); + } + + #[inline(always)] + pub fn dot(&self, other: &Vec4) -> T { + *self.index(0) * *other.index(0) + + *self.index(1) * *other.index(1) + + *self.index(2) * *other.index(2) + + *self.index(3) * *other.index(3) } } impl Neg> for Vec4 { #[inline(always)] - fn neg(&self) -> Vec4 { - BaseVec4::new(-self.index(0), -self.index(1), -self.index(2), -self.index(3)) + pub fn neg(&self) -> Vec4 { + Vec4::new(-self.index(0), -self.index(1), -self.index(2), -self.index(3)) } } -impl NumVec4 for Vec4 { +impl Vec4 { #[inline(always)] - fn unit_x() -> Vec4 { - BaseVec4::new(One::one::(), - Zero::zero::(), - Zero::zero::(), - Zero::zero::()) - } - - #[inline(always)] - fn unit_y() -> Vec4 { - BaseVec4::new(Zero::zero::(), - One::one::(), - Zero::zero::(), - Zero::zero::()) - } - - #[inline(always)] - fn unit_z() -> Vec4 { - BaseVec4::new(Zero::zero::(), - Zero::zero::(), - One::one::(), - Zero::zero::()) - } - - #[inline(always)] - fn unit_w() -> Vec4 { - BaseVec4::new(Zero::zero::(), - Zero::zero::(), - Zero::zero::(), - One::one::()) - } -} - -impl AffineVec for Vec4 { - #[inline(always)] - fn length2(&self) -> T { + pub fn length2(&self) -> T { self.dot(self) } #[inline(always)] - fn length(&self) -> T { + pub fn length(&self) -> T { self.length2().sqrt() } #[inline(always)] - fn distance2(&self, other: &Vec4) -> T { + pub fn distance2(&self, other: &Vec4) -> T { other.sub_v(self).length2() } #[inline(always)] - fn distance(&self, other: &Vec4) -> T { + pub fn distance(&self, other: &Vec4) -> T { other.distance2(self).sqrt() } #[inline(always)] - fn angle(&self, other: &Vec4) -> T { + pub fn angle(&self, other: &Vec4) -> T { (self.dot(other) / (self.length() * other.length())).acos() } #[inline(always)] - fn normalize(&self) -> Vec4 { + pub fn normalize(&self) -> Vec4 { self.mul_t(One::one::()/self.length()) } #[inline(always)] - fn normalize_to(&self, length: T) -> Vec4 { + pub fn normalize_to(&self, length: T) -> Vec4 { self.mul_t(length / self.length()) } #[inline(always)] - fn lerp(&self, other: &Vec4, amount: T) -> Vec4 { + pub fn lerp(&self, other: &Vec4, amount: T) -> Vec4 { self.add_v(&other.sub_v(self).mul_t(amount)) } #[inline(always)] - fn normalize_self(&mut self) { + pub fn normalize_self(&mut self) { let n = One::one::() / self.length(); self.mul_self_t(n); } #[inline(always)] - fn normalize_self_to(&mut self, length: T) { + pub fn normalize_self_to(&mut self, length: T) { let n = length / self.length(); self.mul_self_t(n); } - fn lerp_self(&mut self, other: &Vec4, amount: T) { + pub fn lerp_self(&mut self, other: &Vec4, amount: T) { let v = other.sub_v(self).mul_t(amount); self.add_self_v(&v); } @@ -1323,17 +1243,17 @@ impl AffineVec for Vec4 { impl> ApproxEq for Vec4 { #[inline(always)] - fn approx_epsilon() -> T { + pub fn approx_epsilon() -> T { ApproxEq::approx_epsilon::() } #[inline(always)] - fn approx_eq(&self, other: &Vec4) -> bool { + pub fn approx_eq(&self, other: &Vec4) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } #[inline(always)] - fn approx_eq_eps(&self, other: &Vec4, epsilon: &T) -> bool { + pub fn approx_eq_eps(&self, other: &Vec4, epsilon: &T) -> bool { self.index(0).approx_eq_eps(other.index(0), epsilon) && self.index(1).approx_eq_eps(other.index(1), epsilon) && self.index(2).approx_eq_eps(other.index(2), epsilon) && @@ -1341,69 +1261,128 @@ impl> ApproxEq for Vec4 { } } -impl OrdVec> for Vec4 { +impl Vec4 { #[inline(always)] - fn less_than(&self, other: &Vec4) -> Vec4 { - zip_vec4!(self[] lt other[]) + pub fn lt_t(&self, value: T) -> Vec4 { + Vec4::new(*self.index(0) < value, + *self.index(1) < value, + *self.index(2) < value, + *self.index(3) < value) } #[inline(always)] - fn less_than_equal(&self, other: &Vec4) -> Vec4 { - zip_vec4!(self[] le other[]) + pub fn le_t(&self, value: T) -> Vec4 { + Vec4::new(*self.index(0) <= value, + *self.index(1) <= value, + *self.index(2) <= value, + *self.index(3) <= value) } #[inline(always)] - fn greater_than(&self, other: &Vec4) -> Vec4 { - zip_vec4!(self[] gt other[]) + pub fn ge_t(&self, value: T) -> Vec4 { + Vec4::new(*self.index(0) >= value, + *self.index(1) >= value, + *self.index(2) >= value, + *self.index(3) >= value) } #[inline(always)] - fn greater_than_equal(&self, other: &Vec4) -> Vec4 { - zip_vec4!(self[] ge other[]) + pub fn gt_t(&self, value: T) -> Vec4 { + Vec4::new(*self.index(0) > value, + *self.index(1) > value, + *self.index(2) > value, + *self.index(3) > value) + } + + #[inline(always)] + pub fn lt_v(&self, other: &Vec4) -> Vec4 { + Vec4::new(*self.index(0) < *other.index(0), + *self.index(1) < *other.index(1), + *self.index(2) < *other.index(2), + *self.index(3) < *other.index(3)) + } + + #[inline(always)] + pub fn le_v(&self, other: &Vec4) -> Vec4 { + Vec4::new(*self.index(0) <= *other.index(0), + *self.index(1) <= *other.index(1), + *self.index(2) <= *other.index(2), + *self.index(3) <= *other.index(3)) + } + + #[inline(always)] + pub fn ge_v(&self, other: &Vec4) -> Vec4 { + Vec4::new(*self.index(0) >= *other.index(0), + *self.index(1) >= *other.index(1), + *self.index(2) >= *other.index(2), + *self.index(3) >= *other.index(3)) + } + + #[inline(always)] + pub fn gt_v(&self, other: &Vec4) -> Vec4 { + Vec4::new(*self.index(0) > *other.index(0), + *self.index(1) > *other.index(1), + *self.index(2) > *other.index(2), + *self.index(3) > *other.index(3)) } } -impl EqVec> for Vec4 { +impl Vec4 { #[inline(always)] - fn equal(&self, other: &Vec4) -> Vec4 { - zip_vec4!(self[] eq other[]) + pub fn eq_t(&self, value: T) -> Vec4 { + Vec4::new(*self.index(0) == value, + *self.index(1) == value, + *self.index(2) == value, + *self.index(3) == value) } #[inline(always)] - fn not_equal(&self, other: &Vec4) -> Vec4 { - zip_vec4!(self[] ne other[]) + pub fn ne_t(&self, value: T) -> Vec4 { + Vec4::new(*self.index(0) != value, + *self.index(1) != value, + *self.index(2) != value, + *self.index(3) != value) + } + + #[inline(always)] + pub fn eq_v(&self, other: &Vec4) -> Vec4 { + Vec4::new(*self.index(0) == *other.index(0), + *self.index(1) == *other.index(1), + *self.index(2) == *other.index(2), + *self.index(3) == *other.index(3)) + } + + #[inline(always)] + pub fn ne_v(&self, other: &Vec4) -> Vec4 { + Vec4::new(*self.index(0) != *other.index(0), + *self.index(1) != *other.index(1), + *self.index(2) != *other.index(2), + *self.index(3) != *other.index(3)) } } -impl BoolVec for Vec4 { +impl Vec4 { #[inline(always)] - fn any(&self) -> bool { + pub fn any(&self) -> bool { *self.index(0) || *self.index(1) || *self.index(2) || *self.index(3) } #[inline(always)] - fn all(&self) -> bool { + pub fn all(&self) -> bool { *self.index(0) && *self.index(1) && *self.index(2) && *self.index(3) } #[inline(always)] - fn not(&self) -> Vec4 { - BaseVec4::new(!*self.index(0), !*self.index(1), !*self.index(2), !*self.index(3)) + pub fn not(&self) -> Vec4 { + Vec4::new(!*self.index(0), !*self.index(1), !*self.index(2), !*self.index(3)) } } -// GLSL-style type aliases, corresponding to Section 4.1.5 of the [GLSL 4.30.6 specification] -// (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). - -// a four-component single-precision floating-point vector +// GLSL-style type aliases pub type vec4 = Vec4; -// a four-component double-precision floating-point vector pub type dvec4 = Vec4; -// a four-component Boolean vector pub type bvec4 = Vec4; -// a four-component signed integer vector pub type ivec4 = Vec4; -// a four-component unsigned integer vector pub type uvec4 = Vec4; // Rust-style type aliases