Redesigned ToComponents, removed the implementation for AffineMatrix3 as incorrect.
This commit is contained in:
parent
bb8c91213a
commit
f03d4427ee
2 changed files with 67 additions and 68 deletions
112
src/transform.rs
112
src/transform.rs
|
@ -17,13 +17,12 @@ use std::fmt;
|
||||||
|
|
||||||
use approx::ApproxEq;
|
use approx::ApproxEq;
|
||||||
use matrix::*;
|
use matrix::*;
|
||||||
use num::{BaseNum, BaseFloat, zero, one};
|
use num::*;
|
||||||
use point::{Point, Point3};
|
use point::*;
|
||||||
use quaternion::*;
|
|
||||||
use ray::Ray;
|
use ray::Ray;
|
||||||
use rotation::{Rotation, Rotation3};
|
use rotation::*;
|
||||||
use std::marker::PhantomFn;
|
use std::marker::PhantomFn;
|
||||||
use vector::{Vector, Vector3};
|
use vector::*;
|
||||||
|
|
||||||
/// A trait representing an [affine
|
/// A trait representing an [affine
|
||||||
/// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that
|
/// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that
|
||||||
|
@ -89,7 +88,7 @@ impl<
|
||||||
S: BaseFloat,
|
S: BaseFloat,
|
||||||
V: Vector<S>,
|
V: Vector<S>,
|
||||||
P: Point<S, V>,
|
P: Point<S, V>,
|
||||||
R: Rotation<S, V, P>
|
R: Rotation<S, V, P>,
|
||||||
> Transform<S, V, P> for Decomposed<S, V, R> {
|
> Transform<S, V, P> for Decomposed<S, V, R> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn identity() -> Decomposed<S, V, R> {
|
fn identity() -> Decomposed<S, V, R> {
|
||||||
|
@ -146,11 +145,23 @@ impl<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Transform2<S>: Transform<S, Vector2<S>, Point2<S>> + ToMatrix3<S> {}
|
||||||
pub trait Transform3<S>: Transform<S, Vector3<S>, Point3<S>> + ToMatrix4<S> {}
|
pub trait Transform3<S>: Transform<S, Vector3<S>, Point3<S>> + ToMatrix4<S> {}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
S: BaseFloat + 'static,
|
S: BaseFloat + 'static,
|
||||||
R: Rotation3<S>
|
R: Rotation2<S>,
|
||||||
|
> ToMatrix3<S> for Decomposed<S, Vector2<S>, R> {
|
||||||
|
fn to_matrix3(&self) -> Matrix3<S> {
|
||||||
|
let mut m = self.rot.to_matrix2().mul_s(self.scale.clone()).to_matrix3();
|
||||||
|
m.z = self.disp.extend(one());
|
||||||
|
m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
S: BaseFloat + 'static,
|
||||||
|
R: Rotation3<S>,
|
||||||
> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> {
|
> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> {
|
||||||
fn to_matrix4(&self) -> Matrix4<S> {
|
fn to_matrix4(&self) -> Matrix4<S> {
|
||||||
let mut m = self.rot.to_matrix3().mul_s(self.scale.clone()).to_matrix4();
|
let mut m = self.rot.to_matrix3().mul_s(self.scale.clone()).to_matrix4();
|
||||||
|
@ -161,12 +172,17 @@ impl<
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
S: BaseFloat + 'static,
|
S: BaseFloat + 'static,
|
||||||
R: Rotation3<S>
|
R: Rotation2<S>,
|
||||||
|
> Transform2<S> for Decomposed<S, Vector2<S>, R> {}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
S: BaseFloat + 'static,
|
||||||
|
R: Rotation3<S>,
|
||||||
> Transform3<S> for Decomposed<S, Vector3<S>, R> {}
|
> Transform3<S> for Decomposed<S, Vector3<S>, R> {}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
S: BaseFloat,
|
S: BaseFloat,
|
||||||
R: fmt::Debug + Rotation3<S>
|
R: fmt::Debug + Rotation3<S>,
|
||||||
> fmt::Debug for Decomposed<S, Vector3<S>, R> {
|
> fmt::Debug for Decomposed<S, Vector3<S>, R> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "(scale({:?}), rot({:?}), disp{:?})",
|
write!(f, "(scale({:?}), rot({:?}), disp{:?})",
|
||||||
|
@ -216,72 +232,54 @@ impl<S: BaseNum> ToMatrix4<S> for AffineMatrix3<S> {
|
||||||
#[inline] fn to_matrix4(&self) -> Matrix4<S> { self.mat.clone() }
|
#[inline] fn to_matrix4(&self) -> Matrix4<S> { self.mat.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> Transform3<S> for AffineMatrix3<S> where S: 'static {}
|
impl<S: BaseFloat + 'static> Transform3<S> for AffineMatrix3<S> {}
|
||||||
|
|
||||||
/// A trait that allows extracting components (rotation, translation, scale)
|
/// A trait that allows extracting components (rotation, translation, scale)
|
||||||
/// from an arbitrary transformation/
|
/// from an arbitrary transformations
|
||||||
pub trait ToComponents<S, V: Vector<S>, P: Point<S, V>> {
|
pub trait ToComponents<S, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>>: PhantomFn<(S, P)> {
|
||||||
/// Associated rotation type
|
/// Extract the (scale, rotation, translation) triple
|
||||||
type Rotation;
|
fn decompose(&self) -> (V, R, V);
|
||||||
/// Extract translation component
|
|
||||||
fn to_translation(&self) -> V;
|
|
||||||
/// Extract rotation component
|
|
||||||
fn to_rotation(&self) -> Self::Rotation;
|
|
||||||
/// Extract scale component
|
|
||||||
fn to_scale(&self) -> V;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToComponents3<S>: ToComponents<S, Vector3<S>, Point3<S>>
|
pub trait ToComponents2<S, R: Rotation2<S>>:
|
||||||
where Self::Rotation: ToMatrix3<S> {}
|
ToComponents<S, Vector2<S>, Point2<S>, R> {}
|
||||||
|
pub trait ToComponents3<S, R: Rotation3<S>>:
|
||||||
|
ToComponents<S, Vector3<S>, Point3<S>, R> {}
|
||||||
|
|
||||||
|
pub trait CompositeTransform<S, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>>:
|
||||||
|
Transform<S, V, P> + ToComponents<S, V, P, R> {}
|
||||||
|
pub trait CompositeTransform2<S, R: Rotation2<S>>:
|
||||||
|
Transform2<S> + ToComponents2<S, R> {}
|
||||||
|
pub trait CompositeTransform3<S, R: Rotation3<S>>:
|
||||||
|
Transform3<S> + ToComponents3<S, R> {}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
S: BaseFloat,
|
S: BaseFloat,
|
||||||
V: Vector<S> + Clone,
|
V: Vector<S> + Clone,
|
||||||
P: Point<S, V>,
|
P: Point<S, V>,
|
||||||
R: Rotation<S, V, P> + Clone,
|
R: Rotation<S, V, P> + Clone,
|
||||||
> ToComponents<S, V, P> for Decomposed<S, V, R> {
|
> ToComponents<S, V, P, R> for Decomposed<S, V, R> {
|
||||||
type Rotation = R;
|
fn decompose(&self) -> (V, R, V) {
|
||||||
|
(Vector::from_value(self.scale), self.rot.clone(), self.disp.clone())
|
||||||
fn to_translation(&self) -> V {
|
|
||||||
self.disp.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_rotation(&self) -> R {
|
|
||||||
self.rot.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_scale(&self) -> V {
|
|
||||||
Vector::from_value(self.scale)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
S: BaseFloat,
|
S: BaseFloat,
|
||||||
R: Rotation<S, Vector3<S>, Point3<S>> + Clone + ToMatrix3<S>,
|
R: Rotation2<S> + Clone,
|
||||||
> ToComponents3<S> for Decomposed<S, Vector3<S>, R> {}
|
> ToComponents2<S, R> for Decomposed<S, Vector2<S>, R> {}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
S: BaseFloat,
|
||||||
|
R: Rotation3<S> + Clone,
|
||||||
|
> ToComponents3<S, R> for Decomposed<S, Vector3<S>, R> {}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
S: BaseFloat + 'static,
|
S: BaseFloat + 'static,
|
||||||
> ToComponents<S, Vector3<S>, Point3<S>> for AffineMatrix3<S> {
|
R: Rotation2<S> + Clone,
|
||||||
type Rotation = Quaternion<S>;
|
> CompositeTransform2<S, R> for Decomposed<S, Vector2<S>, R> {}
|
||||||
|
|
||||||
fn to_translation(&self) -> Vector3<S> {
|
|
||||||
Vector3::new(self.mat.w.x, self.mat.w.y, self.mat.w.z)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_rotation(&self) -> Quaternion<S> {
|
|
||||||
Matrix3::new(
|
|
||||||
self.mat.x.x, self.mat.x.y, self.mat.x.z,
|
|
||||||
self.mat.y.x, self.mat.y.y, self.mat.y.z,
|
|
||||||
self.mat.z.x, self.mat.z.y, self.mat.z.z,
|
|
||||||
).to_quaternion()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_scale(&self) -> Vector3<S> {
|
|
||||||
Vector3::new(self.mat.x.x, self.mat.y.y, self.mat.z.z)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
S: BaseFloat + 'static,
|
S: BaseFloat + 'static,
|
||||||
> ToComponents3<S> for AffineMatrix3<S> {}
|
R: Rotation3<S> + Clone,
|
||||||
|
> CompositeTransform3<S, R> for Decomposed<S, Vector3<S>, R> {}
|
||||||
|
|
|
@ -20,11 +20,11 @@ use cgmath::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invert() {
|
fn test_invert() {
|
||||||
let v = Vector3::new(1.0f64, 2.0f64, 3.0f64);
|
let v = Vector3::new(1.0f64, 2.0, 3.0);
|
||||||
let t = Decomposed {
|
let t = Decomposed {
|
||||||
scale: 1.5f64,
|
scale: 1.5f64,
|
||||||
rot: Quaternion::new(0.5f64,0.5,0.5,0.5),
|
rot: Quaternion::new(0.5f64,0.5,0.5,0.5),
|
||||||
disp: Vector3::new(6.0f64,-7.0f64,8.0)
|
disp: Vector3::new(6.0f64,-7.0,8.0)
|
||||||
};
|
};
|
||||||
let ti = t.invert().expect("Expected successful inversion");
|
let ti = t.invert().expect("Expected successful inversion");
|
||||||
let vt = t.transform_vector( &v );
|
let vt = t.transform_vector( &v );
|
||||||
|
@ -33,12 +33,12 @@ fn test_invert() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_look_at() {
|
fn test_look_at() {
|
||||||
let eye = Point3::new(0.0f64, 0.0f64, -5.0f64);
|
let eye = Point3::new(0.0f64, 0.0, -5.0);
|
||||||
let center = Point3::new(0.0f64, 0.0f64, 0.0f64);
|
let center = Point3::new(0.0f64, 0.0, 0.0);
|
||||||
let up = Vector3::new(1.0f64, 0.0f64, 0.0f64);
|
let up = Vector3::new(1.0f64, 0.0, 0.0);
|
||||||
let t: Decomposed<f64,Vector3<f64>,Quaternion<f64>> = Transform::look_at(&eye, ¢er, &up);
|
let t: Decomposed<f64,Vector3<f64>,Quaternion<f64>> = Transform::look_at(&eye, ¢er, &up);
|
||||||
let point = Point3::new(1.0f64, 0.0f64, 0.0f64);
|
let point = Point3::new(1.0f64, 0.0, 0.0);
|
||||||
let view_point = Point3::new(0.0f64, 1.0f64, 5.0f64);
|
let view_point = Point3::new(0.0f64, 1.0, 5.0);
|
||||||
assert!( t.transform_point(&point).approx_eq(&view_point) );
|
assert!( t.transform_point(&point).approx_eq(&view_point) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,9 +47,10 @@ fn test_components() {
|
||||||
let t = Decomposed {
|
let t = Decomposed {
|
||||||
scale: 1.5f64,
|
scale: 1.5f64,
|
||||||
rot: Quaternion::new(0.5f64,0.5,0.5,0.5),
|
rot: Quaternion::new(0.5f64,0.5,0.5,0.5),
|
||||||
disp: Vector3::new(6.0f64,-7.0f64,8.0)
|
disp: Vector3::new(6.0f64,-7.0,8.0)
|
||||||
};
|
};
|
||||||
assert_eq!(t.to_translation(), t.disp);
|
let (scale, rot, disp) = t.decompose();
|
||||||
assert_eq!(t.to_rotation(), t.rot);
|
assert_eq!(scale, Vector::from_value(t.scale));
|
||||||
assert_eq!(t.to_scale(), Vector::from_value(t.scale));
|
assert_eq!(rot, t.rot);
|
||||||
|
assert_eq!(disp, t.disp);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue