Add `Absolute`, `Col`, `Mat`, `AbsoluteRotate` traits.

Traits like `AbsoluteRotate` and `RotationWithTranslation` have been moved to a `comp` folder
containing any trait providing operations which are combination of several traits.
This commit is contained in:
Sébastien Crozet 2013-09-13 10:26:19 +02:00
parent 00f26f8951
commit 6f81fc6d5c
14 changed files with 380 additions and 73 deletions

View File

@ -5,15 +5,18 @@ use traits::rlmul::{RMul, LMul};
use traits::cross::Cross; use traits::cross::Cross;
use traits::dim::Dim; use traits::dim::Dim;
use traits::inv::Inv; use traits::inv::Inv;
use traits::row::Row;
use traits::col::Col;
use traits::transpose::Transpose; use traits::transpose::Transpose;
use traits::rotation::{Rotation, Rotate}; use traits::absolute::Absolute;
use traits::rotation::{Rotation, Rotate, RotationMatrix};
use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable
use traits::homogeneous::ToHomogeneous; use traits::homogeneous::ToHomogeneous;
use traits::indexable::Indexable; use traits::indexable::Indexable;
use traits::norm::Norm; use traits::norm::Norm;
use vec::Vec1; use traits::comp::absolute_rotate::AbsoluteRotate;
use vec::{Vec1, Vec2, Vec3};
use mat::{Mat2, Mat3}; use mat::{Mat2, Mat3};
use vec::Vec3;
/// Matrix wrapper representing rotation matrix. It is built uppon another matrix and ensures (at /// Matrix wrapper representing rotation matrix. It is built uppon another matrix and ensures (at
/// the type-level) that it will always represent a rotation. Rotation matrices have some /// the type-level) that it will always represent a rotation. Rotation matrices have some
@ -120,6 +123,14 @@ impl<N: Clone + Num + Algebraic> Rotmat<Mat3<N>> {
} }
} }
impl<N: Trigonometric + Num + Clone>
RotationMatrix<Vec2<N>, Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>> {
#[inline]
fn to_rot_mat(&self) -> Rotmat<Mat2<N>> {
self.clone()
}
}
impl<N: Trigonometric + Num + Clone> impl<N: Trigonometric + Num + Clone>
Rotation<Vec1<N>> for Rotmat<Mat2<N>> { Rotation<Vec1<N>> for Rotmat<Mat2<N>> {
#[inline] #[inline]
@ -148,6 +159,14 @@ Rotation<Vec1<N>> for Rotmat<Mat2<N>> {
} }
} }
impl<N: NumCast + Algebraic + Trigonometric + Num + Clone>
RotationMatrix<Vec3<N>, Vec3<N>, Rotmat<Mat3<N>>> for Rotmat<Mat3<N>> {
#[inline]
fn to_rot_mat(&self) -> Rotmat<Mat3<N>> {
self.clone()
}
}
impl<N: Clone + Trigonometric + Num + Algebraic + NumCast> impl<N: Clone + Trigonometric + Num + Algebraic + NumCast>
Rotation<Vec3<N>> for Rotmat<Mat3<N>> { Rotation<Vec3<N>> for Rotmat<Mat3<N>> {
#[inline] #[inline]
@ -304,8 +323,42 @@ Transpose for Rotmat<M> {
} }
} }
impl<M: Row<R>, R> Row<R> for Rotmat<M> {
#[inline]
fn num_rows(&self) -> uint {
self.submat.num_rows()
}
#[inline]
fn row(&self, i: uint) -> R {
self.submat.row(i)
}
#[inline]
fn set_row(&mut self, i: uint, row: R) {
self.submat.set_row(i, row);
}
}
impl<M: Col<C>, C> Col<C> for Rotmat<M> {
#[inline]
fn num_cols(&self) -> uint {
self.submat.num_cols()
}
#[inline]
fn col(&self, i: uint) -> C {
self.submat.col(i)
}
#[inline]
fn set_col(&mut self, i: uint, col: C) {
self.submat.set_col(i, col);
}
}
// we loose the info that we are a rotation matrix // we loose the info that we are a rotation matrix
impl<M: ToHomogeneous<M2>, M2> ToHomogeneous<M2> for Rotmat<M> { impl<M: ToHomogeneous<M2>, M2> ToHomogeneous<M2> for Rotmat<M> {
#[inline]
fn to_homogeneous(&self) -> M2 { fn to_homogeneous(&self) -> M2 {
self.submat.to_homogeneous() self.submat.to_homogeneous()
} }
@ -328,3 +381,33 @@ impl<N: ApproxEq<N>, M: ApproxEq<N>> ApproxEq<N> for Rotmat<M> {
self.submat.approx_eq_eps(&other.submat, epsilon) self.submat.approx_eq_eps(&other.submat, epsilon)
} }
} }
impl<M: Absolute<M2>, M2> Absolute<M2> for Rotmat<M> {
#[inline]
fn absolute(&self) -> M2 {
self.submat.absolute()
}
}
impl<N: Signed> AbsoluteRotate<Vec3<N>> for Rotmat<Mat3<N>> {
#[inline]
fn absolute_rotate(&self, v: &Vec3<N>) -> Vec3<N> {
Vec3::new(
self.submat.m11.abs() * v.x + self.submat.m12.abs() * v.y + self.submat.m13.abs() * v.z,
self.submat.m21.abs() * v.x + self.submat.m22.abs() * v.y + self.submat.m23.abs() * v.z,
self.submat.m31.abs() * v.x + self.submat.m32.abs() * v.y + self.submat.m33.abs() * v.z)
}
}
impl<N: Signed> AbsoluteRotate<Vec2<N>> for Rotmat<Mat2<N>> {
#[inline]
fn absolute_rotate(&self, v: &Vec2<N>) -> Vec2<N> {
// the matrix is skew-symetric, so we dont need to compute the absolute value of every
// component.
let m11 = self.submat.m11.abs();
let m12 = self.submat.m12.abs();
let m22 = self.submat.m22.abs();
Vec2::new(m11 * v.x + m12 * v.y, m12 * v.x + m22 * v.y)
}
}

View File

@ -2,14 +2,17 @@ use std::num::{One, Zero};
use std::rand::{Rand, Rng, RngUtil}; use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq; use std::cmp::ApproxEq;
use traits::dim::Dim; use traits::dim::Dim;
use traits::absolute::Absolute;
use traits::mat::Mat;
use traits::inv::Inv; use traits::inv::Inv;
use traits::rotation::{Rotation, Rotate}; use traits::rotation::{Rotation, Rotate, RotationMatrix};
use traits::translation::{Translation, Translate}; use traits::translation::{Translation, Translate};
use Ts = traits::transformation::Transform; use Ts = traits::transformation::Transform;
use traits::transformation::{Transformation}; use traits::transformation::{Transformation};
use traits::rlmul::{RMul, LMul}; use traits::rlmul::{RMul, LMul};
use traits::homogeneous::{ToHomogeneous, FromHomogeneous}; use traits::homogeneous::{ToHomogeneous, FromHomogeneous};
use traits::column::Column; use traits::column::Column;
use traits::comp::absolute_rotate::AbsoluteRotate;
use adaptors::rotmat::Rotmat; use adaptors::rotmat::Rotmat;
use vec::Vec3; use vec::Vec3;
use mat::Mat3; use mat::Mat3;
@ -53,6 +56,14 @@ impl<V: Clone, M: Clone> Transform<V, M> {
} }
} }
impl<LV, AV, M: One + RMul<LV> + RotationMatrix<LV, AV, M2>, M2: Mat<LV, LV> + Rotation<AV>>
RotationMatrix<LV, AV, M2> for Transform<LV, M> {
#[inline]
fn to_rot_mat(&self) -> M2 {
self.submat.to_rot_mat()
}
}
impl<N: Clone + Num + Algebraic> Transform<Vec3<N>, Rotmat<Mat3<N>>> { impl<N: Clone + Num + Algebraic> Transform<Vec3<N>, Rotmat<Mat3<N>>> {
/// Reorient and translate this transformation such that its local `x` axis points to a given /// Reorient and translate this transformation such that its local `x` axis points to a given
/// direction. Note that the usually known `look_at` function does the same thing but with the /// direction. Note that the usually known `look_at` function does the same thing but with the
@ -342,3 +353,18 @@ impl<M: Rand, V: Rand> Rand for Transform<V, M> {
Transform::new(rng.gen(), rng.gen()) Transform::new(rng.gen(), rng.gen())
} }
} }
impl<V: Absolute<V2>, M: Absolute<M2>, V2, M2>
Absolute<Transform<V2, M2>> for Transform<V, M> {
#[inline]
fn absolute(&self) -> Transform<V2, M2> {
Transform::new(self.subtrans.absolute(), self.submat.absolute())
}
}
impl<V, M: AbsoluteRotate<V>> AbsoluteRotate<V> for Transform<V, M> {
#[inline]
fn absolute_rotate(&self, v: &V) -> V {
self.submat.absolute_rotate(v)
}
}

View File

@ -29,16 +29,14 @@ mod vec0_spec;
mod identity_spec; mod identity_spec;
/// Wrappers around raw matrices to restrict their behaviour. /// Wrappers around raw matrices to restrict their behaviour.
pub mod adaptors pub mod adaptors {
{
pub mod rotmat; pub mod rotmat;
pub mod transform; pub mod transform;
} }
pub mod types; pub mod types;
pub mod traits pub mod traits {
{
pub mod vector; pub mod vector;
pub mod sample; pub mod sample;
pub mod indexable; pub mod indexable;
@ -61,11 +59,21 @@ pub mod traits
pub mod mat_cast; pub mod mat_cast;
pub mod norm; pub mod norm;
pub mod dot; pub mod dot;
pub mod mat;
pub mod absolute;
pub mod col;
/// Unusual traits which are composition of other primitive traits.
/// Those are mainly shortcuts to make some operation easier to use or faster.
/// Mathematics purists should really not go in there!
pub mod comp {
pub mod rotation_with_translation;
pub mod absolute_rotate;
}
} }
#[cfg(test)] #[cfg(test)]
pub mod tests pub mod tests {
{
pub mod mat; pub mod mat;
pub mod vec; pub mod vec;
} }

View File

@ -7,6 +7,8 @@ use std::vec::{VecIterator, VecMutIterator};
use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Outer}; use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Outer};
// traits // traits
pub use traits::mat::Mat;
pub use traits::absolute::Absolute;
pub use traits::dim::Dim; pub use traits::dim::Dim;
pub use traits::indexable::Indexable; pub use traits::indexable::Indexable;
pub use traits::iterable::{Iterable, IterableMut}; pub use traits::iterable::{Iterable, IterableMut};
@ -15,12 +17,15 @@ pub use traits::mat_cast::MatCast;
pub use traits::column::Column; pub use traits::column::Column;
pub use traits::inv::Inv; pub use traits::inv::Inv;
pub use traits::rlmul::{RMul, LMul}; pub use traits::rlmul::{RMul, LMul};
pub use traits::rotation::{Rotation, Rotate, RotationWithTranslation}; pub use traits::rotation::{Rotation, RotationMatrix, Rotate};
pub use traits::transformation::{Transformation, Transform}; pub use traits::transformation::{Transformation, Transform};
pub use traits::translation::{Translation, Translate}; pub use traits::translation::{Translation, Translate};
pub use traits::transpose::{Transpose}; pub use traits::transpose::{Transpose};
pub use traits::homogeneous::{ToHomogeneous, FromHomogeneous}; pub use traits::homogeneous::{ToHomogeneous, FromHomogeneous};
pub use traits::row::Row; pub use traits::row::Row;
pub use traits::col::Col;
pub use traits::comp::rotation_with_translation::RotationWithTranslation;
pub use traits::comp::absolute_rotate::AbsoluteRotate;
// structs // structs
pub use dmat::DMat; pub use dmat::DMat;
@ -57,6 +62,7 @@ scalar_mul_impl!(Mat1, m11)
scalar_div_impl!(Mat1, m11) scalar_div_impl!(Mat1, m11)
scalar_add_impl!(Mat1, m11) scalar_add_impl!(Mat1, m11)
scalar_sub_impl!(Mat1, m11) scalar_sub_impl!(Mat1, m11)
absolute_impl!(Mat1, m11)
one_impl!(Mat1, One::one) one_impl!(Mat1, One::one)
iterable_impl!(Mat1, 1) iterable_impl!(Mat1, 1)
iterable_mut_impl!(Mat1, 1) iterable_mut_impl!(Mat1, 1)
@ -71,6 +77,7 @@ transpose_impl!(Mat1, 1)
approx_eq_impl!(Mat1) approx_eq_impl!(Mat1)
column_impl!(Mat1, Vec1, 1) column_impl!(Mat1, Vec1, 1)
row_impl!(Mat1, Vec1, 1) row_impl!(Mat1, Vec1, 1)
col_impl!(Mat1, Vec1, 1)
to_homogeneous_impl!(Mat1, Mat2, 1, 2) to_homogeneous_impl!(Mat1, Mat2, 1, 2)
from_homogeneous_impl!(Mat1, Mat2, 1, 2) from_homogeneous_impl!(Mat1, Mat2, 1, 2)
outer_impl!(Vec1, Mat1) outer_impl!(Vec1, Mat1)
@ -98,6 +105,8 @@ scalar_add_impl!(Mat2, m11, m12,
m21, m22) m21, m22)
scalar_sub_impl!(Mat2, m11, m12, scalar_sub_impl!(Mat2, m11, m12,
m21, m22) m21, m22)
absolute_impl!(Mat2, m11, m12,
m21, m22)
one_impl!(Mat2, One::one, Zero::zero, one_impl!(Mat2, One::one, Zero::zero,
Zero::zero, One::one) Zero::zero, One::one)
iterable_impl!(Mat2, 2) iterable_impl!(Mat2, 2)
@ -113,6 +122,7 @@ transpose_impl!(Mat2, 2)
approx_eq_impl!(Mat2) approx_eq_impl!(Mat2)
column_impl!(Mat2, Vec2, 2) column_impl!(Mat2, Vec2, 2)
row_impl!(Mat2, Vec2, 2) row_impl!(Mat2, Vec2, 2)
col_impl!(Mat2, Vec2, 2)
to_homogeneous_impl!(Mat2, Mat3, 2, 3) to_homogeneous_impl!(Mat2, Mat3, 2, 3)
from_homogeneous_impl!(Mat2, Mat3, 2, 3) from_homogeneous_impl!(Mat2, Mat3, 2, 3)
outer_impl!(Vec2, Mat2) outer_impl!(Vec2, Mat2)
@ -149,6 +159,9 @@ scalar_add_impl!(Mat3, m11, m12, m13,
scalar_sub_impl!(Mat3, m11, m12, m13, scalar_sub_impl!(Mat3, m11, m12, m13,
m21, m22, m23, m21, m22, m23,
m31, m32, m33) m31, m32, m33)
absolute_impl!(Mat3, m11, m12, m13,
m21, m22, m23,
m31, m32, m33)
one_impl!(Mat3, One::one , Zero::zero, Zero::zero, one_impl!(Mat3, One::one , Zero::zero, Zero::zero,
Zero::zero, One::one , Zero::zero, Zero::zero, One::one , Zero::zero,
Zero::zero, Zero::zero, One::one) Zero::zero, Zero::zero, One::one)
@ -165,6 +178,7 @@ transpose_impl!(Mat3, 3)
approx_eq_impl!(Mat3) approx_eq_impl!(Mat3)
column_impl!(Mat3, Vec3, 3) column_impl!(Mat3, Vec3, 3)
// (specialized) row_impl!(Mat3, Vec3, 3) // (specialized) row_impl!(Mat3, Vec3, 3)
// (specialized) col_impl!(Mat3, Vec3, 3)
to_homogeneous_impl!(Mat3, Mat4, 3, 4) to_homogeneous_impl!(Mat3, Mat4, 3, 4)
from_homogeneous_impl!(Mat3, Mat4, 3, 4) from_homogeneous_impl!(Mat3, Mat4, 3, 4)
outer_impl!(Vec3, Mat3) outer_impl!(Vec3, Mat3)
@ -226,6 +240,12 @@ scalar_sub_impl!(Mat4,
m31, m32, m33, m34, m31, m32, m33, m34,
m41, m42, m43, m44 m41, m42, m43, m44
) )
absolute_impl!(Mat4,
m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44
)
one_impl!(Mat4, One::one , Zero::zero, Zero::zero, Zero::zero, one_impl!(Mat4, One::one , Zero::zero, Zero::zero, Zero::zero,
Zero::zero, One::one , Zero::zero, Zero::zero, Zero::zero, One::one , Zero::zero, Zero::zero,
Zero::zero, Zero::zero, One::one , Zero::zero, Zero::zero, Zero::zero, One::one , Zero::zero,
@ -243,6 +263,7 @@ transpose_impl!(Mat4, 4)
approx_eq_impl!(Mat4) approx_eq_impl!(Mat4)
column_impl!(Mat4, Vec4, 4) column_impl!(Mat4, Vec4, 4)
row_impl!(Mat4, Vec4, 4) row_impl!(Mat4, Vec4, 4)
col_impl!(Mat4, Vec4, 4)
to_homogeneous_impl!(Mat4, Mat5, 4, 5) to_homogeneous_impl!(Mat4, Mat5, 4, 5)
from_homogeneous_impl!(Mat4, Mat5, 4, 5) from_homogeneous_impl!(Mat4, Mat5, 4, 5)
outer_impl!(Vec4, Mat4) outer_impl!(Vec4, Mat4)
@ -271,6 +292,13 @@ mat_cast_impl!(Mat5,
m41, m42, m43, m44, m45, m41, m42, m43, m44, m45,
m51, m52, m53, m54, m55 m51, m52, m53, m54, m55
) )
absolute_impl!(Mat5,
m11, m12, m13, m14, m15,
m21, m22, m23, m24, m25,
m31, m32, m33, m34, m35,
m41, m42, m43, m44, m45,
m51, m52, m53, m54, m55
)
one_impl!(Mat5, one_impl!(Mat5,
One::one , Zero::zero, Zero::zero, Zero::zero, Zero::zero, One::one , Zero::zero, 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,
@ -333,6 +361,7 @@ transpose_impl!(Mat5, 5)
approx_eq_impl!(Mat5) approx_eq_impl!(Mat5)
column_impl!(Mat5, Vec5, 5) column_impl!(Mat5, Vec5, 5)
row_impl!(Mat5, Vec5, 5) row_impl!(Mat5, Vec5, 5)
col_impl!(Mat5, Vec5, 5)
to_homogeneous_impl!(Mat5, Mat6, 5, 6) to_homogeneous_impl!(Mat5, Mat6, 5, 6)
from_homogeneous_impl!(Mat5, Mat6, 5, 6) from_homogeneous_impl!(Mat5, Mat6, 5, 6)
outer_impl!(Vec5, Mat5) outer_impl!(Vec5, Mat5)
@ -412,6 +441,14 @@ scalar_sub_impl!(Mat6,
m51, m52, m53, m54, m55, m56, m51, m52, m53, m54, m55, m56,
m61, m62, m63, m64, m65, m66 m61, m62, m63, m64, m65, m66
) )
absolute_impl!(Mat6,
m11, m12, m13, m14, m15, m16,
m21, m22, m23, m24, m25, m26,
m31, m32, m33, m34, m35, m36,
m41, m42, m43, m44, m45, m46,
m51, m52, m53, m54, m55, m56,
m61, m62, m63, m64, m65, m66
)
one_impl!(Mat6, one_impl!(Mat6,
One::one , Zero::zero, Zero::zero, Zero::zero, Zero::zero, Zero::zero, One::one , Zero::zero, Zero::zero, Zero::zero, Zero::zero, Zero::zero,
Zero::zero, One::one , Zero::zero, Zero::zero, Zero::zero, Zero::zero, Zero::zero, One::one , Zero::zero, Zero::zero, Zero::zero, Zero::zero,
@ -433,4 +470,5 @@ transpose_impl!(Mat6, 6)
approx_eq_impl!(Mat6) approx_eq_impl!(Mat6)
column_impl!(Mat6, Vec6, 6) column_impl!(Mat6, Vec6, 6)
row_impl!(Mat6, Vec6, 6) row_impl!(Mat6, Vec6, 6)
col_impl!(Mat6, Vec6, 6)
outer_impl!(Vec6, Mat6) outer_impl!(Vec6, Mat6)

View File

@ -105,6 +105,17 @@ macro_rules! scalar_sub_impl(
) )
) )
macro_rules! absolute_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Signed> Absolute<$t<N>> for $t<N> {
#[inline]
fn absolute(&self) -> $t<N> {
$t::new(self.$comp0.abs() $(, self.$compN.abs() )*)
}
}
)
)
macro_rules! iterable_impl( macro_rules! iterable_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N> Iterable<N> for $t<N> { impl<N> Iterable<N> for $t<N> {
@ -208,6 +219,11 @@ macro_rules! column_impl(
macro_rules! row_impl( macro_rules! row_impl(
($t: ident, $tv: ident, $dim: expr) => ( ($t: ident, $tv: ident, $dim: expr) => (
impl<N: Clone + Zero> Row<$tv<N>> for $t<N> { impl<N: Clone + Zero> Row<$tv<N>> for $t<N> {
#[inline]
fn num_rows(&self) -> uint {
Dim::dim(None::<$t<N>>)
}
#[inline] #[inline]
fn set_row(&mut self, row: uint, v: $tv<N>) { fn set_row(&mut self, row: uint, v: $tv<N>) {
for (i, e) in v.iter().enumerate() { for (i, e) in v.iter().enumerate() {
@ -229,6 +245,35 @@ macro_rules! row_impl(
) )
) )
macro_rules! col_impl(
($t: ident, $tv: ident, $dim: expr) => (
impl<N: Clone + Zero> Col<$tv<N>> for $t<N> {
#[inline]
fn num_cols(&self) -> uint {
Dim::dim(None::<$t<N>>)
}
#[inline]
fn set_col(&mut self, col: uint, v: $tv<N>) {
for (i, e) in v.iter().enumerate() {
self.set((col, i), e.clone());
}
}
#[inline]
fn col(&self, col: uint) -> $tv<N> {
let mut res: $tv<N> = Zero::zero();
for (i, e) in res.mut_iter().enumerate() {
*e = self.at((i, col));
}
res
}
}
)
)
macro_rules! mul_impl( macro_rules! mul_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N: Clone + Num> Mul<$t<N>, $t<N>> for $t<N> { impl<N: Clone + Num> Mul<$t<N>, $t<N>> for $t<N> {

View File

@ -1,6 +1,6 @@
use std::num::{Zero, One}; use std::num::{Zero, One};
use vec::Vec3; use vec::Vec3;
use mat::{Mat1, Mat2, Mat3, Inv, Row}; use mat::{Mat1, Mat2, Mat3, Inv, Row, Col};
use mat; use mat;
// some specializations: // some specializations:
@ -110,6 +110,11 @@ Inv for Mat3<N> {
} }
impl<N: Clone> Row<Vec3<N>> for Mat3<N> { impl<N: Clone> Row<Vec3<N>> for Mat3<N> {
#[inline]
fn num_rows(&self) -> uint {
3
}
#[inline] #[inline]
fn row(&self, i: uint) -> Vec3<N> { fn row(&self, i: uint) -> Vec3<N> {
match i { match i {
@ -144,6 +149,46 @@ impl<N: Clone> Row<Vec3<N>> for Mat3<N> {
} }
} }
impl<N: Clone> Col<Vec3<N>> for Mat3<N> {
#[inline]
fn num_cols(&self) -> uint {
3
}
#[inline]
fn col(&self, i: uint) -> Vec3<N> {
match i {
0 => Vec3::new(self.m11.clone(), self.m21.clone(), self.m31.clone()),
1 => Vec3::new(self.m12.clone(), self.m22.clone(), self.m32.clone()),
2 => Vec3::new(self.m13.clone(), self.m23.clone(), self.m33.clone()),
_ => fail!("Index out of range: 3d matrices do not have " + i.to_str() + " cols.")
}
}
#[inline]
fn set_col(&mut self, i: uint, r: Vec3<N>) {
match i {
0 => {
self.m11 = r.x.clone();
self.m21 = r.y.clone();
self.m31 = r.z;
},
1 => {
self.m12 = r.x.clone();
self.m22 = r.y.clone();
self.m32 = r.z;
},
2 => {
self.m13 = r.x.clone();
self.m23 = r.y.clone();
self.m33 = r.z;
},
_ => fail!("Index out of range: 3d matrices do not have " + i.to_str() + " cols.")
}
}
}
// FIXME: move this to another file? // FIXME: move this to another file?
impl<N: Real + NumCast + Zero + One> mat::Mat4<N> { impl<N: Real + NumCast + Zero + One> mat::Mat4<N> {
/// Computes a projection matrix given the frustrum near plane width, height, the field of /// Computes a projection matrix given the frustrum near plane width, height, the field of

7
src/traits/absolute.rs Normal file
View File

@ -0,0 +1,7 @@
/// Trait of objects having an absolute value.
/// This is useful of the object and the absolute value do not have the same type.
pub trait Absolute<A> {
/// Compute some absolute representation of this object.
/// Typically, this will make all component of a matrix or vector positive.
fn absolute(&self) -> A;
}

9
src/traits/col.rs Normal file
View File

@ -0,0 +1,9 @@
/// Traits to access columns of a matrix or vector.
pub trait Col<C> {
/// The number of columun of this matrix or vector.
fn num_cols(&self) -> uint;
/// Reads the `i`-th column of `self`.
fn col(&self, i: uint) -> C;
/// Writes the `i`-th column of `self`.
fn set_col(&mut self, i: uint, C);
}

View File

@ -0,0 +1,16 @@
/// Trait of matrices having the following operation:
///
/// self.absolute_rotate(v) = self.rotation_matrix().absolute().rmul(v)
///
/// The operation is accessible using the `RotationMatrix`, `Absolute`, and `RMul` traits, but
/// doing so is not easy in generic code as it can be a cause of type over-parametrization.
///
/// # Known use case:
/// * to compute efficiently the AABB of a rotated AABB.
pub trait AbsoluteRotate<V> {
/// This is the same as:
///
/// self.absolute_rotate(v) = self.rotation_matrix().absolute().rmul(v)
fn absolute_rotate(&self, &V) -> V;
}

View File

@ -0,0 +1,70 @@
use traits::rotation::Rotation;
use traits::translation::Translation;
// NOTE: we cannot call this an Isometry since an isometry really does not need to have a rotation
// nor a translation (this can be a reflexion).
/// Utilities to make rotations with regard to a point different than the origin.
/// All those operations are the composition of rotations and translations.
/// This could be implemented in term of the `Rotation` and `Translation` traits, but having those
/// here make it easier to use.
///
/// # Known use case:
/// * to change the center of a rotation.
pub trait RotationWithTranslation<LV: Neg<LV>, AV>: Rotation<AV> + Translation<LV> {
/**
* Applies a rotation centered on a specific point.
*
* - `m`: the object to be rotated.
* - `ammount`: the rotation to apply.
* - `point`: the center of rotation.
*/
#[inline]
fn rotated_wrt_point(&self, ammount: &AV, center: &LV) -> Self {
let mut res = self.translated(&-center);
res.rotate_by(ammount);
res.translate_by(center);
res
}
/// Rotates an object using a specific center of rotation.
///
/// # Arguments
/// * `m` - the object to be rotated
/// * `ammount` - the rotation to be applied
/// * `center` - the new center of rotation
#[inline]
fn rotate_wrt_point(&mut self, ammount: &AV, center: &LV) {
self.translate_by(&-center);
self.rotate_by(ammount);
self.translate_by(center);
}
/**
* Applies a rotation centered on the input translation.
*
* # Arguments
* * `m` - the object to be rotated.
* * `ammount` - the rotation to apply.
*/
#[inline]
fn rotated_wrt_center(&self, ammount: &AV) -> Self {
self.rotated_wrt_point(ammount, &self.translation())
}
/**
* Applies a rotation centered on the input translation.
*
* # Arguments
* * `m` - the object to be rotated.
* * `ammount` - the rotation to apply.
*/
#[inline]
fn rotate_wrt_center(&mut self, ammount: &AV) {
let center = self.translation();
self.rotate_wrt_point(ammount, &center)
}
}
impl<LV: Neg<LV>, AV, M: Rotation<AV> + Translation<LV>> RotationWithTranslation<LV, AV> for M;

8
src/traits/mat.rs Normal file
View File

@ -0,0 +1,8 @@
use traits::row::Row;
use traits::col::Col;
use traits::rlmul::{RMul, LMul};
/// Trait of matrix. A matrix must have lines and columns.
pub trait Mat<R, C> : Row<R> + Col<C> + RMul<R> + LMul<C> { }
impl<M: Row<R> + Col<C> + RMul<R> + LMul<C>, R, C> Mat<R, C> for M;

View File

@ -1,4 +1,4 @@
use traits::translation::Translation; use traits::mat::Mat;
/// Trait of object which represent a rotation, and to wich new rotations can /// Trait of object which represent a rotation, and to wich new rotations can
/// be appended. A rotation is assumed to be an isomitry without translation /// be appended. A rotation is assumed to be an isomitry without translation
@ -29,64 +29,9 @@ pub trait Rotate<V> {
fn inv_rotate(&self, &V) -> V; fn inv_rotate(&self, &V) -> V;
} }
/// Utilities to make rotations with regard to a point different than the origin. /// Trait of transformation having a rotation extractable as a rotation matrix. This can typically
// NOTE: we cannot call this an Isometry since an isometry really does not need to have a rotation /// be implemented by quaternions to convert them
// nor a translation (this can be a reflexion). pub trait RotationMatrix<LV, AV, R: Mat<LV, LV> + Rotation<AV>> : Rotation<AV> {
pub trait RotationWithTranslation<LV: Neg<LV>, AV>: Rotation<AV> + Translation<LV> { /// Gets the rotation matrix from this object.
/** fn to_rot_mat(&self) -> R;
* Applies a rotation centered on a specific point.
*
* - `m`: the object to be rotated.
* - `ammount`: the rotation to apply.
* - `point`: the center of rotation.
*/
#[inline]
fn rotated_wrt_point(&self, ammount: &AV, center: &LV) -> Self {
let mut res = self.translated(&-center);
res.rotate_by(ammount);
res.translate_by(center);
res
}
/// Rotates an object using a specific center of rotation.
///
/// # Arguments
/// * `m` - the object to be rotated
/// * `ammount` - the rotation to be applied
/// * `center` - the new center of rotation
#[inline]
fn rotate_wrt_point(&mut self, ammount: &AV, center: &LV) {
self.translate_by(&-center);
self.rotate_by(ammount);
self.translate_by(center);
}
/**
* Applies a rotation centered on the input translation.
*
* # Arguments
* * `m` - the object to be rotated.
* * `ammount` - the rotation to apply.
*/
#[inline]
fn rotated_wrt_center(&self, ammount: &AV) -> Self {
self.rotated_wrt_point(ammount, &self.translation())
}
/**
* Applies a rotation centered on the input translation.
*
* # Arguments
* * `m` - the object to be rotated.
* * `ammount` - the rotation to apply.
*/
#[inline]
fn rotate_wrt_center(&mut self, ammount: &AV) {
let center = self.translation();
self.rotate_wrt_point(ammount, &center)
}
} }
impl<LV: Neg<LV>, AV, M: Rotation<AV> + Translation<LV>> RotationWithTranslation<LV, AV> for M;

View File

@ -1,5 +1,7 @@
/// Traits to access rows of a matrix or vector. /// Traits to access rows of a matrix or vector.
pub trait Row<R> { pub trait Row<R> {
/// The number of columun of this matrix or vector.
fn num_rows(&self) -> uint;
/// Reads the `i`-th row of `self`. /// Reads the `i`-th row of `self`.
fn row(&self, i: uint) -> R; fn row(&self, i: uint) -> R;
/// Writes the `i`-th row of `self`. /// Writes the `i`-th row of `self`.

View File

@ -41,6 +41,11 @@ impl<N: Neg<N> + Zero + Clone> CrossMatrix<Mat3<N>> for Vec3<N> {
// FIXME: iplement this for all other vectors // FIXME: iplement this for all other vectors
impl<N: Clone> Row<Vec1<N>> for Vec2<N> { impl<N: Clone> Row<Vec1<N>> for Vec2<N> {
#[inline]
fn num_rows(&self) -> uint {
2
}
#[inline] #[inline]
fn row(&self, i: uint) -> Vec1<N> { fn row(&self, i: uint) -> Vec1<N> {
match i { match i {