diff --git a/src/cgmath.rs b/src/cgmath.rs index b7df0d7..b1dfea7 100644 --- a/src/cgmath.rs +++ b/src/cgmath.rs @@ -15,7 +15,7 @@ #![crate_type = "rlib"] #![crate_type = "dylib"] -#![feature(old_impl_check, plugin, core, hash, std_misc)] +#![feature(old_impl_check, plugin, core, std_misc)] #![plugin(rand_macros)] //! Computer graphics-centric math. @@ -37,45 +37,30 @@ extern crate rand; // Re-exports -pub use array::{Array1, Array2, FixedArray}; +pub use array::*; +pub use matrix::*; +pub use quaternion::*; +pub use vector::*; -pub use matrix::Matrix; -pub use matrix::{Matrix2, Matrix3, Matrix4}; -pub use matrix::{ToMatrix2, ToMatrix3, ToMatrix4}; -pub use quaternion::{Quaternion, ToQuaternion}; -pub use vector::{Vector, EuclideanVector}; -pub use vector::{Vector2, Vector3, Vector4}; -pub use vector::{dot, vec2, vec3, vec4}; - -pub use angle::{rad, deg}; -pub use angle::{Angle, Rad, Deg}; -pub use angle::{ToRad, ToDeg}; -pub use angle::bisect; -pub use angle::{sin, cos, tan, sin_cos}; -pub use angle::{cot, sec, csc}; -pub use angle::{acos, asin, atan, atan2}; +pub use angle::*; pub use plane::Plane; -pub use point::{Point, Point2, Point3}; -pub use line::{Line, Line2, Line3}; -pub use ray::{Ray, Ray2, Ray3}; -pub use rotation::{Rotation, Rotation2, Rotation3}; -pub use rotation::{Basis3, Basis2}; -pub use rotation::{ToBasis2, ToBasis3}; -pub use transform::{Transform, Transform3}; -pub use transform::{Decomposed, AffineMatrix3}; +pub use point::*; +pub use line::*; +pub use ray::*; +pub use rotation::*; +pub use transform::*; -pub use projection::{perspective, frustum, ortho}; -pub use projection::{Projection, PerspectiveFov, Perspective, Ortho}; +pub use projection::*; -pub use aabb::{Aabb, Aabb2, Aabb3}; +pub use aabb::*; pub use cylinder::Cylinder; pub use frustum::{Frustum, FrustumPoints}; pub use intersect::Intersect; -pub use obb::{Obb2, Obb3}; +pub use obb::*; pub use sphere::Sphere; pub use approx::ApproxEq; -pub use num::{PartialOrd, BaseNum, BaseInt, BaseFloat, One, one, Zero, zero}; +pub use num::*; // Modules diff --git a/src/transform.rs b/src/transform.rs index a95b2fc..de3d33a 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -16,9 +16,10 @@ use std::fmt; use approx::ApproxEq; -use matrix::{Matrix, Matrix4, ToMatrix4}; +use matrix::*; use num::{BaseNum, BaseFloat, zero, one}; use point::{Point, Point3}; +use quaternion::*; use ray::Ray; use rotation::{Rotation, Rotation3}; use std::marker::PhantomFn; @@ -27,7 +28,7 @@ use vector::{Vector, Vector3}; /// A trait representing an [affine /// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that /// can be applied to points or vectors. An affine transformation is one which -pub trait Transform, P: Point>: Sized + PhantomFn { +pub trait Transform, P: Point>: Sized + PhantomFn { /// Create an identity transformation. That is, a transformation which /// does nothing. fn identity() -> Self; @@ -44,7 +45,7 @@ pub trait Transform, P: Point>: Sized + PhantomFn< /// Transform a ray using this transform. #[inline] - fn transform_ray(&self, ray: &Ray) -> Ray { + fn transform_ray(&self, ray: &Ray) -> Ray { Ray::new(self.transform_point(&ray.origin), self.transform_vector(&ray.direction)) } @@ -84,7 +85,12 @@ pub struct Decomposed { pub disp: V, } -impl, P: Point, R: Rotation> Transform for Decomposed { +impl< + S: BaseFloat, + V: Vector, + P: Point, + R: Rotation +> Transform for Decomposed { #[inline] fn identity() -> Decomposed { Decomposed { @@ -140,9 +146,12 @@ impl, P: Point, R: Rotation> Transform } } -pub trait Transform3: Transform, Point3>+ ToMatrix4 {} +pub trait Transform3: Transform, Point3> + ToMatrix4 {} -impl> ToMatrix4 for Decomposed, R> { +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(); m.w = self.disp.extend(one()); @@ -150,9 +159,15 @@ impl> ToMatrix4 for Decomposed> Transform3 for Decomposed,R> where S: 'static {} +impl< + S: BaseFloat + 'static, + R: Rotation3 +> Transform3 for Decomposed, R> {} -impl> fmt::Debug for Decomposed,R> { +impl< + S: BaseFloat, + R: fmt::Debug + Rotation3 +> fmt::Debug for Decomposed, R> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "(scale({:?}), rot({:?}), disp{:?})", self.scale, self.rot, self.disp) @@ -202,3 +217,71 @@ impl ToMatrix4 for AffineMatrix3 { } impl Transform3 for AffineMatrix3 where S: 'static {} + +/// 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; +} + +pub trait ToComponents3: ToComponents, Point3> + where Self::Rotation: ToMatrix3 {} + +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) + } +} + +impl< + S: BaseFloat, + R: Rotation, Point3> + Clone + ToMatrix3, +> 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) + } +} + +impl< + S: BaseFloat + 'static, +> ToComponents3 for AffineMatrix3 {} diff --git a/src/vector.rs b/src/vector.rs index 1fe88e6..83c26fb 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -22,11 +22,11 @@ //! vector are also provided: //! //! ```rust -//! use cgmath::{Vector2, Vector3, Vector4, one, zero, vec3}; +//! use cgmath::{Vector, Vector2, Vector3, Vector4, zero, vec2, vec3}; //! //! assert_eq!(Vector2::new(1.0f64, 0.0f64), Vector2::unit_x()); //! assert_eq!(vec3(0.0f64, 0.0f64, 0.0f64), zero()); -//! assert_eq!(Vector4::from_value(1.0f64), one()); +//! assert_eq!(Vector::from_value(1.0f64), vec2(1.0, 1.0)); //! ``` //! //! Vectors can be manipulated with typical mathematical operations (addition, @@ -76,7 +76,7 @@ //! //! // Scalar multiplication can return a new object, or be done in place //! // to avoid an allocation: -//! let mut c: Vector4 = Vector4::from_value(3.0); +//! let mut c: Vector4 = Vector::from_value(3.0); //! let d: Vector4 = c.mul_s(2.0); //! c.mul_self_s(2.0); //! assert_eq!(c, d); @@ -110,6 +110,8 @@ use num::{BaseNum, BaseFloat, Zero, One, zero, one}; /// of these make sense from a linear algebra point of view, but are included /// for pragmatic reasons. pub trait Vector: Array1 + Zero + One + Neg { + /// Construct a vector from a single value, replicating it. + fn from_value(s: S) -> Self; /// Add a scalar to this vector, returning a new vector. #[must_use] fn add_s(&self, s: S) -> Self; @@ -206,14 +208,6 @@ macro_rules! vec( $Self_::new($($field),+) } - impl<$S: Copy> $Self_<$S> { - /// Construct a vector from a single value, replicating it. - #[inline] - pub fn from_value(value: $S) -> $Self_<$S> { - $Self_ { $($field: value),+ } - } - } - impl<$S: Zero> Zero for $Self_<$S> { #[inline] fn zero() -> $Self_ { $Self_ { $($field: zero()),+ } } @@ -292,6 +286,7 @@ macro_rules! vec( } impl Vector for $Self_ { + #[inline] fn from_value(s: S) -> $Self_ { $Self_ { $($field: s),+ } } #[inline] fn add_s(&self, s: S) -> $Self_ { $Self_::new($(self.$field + s),+) } #[inline] fn sub_s(&self, s: S) -> $Self_ { $Self_::new($(self.$field - s),+) } #[inline] fn mul_s(&self, s: S) -> $Self_ { $Self_::new($(self.$field * s),+) } diff --git a/tests/transform.rs b/tests/transform.rs index 25d68f9..3ec7b1a 100644 --- a/tests/transform.rs +++ b/tests/transform.rs @@ -41,3 +41,15 @@ fn test_look_at() { let view_point = Point3::new(0.0f64, 1.0f64, 5.0f64); assert!( t.transform_point(&point).approx_eq(&view_point) ); } + +#[test] +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) + }; + assert_eq!(t.to_translation(), t.disp); + assert_eq!(t.to_rotation(), t.rot); + assert_eq!(t.to_scale(), Vector::from_value(t.scale)); +} diff --git a/tests/vector.rs b/tests/vector.rs index 848e963..6c37560 100644 --- a/tests/vector.rs +++ b/tests/vector.rs @@ -31,9 +31,9 @@ fn test_constructor() { #[test] fn test_from_value() { - assert_eq!(Vector2::from_value(102is), Vector2::new(102is, 102is)); - assert_eq!(Vector3::from_value(22is), Vector3::new(22is, 22is, 22is)); - assert_eq!(Vector4::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64)); + assert_eq!(Vector::from_value(102is), Vector2::new(102is, 102is)); + assert_eq!(Vector::from_value(22is), Vector3::new(22is, 22is, 22is)); + assert_eq!(Vector::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64)); } #[test]