From f03d4427ee56e103c2b324c1f4a0a22dcdd355d5 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sun, 1 Mar 2015 23:05:47 -0500 Subject: [PATCH] Redesigned ToComponents, removed the implementation for AffineMatrix3 as incorrect. --- src/transform.rs | 112 ++++++++++++++++++++++----------------------- tests/transform.rs | 23 +++++----- 2 files changed, 67 insertions(+), 68 deletions(-) diff --git a/src/transform.rs b/src/transform.rs index de3d33a..48e966e 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -17,13 +17,12 @@ use std::fmt; use approx::ApproxEq; use matrix::*; -use num::{BaseNum, BaseFloat, zero, one}; -use point::{Point, Point3}; -use quaternion::*; +use num::*; +use point::*; use ray::Ray; -use rotation::{Rotation, Rotation3}; +use rotation::*; use std::marker::PhantomFn; -use vector::{Vector, Vector3}; +use vector::*; /// A trait representing an [affine /// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that @@ -89,7 +88,7 @@ impl< S: BaseFloat, V: Vector, P: Point, - R: Rotation + R: Rotation, > Transform for Decomposed { #[inline] fn identity() -> Decomposed { @@ -146,11 +145,23 @@ impl< } } +pub trait Transform2: Transform, Point2> + ToMatrix3 {} pub trait Transform3: Transform, Point3> + ToMatrix4 {} impl< S: BaseFloat + 'static, - R: Rotation3 + R: Rotation2, +> ToMatrix3 for Decomposed, R> { + fn to_matrix3(&self) -> Matrix3 { + 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, > ToMatrix4 for Decomposed, R> { fn to_matrix4(&self) -> Matrix4 { let mut m = self.rot.to_matrix3().mul_s(self.scale.clone()).to_matrix4(); @@ -161,12 +172,17 @@ impl< impl< S: BaseFloat + 'static, - R: Rotation3 + R: Rotation2, +> Transform2 for Decomposed, R> {} + +impl< + S: BaseFloat + 'static, + R: Rotation3, > Transform3 for Decomposed, R> {} impl< S: BaseFloat, - R: fmt::Debug + Rotation3 + R: fmt::Debug + Rotation3, > fmt::Debug for Decomposed, R> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "(scale({:?}), rot({:?}), disp{:?})", @@ -216,72 +232,54 @@ impl ToMatrix4 for AffineMatrix3 { #[inline] fn to_matrix4(&self) -> Matrix4 { self.mat.clone() } } -impl Transform3 for AffineMatrix3 where S: 'static {} +impl Transform3 for AffineMatrix3 {} /// A trait that allows extracting components (rotation, translation, scale) -/// from an arbitrary transformation/ -pub trait ToComponents, P: Point> { - /// Associated rotation type - type Rotation; - /// 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; +/// from an arbitrary transformations +pub trait ToComponents, P: Point, R: Rotation>: PhantomFn<(S, P)> { + /// Extract the (scale, rotation, translation) triple + fn decompose(&self) -> (V, R, V); } -pub trait ToComponents3: ToComponents, Point3> - where Self::Rotation: ToMatrix3 {} +pub trait ToComponents2>: + ToComponents, Point2, R> {} +pub trait ToComponents3>: + ToComponents, Point3, R> {} + +pub trait CompositeTransform, P: Point, R: Rotation>: + Transform + ToComponents {} +pub trait CompositeTransform2>: + Transform2 + ToComponents2 {} +pub trait CompositeTransform3>: + Transform3 + ToComponents3 {} impl< S: BaseFloat, V: Vector + Clone, P: Point, R: Rotation + Clone, -> ToComponents for Decomposed { - type Rotation = R; - - 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) +> ToComponents for Decomposed { + fn decompose(&self) -> (V, R, V) { + (Vector::from_value(self.scale), self.rot.clone(), self.disp.clone()) } } impl< S: BaseFloat, - R: Rotation, Point3> + Clone + ToMatrix3, -> ToComponents3 for Decomposed, R> {} + R: Rotation2 + Clone, +> ToComponents2 for Decomposed, R> {} + +impl< + S: BaseFloat, + R: Rotation3 + Clone, +> ToComponents3 for Decomposed, R> {} impl< S: BaseFloat + 'static, -> ToComponents, Point3> for AffineMatrix3 { - type Rotation = Quaternion; - - fn to_translation(&self) -> Vector3 { - Vector3::new(self.mat.w.x, self.mat.w.y, self.mat.w.z) - } - - fn to_rotation(&self) -> Quaternion { - 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 { - Vector3::new(self.mat.x.x, self.mat.y.y, self.mat.z.z) - } -} + R: Rotation2 + Clone, +> CompositeTransform2 for Decomposed, R> {} impl< S: BaseFloat + 'static, -> ToComponents3 for AffineMatrix3 {} + R: Rotation3 + Clone, +> CompositeTransform3 for Decomposed, R> {} diff --git a/tests/transform.rs b/tests/transform.rs index 3ec7b1a..64683e2 100644 --- a/tests/transform.rs +++ b/tests/transform.rs @@ -20,11 +20,11 @@ use cgmath::*; #[test] 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 { scale: 1.5f64, 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 vt = t.transform_vector( &v ); @@ -33,12 +33,12 @@ fn test_invert() { #[test] fn test_look_at() { - let eye = Point3::new(0.0f64, 0.0f64, -5.0f64); - let center = Point3::new(0.0f64, 0.0f64, 0.0f64); - let up = Vector3::new(1.0f64, 0.0f64, 0.0f64); + let eye = Point3::new(0.0f64, 0.0, -5.0); + let center = Point3::new(0.0f64, 0.0, 0.0); + let up = Vector3::new(1.0f64, 0.0, 0.0); let t: Decomposed,Quaternion> = Transform::look_at(&eye, ¢er, &up); - let point = Point3::new(1.0f64, 0.0f64, 0.0f64); - let view_point = Point3::new(0.0f64, 1.0f64, 5.0f64); + let point = Point3::new(1.0f64, 0.0, 0.0); + let view_point = Point3::new(0.0f64, 1.0, 5.0); assert!( t.transform_point(&point).approx_eq(&view_point) ); } @@ -47,9 +47,10 @@ fn test_components() { let t = Decomposed { scale: 1.5f64, 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); - assert_eq!(t.to_rotation(), t.rot); - assert_eq!(t.to_scale(), Vector::from_value(t.scale)); + let (scale, rot, disp) = t.decompose(); + assert_eq!(scale, Vector::from_value(t.scale)); + assert_eq!(rot, t.rot); + assert_eq!(disp, t.disp); }