2013-06-02 02:50:00 +08:00
|
|
|
use std::num::{One, Zero};
|
|
|
|
use std::rand::{Rand, Rng, RngUtil};
|
|
|
|
use std::cmp::ApproxEq;
|
2013-05-17 05:30:39 +08:00
|
|
|
use traits::dim::Dim;
|
|
|
|
use traits::inv::Inv;
|
2013-06-29 05:03:40 +08:00
|
|
|
use traits::rotation::{Rotation, Rotate, Rotatable};
|
|
|
|
use traits::translation::{Translation, Translate, Translatable};
|
|
|
|
use traits::transformation;
|
2013-06-28 00:16:07 +08:00
|
|
|
use traits::transformation::{Transformation, Transformable};
|
2013-06-16 04:16:44 +08:00
|
|
|
use traits::rlmul::{RMul, LMul};
|
2013-06-29 19:40:31 +08:00
|
|
|
use traits::homogeneous::{ToHomogeneous, FromHomogeneous};
|
|
|
|
use traits::column::Column;
|
2013-05-17 05:30:39 +08:00
|
|
|
|
2013-07-06 06:54:42 +08:00
|
|
|
#[deriving(Eq, ToStr, Clone)]
|
2013-05-17 05:30:39 +08:00
|
|
|
pub struct Transform<M, V>
|
|
|
|
{
|
2013-05-20 03:45:30 +08:00
|
|
|
priv submat : M,
|
|
|
|
priv subtrans : V
|
2013-05-17 05:30:39 +08:00
|
|
|
}
|
|
|
|
|
2013-06-27 04:56:30 +08:00
|
|
|
impl<M, V> Transform<M, V>
|
2013-06-14 00:48:28 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-25 05:38:52 +08:00
|
|
|
pub fn new(mat: M, trans: V) -> Transform<M, V>
|
|
|
|
{ Transform { submat: mat, subtrans: trans } }
|
2013-06-14 00:48:28 +08:00
|
|
|
}
|
2013-05-17 05:30:39 +08:00
|
|
|
|
2013-06-30 02:35:01 +08:00
|
|
|
impl<M: Copy, V: Copy> Transform<M, V>
|
|
|
|
{
|
|
|
|
#[inline]
|
|
|
|
pub fn submat(&self) -> M
|
|
|
|
{ copy self.submat }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn subtrans(&self) -> V
|
|
|
|
{ copy self.subtrans }
|
|
|
|
}
|
|
|
|
|
2013-05-17 05:30:39 +08:00
|
|
|
impl<M:Dim, V> Dim for Transform<M, V>
|
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn dim() -> uint
|
|
|
|
{ Dim::dim::<M>() }
|
|
|
|
}
|
|
|
|
|
2013-06-27 04:56:30 +08:00
|
|
|
impl<M: One, V: Zero> One for Transform<M, V>
|
2013-05-17 05:30:39 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn one() -> Transform<M, V>
|
|
|
|
{ Transform { submat: One::one(), subtrans: Zero::zero() } }
|
|
|
|
}
|
|
|
|
|
2013-06-27 04:56:30 +08:00
|
|
|
impl<M: Zero, V: Zero> Zero for Transform<M, V>
|
2013-05-17 05:30:39 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn zero() -> Transform<M, V>
|
|
|
|
{ Transform { submat: Zero::zero(), subtrans: Zero::zero() } }
|
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn is_zero(&self) -> bool
|
|
|
|
{ self.submat.is_zero() && self.subtrans.is_zero() }
|
|
|
|
}
|
|
|
|
|
2013-06-27 04:56:30 +08:00
|
|
|
impl<M: RMul<V> + Mul<M, M>, V: Add<V, V>>
|
2013-05-17 05:30:39 +08:00
|
|
|
Mul<Transform<M, V>, Transform<M, V>> for Transform<M, V>
|
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn mul(&self, other: &Transform<M, V>) -> Transform<M, V>
|
|
|
|
{
|
|
|
|
Transform { submat: self.submat * other.submat,
|
|
|
|
subtrans: self.subtrans + self.submat.rmul(&other.subtrans) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-13 22:44:15 +08:00
|
|
|
impl<M: RMul<V>, V: Add<V, V>> RMul<V> for Transform<M, V>
|
2013-05-17 05:30:39 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn rmul(&self, other: &V) -> V
|
2013-06-13 22:44:15 +08:00
|
|
|
{ self.submat.rmul(other) + self.subtrans }
|
2013-05-17 05:30:39 +08:00
|
|
|
}
|
|
|
|
|
2013-06-13 22:44:15 +08:00
|
|
|
impl<M: LMul<V>, V: Add<V, V>> LMul<V> for Transform<M, V>
|
2013-05-17 05:30:39 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-17 05:30:39 +08:00
|
|
|
fn lmul(&self, other: &V) -> V
|
2013-06-13 22:44:15 +08:00
|
|
|
{ self.submat.lmul(other) + self.subtrans }
|
2013-05-17 05:30:39 +08:00
|
|
|
}
|
|
|
|
|
2013-06-28 00:16:07 +08:00
|
|
|
impl<M, V: Translation<V>> Translation<V> for Transform<M, V>
|
2013-05-19 19:44:27 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-19 19:44:27 +08:00
|
|
|
fn translation(&self) -> V
|
|
|
|
{ self.subtrans.translation() }
|
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-29 05:03:40 +08:00
|
|
|
fn inv_translation(&self) -> V
|
|
|
|
{ self.subtrans.inv_translation() }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn translate_by(&mut self, t: &V)
|
|
|
|
{ self.subtrans.translate_by(t) }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<M: Translate<V>, V, _0> Translate<V> for Transform<M, _0>
|
|
|
|
{
|
|
|
|
#[inline]
|
|
|
|
fn translate(&self, v: &V) -> V
|
|
|
|
{ self.submat.translate(v) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn inv_translate(&self, v: &V) -> V
|
|
|
|
{ self.submat.inv_translate(v) }
|
2013-05-19 19:44:27 +08:00
|
|
|
}
|
|
|
|
|
2013-06-29 20:06:39 +08:00
|
|
|
impl<M: Copy, V: Translatable<V, V> + Translation<V>>
|
|
|
|
Translatable<V, Transform<M, V>> for Transform<M, V>
|
2013-06-28 00:16:07 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-29 20:06:39 +08:00
|
|
|
fn translated(&self, t: &V) -> Transform<M, V>
|
2013-06-28 00:16:07 +08:00
|
|
|
{ Transform::new(copy self.submat, self.subtrans.translated(t)) }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<M: Rotation<AV> + RMul<V> + One,
|
2013-06-27 04:56:30 +08:00
|
|
|
V,
|
|
|
|
AV>
|
2013-06-28 00:16:07 +08:00
|
|
|
Rotation<AV> for Transform<M, V>
|
2013-05-19 19:44:27 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-09 00:33:49 +08:00
|
|
|
fn rotation(&self) -> AV
|
2013-05-19 19:44:27 +08:00
|
|
|
{ self.submat.rotation() }
|
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-29 05:03:40 +08:00
|
|
|
fn inv_rotation(&self) -> AV
|
|
|
|
{ self.submat.inv_rotation() }
|
|
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn rotate_by(&mut self, rot: &AV)
|
2013-05-19 23:01:38 +08:00
|
|
|
{
|
|
|
|
// FIXME: this does not seem opitmal
|
2013-06-28 00:16:07 +08:00
|
|
|
let mut delta = One::one::<M>();
|
2013-06-29 05:03:40 +08:00
|
|
|
delta.rotate_by(rot);
|
|
|
|
self.submat.rotate_by(rot);
|
2013-06-28 00:16:07 +08:00
|
|
|
self.subtrans = delta.rmul(&self.subtrans);
|
2013-05-19 23:01:38 +08:00
|
|
|
}
|
2013-06-28 00:16:07 +08:00
|
|
|
}
|
2013-05-19 19:44:27 +08:00
|
|
|
|
2013-06-29 05:03:40 +08:00
|
|
|
impl<M: Rotate<V>, V, _0> Rotate<V> for Transform<M, _0>
|
|
|
|
{
|
|
|
|
#[inline]
|
|
|
|
fn rotate(&self, v: &V) -> V
|
|
|
|
{ self.submat.rotate(v) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn inv_rotate(&self, v: &V) -> V
|
|
|
|
{ self.submat.inv_rotate(v) }
|
|
|
|
}
|
|
|
|
|
2013-06-28 00:16:07 +08:00
|
|
|
impl<M: Rotatable<AV, Res> + One,
|
2013-06-29 20:06:39 +08:00
|
|
|
Res: Rotation<AV> + RMul<V> + One,
|
2013-06-28 00:16:07 +08:00
|
|
|
V,
|
|
|
|
AV>
|
|
|
|
Rotatable<AV, Transform<Res, V>> for Transform<M, V>
|
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-28 00:16:07 +08:00
|
|
|
fn rotated(&self, rot: &AV) -> Transform<Res, V>
|
2013-05-19 23:01:38 +08:00
|
|
|
{
|
|
|
|
// FIXME: this does not seem opitmal
|
|
|
|
let delta = One::one::<M>().rotated(rot);
|
2013-06-28 00:16:07 +08:00
|
|
|
|
|
|
|
Transform::new(self.submat.rotated(rot), delta.rmul(&self.subtrans))
|
2013-05-19 23:01:38 +08:00
|
|
|
}
|
2013-05-19 19:44:27 +08:00
|
|
|
}
|
|
|
|
|
2013-06-29 05:03:40 +08:00
|
|
|
impl<M: Inv + RMul<V> + Mul<M, M> + Copy, V: Add<V, V> + Neg<V> + Copy>
|
|
|
|
Transformation<Transform<M, V>> for Transform<M, V>
|
2013-06-28 00:16:07 +08:00
|
|
|
{
|
|
|
|
fn transformation(&self) -> Transform<M, V>
|
|
|
|
{ copy *self }
|
|
|
|
|
2013-06-29 05:03:40 +08:00
|
|
|
fn inv_transformation(&self) -> Transform<M, V>
|
2013-07-04 22:23:08 +08:00
|
|
|
{
|
|
|
|
// FIXME: fail or return a Some<Transform<M, V>> ?
|
|
|
|
match self.inverse()
|
|
|
|
{
|
|
|
|
Some(t) => t,
|
|
|
|
None => fail!("This transformation was not inversible.")
|
|
|
|
}
|
|
|
|
}
|
2013-06-29 05:03:40 +08:00
|
|
|
|
2013-06-28 00:16:07 +08:00
|
|
|
fn transform_by(&mut self, other: &Transform<M, V>)
|
|
|
|
{ *self = other * *self; }
|
|
|
|
}
|
|
|
|
|
2013-06-29 05:03:40 +08:00
|
|
|
impl<M: transformation::Transform<V>, V: Add<V, V> + Sub<V, V>>
|
|
|
|
transformation::Transform<V> for Transform<M, V>
|
|
|
|
{
|
|
|
|
#[inline]
|
|
|
|
fn transform_vec(&self, v: &V) -> V
|
|
|
|
{ self.submat.transform_vec(v) + self.subtrans }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn inv_transform(&self, v: &V) -> V
|
|
|
|
{ self.submat.inv_transform(&(v - self.subtrans)) }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-28 00:16:07 +08:00
|
|
|
// FIXME: constraints are too restrictive.
|
|
|
|
// Should be: Transformable<M2, // Transform<Res, V> ...
|
2013-06-29 20:06:39 +08:00
|
|
|
impl<M: RMul<V> + Mul<M, M> + Inv, V: Add<V, V> + Neg<V>>
|
2013-06-28 00:16:07 +08:00
|
|
|
Transformable<Transform<M, V>, Transform<M, V>> for Transform<M, V>
|
|
|
|
{
|
|
|
|
fn transformed(&self, t: &Transform<M, V>) -> Transform<M, V>
|
|
|
|
{ t * *self }
|
|
|
|
}
|
|
|
|
|
2013-06-29 05:03:40 +08:00
|
|
|
impl<M: Copy + Inv + RMul<V>, V: Copy + Neg<V>>
|
2013-05-17 05:30:39 +08:00
|
|
|
Inv for Transform<M, V>
|
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-07-04 22:23:08 +08:00
|
|
|
fn invert(&mut self) -> bool
|
2013-05-17 05:30:39 +08:00
|
|
|
{
|
2013-07-04 22:23:08 +08:00
|
|
|
if !self.submat.invert()
|
|
|
|
{ false }
|
|
|
|
else
|
|
|
|
{
|
|
|
|
self.subtrans = self.submat.rmul(&-self.subtrans);
|
|
|
|
true
|
|
|
|
}
|
2013-05-17 05:30:39 +08:00
|
|
|
}
|
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-07-04 22:23:08 +08:00
|
|
|
fn inverse(&self) -> Option<Transform<M, V>>
|
2013-05-17 05:30:39 +08:00
|
|
|
{
|
2013-06-19 18:26:59 +08:00
|
|
|
let mut res = copy *self;
|
2013-05-17 05:30:39 +08:00
|
|
|
|
2013-07-04 22:23:08 +08:00
|
|
|
if res.invert()
|
|
|
|
{ Some(res) }
|
|
|
|
else
|
|
|
|
{ None }
|
2013-05-17 05:30:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-29 19:40:31 +08:00
|
|
|
impl<M: ToHomogeneous<M2>, M2: Dim + Column<V>, V: Copy>
|
|
|
|
ToHomogeneous<M2> for Transform<M, V>
|
|
|
|
{
|
|
|
|
fn to_homogeneous(&self) -> M2
|
|
|
|
{
|
|
|
|
let mut res = self.submat.to_homogeneous();
|
|
|
|
|
|
|
|
// copy the translation
|
|
|
|
let dim = Dim::dim::<M2>();
|
|
|
|
|
|
|
|
res.set_column(dim - 1, copy self.subtrans);
|
|
|
|
|
|
|
|
res
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<M: Column<V> + Dim, M2: FromHomogeneous<M>, V: Copy>
|
|
|
|
FromHomogeneous<M> for Transform<M2, V>
|
|
|
|
{
|
|
|
|
fn from_homogeneous(m: &M) -> Transform<M2, V>
|
|
|
|
{
|
|
|
|
Transform::new(FromHomogeneous::from_homogeneous(m),
|
|
|
|
m.column(Dim::dim::<M>() - 1))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-10 07:36:47 +08:00
|
|
|
impl<N: ApproxEq<N>, M:ApproxEq<N>, V:ApproxEq<N>>
|
|
|
|
ApproxEq<N> for Transform<M, V>
|
2013-05-17 06:23:25 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-10 07:36:47 +08:00
|
|
|
fn approx_epsilon() -> N
|
|
|
|
{ ApproxEq::approx_epsilon::<N, N>() }
|
2013-05-21 23:25:01 +08:00
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-21 23:25:01 +08:00
|
|
|
fn approx_eq(&self, other: &Transform<M, V>) -> bool
|
2013-05-17 06:23:25 +08:00
|
|
|
{
|
2013-05-21 23:25:01 +08:00
|
|
|
self.submat.approx_eq(&other.submat) &&
|
|
|
|
self.subtrans.approx_eq(&other.subtrans)
|
2013-05-17 06:23:25 +08:00
|
|
|
}
|
|
|
|
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-06-10 07:36:47 +08:00
|
|
|
fn approx_eq_eps(&self, other: &Transform<M, V>, epsilon: &N) -> bool
|
2013-05-17 06:23:25 +08:00
|
|
|
{
|
2013-05-21 23:25:01 +08:00
|
|
|
self.submat.approx_eq_eps(&other.submat, epsilon) &&
|
|
|
|
self.subtrans.approx_eq_eps(&other.subtrans, epsilon)
|
2013-05-17 06:23:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-27 04:56:30 +08:00
|
|
|
impl<M: Rand, V: Rand> Rand for Transform<M, V>
|
2013-05-18 08:11:59 +08:00
|
|
|
{
|
2013-06-28 01:40:37 +08:00
|
|
|
#[inline]
|
2013-05-21 23:25:01 +08:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> Transform<M, V>
|
2013-06-25 05:38:52 +08:00
|
|
|
{ Transform::new(rng.gen(), rng.gen()) }
|
2013-05-18 08:11:59 +08:00
|
|
|
}
|