From d81157fba54e5aa046d474314127e99e3de87d97 Mon Sep 17 00:00:00 2001 From: kvark Date: Fri, 1 Nov 2013 07:09:57 -0400 Subject: [PATCH 1/5] Generalized Ray & Transform over dimensions --- src/cgmath/ray.rs | 41 ++++++++++++++++++----------------------- src/cgmath/transform.rs | 35 +++++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/cgmath/ray.rs b/src/cgmath/ray.rs index ec6c06a..3b1096c 100644 --- a/src/cgmath/ray.rs +++ b/src/cgmath/ray.rs @@ -13,33 +13,28 @@ // See the License for the specific language governing permissions and // limitations under the License. -use point::{Point2, Point3}; -use vector::{Vec2, Vec3}; +use point::{Point,Point2, Point3}; +use vector::{Vector,Vec2, Vec3}; #[deriving(Clone, Eq)] -pub struct Ray2 { - origin: Point2, - direction: Vec2, +pub struct Ray +{ + origin: P, + direction: V, } -impl Ray2 { - /// Creates a new ray from a position coordinate and a direction vector - #[inline] - pub fn new(origin: Point2, direction: Vec2) -> Ray2 { - Ray2 { origin: origin, direction: direction } +impl +< + S: Primitive, + Slice, + V: Vector, + P: Point +> Ray +{ + pub fn new(origin: P, direction: V) -> Ray { + Ray { origin:origin, direction:direction } } } -#[deriving(Clone, Eq)] -pub struct Ray3 { - origin: Point3, - direction: Vec3, -} - -impl Ray3 { - /// Creates a new ray from a position coordinate and a direction vector - #[inline] - pub fn new(origin: Point3, direction: Vec3) -> Ray3 { - Ray3 { origin: origin, direction: direction } - } -} +pub type Ray2 = Ray,Vec2>; +pub type Ray3 = Ray,Vec3>; diff --git a/src/cgmath/transform.rs b/src/cgmath/transform.rs index bb60df7..2eefb44 100644 --- a/src/cgmath/transform.rs +++ b/src/cgmath/transform.rs @@ -15,18 +15,25 @@ use matrix::Mat4; use point::{Point,Point3}; -use ray::Ray3; +use ray::Ray; use rotation::Rotation3; use vector::{Vector,Vec3}; +/// A trait of affine transformation, that can be applied to points or vectors +pub trait Transform +< + S: Primitive, + Slice, + V: Vector, + P: Point +> +{ + fn transform_vec(&self, vec: &V) -> V; + fn transform_point(&self, point: &P) -> P; -pub trait Transform3 { - fn transform_vec3(&self, vec: &Vec3) -> Vec3; - fn transform_point3(&self, point: &Point3) -> Point3; - #[inline] - fn transform_ray3(&self, ray: &Ray3) -> Ray3 { - Ray3::new( self.transform_point3(&ray.origin), self.transform_vec3(&ray.direction) ) + fn transform_ray(&self, ray: &Ray) -> Ray { + Ray::new( self.transform_point(&ray.origin), self.transform_vec(&ray.direction) ) } } @@ -37,27 +44,27 @@ pub struct AffineMatrix3 { /// A transformation in three dimensions consisting of a rotation, /// displacement vector and scale amount. -pub struct Transform3D { +pub struct Transform3 { rot: R, disp: Vec3, scale: S, } -impl> Transform3D { +impl> Transform3 { #[inline] - pub fn new(rot: R, disp: Vec3, scale: S) -> Transform3D { - Transform3D { rot: rot, disp: disp, scale: scale } + pub fn new(rot: R, disp: Vec3, scale: S) -> Transform3 { + Transform3 { rot: rot, disp: disp, scale: scale } } } -impl > Transform3 for Transform3D { +impl > Transform, Point3> for Transform3 { #[inline] - fn transform_vec3(&self, vec: &Vec3) -> Vec3 { + fn transform_vec(&self, vec: &Vec3) -> Vec3 { self.rot.rotate_vec3( &vec.mul_s( self.scale.clone() )) } #[inline] - fn transform_point3(&self, point: &Point3) -> Point3 { + fn transform_point(&self, point: &Point3) -> Point3 { self.rot.rotate_point3( &point.mul_s( self.scale.clone() )).add_v( &self.disp ) } } From 0c41aa39513985965ca46f0dd5e3c499138ae9b6 Mon Sep 17 00:00:00 2001 From: kvark Date: Fri, 1 Nov 2013 07:34:39 -0400 Subject: [PATCH 2/5] Rotation is generalized over dimensions --- src/cgmath/ray.rs | 5 ++- src/cgmath/rotation.rs | 94 +++++++++++++++++++++++++---------------- src/cgmath/transform.rs | 8 ++-- 3 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/cgmath/ray.rs b/src/cgmath/ray.rs index 3b1096c..f9d4125 100644 --- a/src/cgmath/ray.rs +++ b/src/cgmath/ray.rs @@ -13,9 +13,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use point::{Point,Point2, Point3}; -use vector::{Vector,Vec2, Vec3}; +use point::{Point, Point2, Point3}; +use vector::{Vector, Vec2, Vec3}; +/// A generic ray #[deriving(Clone, Eq)] pub struct Ray { diff --git a/src/cgmath/rotation.rs b/src/cgmath/rotation.rs index 28dc015..4da5b96 100644 --- a/src/cgmath/rotation.rs +++ b/src/cgmath/rotation.rs @@ -17,49 +17,65 @@ use angle::Rad; use matrix::Matrix; use matrix::{Mat2, ToMat2}; use matrix::{Mat3, ToMat3}; -use point::{Point2, Point3}; +use point::{Point, Point2, Point3}; use quaternion::{Quat, ToQuat}; -use ray::{Ray2, Ray3}; +use ray::{Ray, Ray2, Ray3}; use vector::{Vector, Vec2, Vec3}; +/// A trait for generic rotation +pub trait Rotation +< + S: Primitive + Clone, + Slice, + V: Vector, + P: Point + Clone +> +: Eq ++ ApproxEq +{ + fn rotate_point(&self, point: &P) -> P; + fn rotate_vec(&self, vec: &V) -> V; + + #[inline] + fn rotate_ray(&self, ray: &Ray) -> Ray { + Ray::new( ray.origin.clone(), self.rotate_vec(&ray.direction) ) + } + + fn concat(&self, other: &Self) -> Self; + fn invert(&self) -> Self; + + #[inline] + fn concat_self(&mut self, other: &Self) { + *self = self.concat(other); + } + + #[inline] + fn invert_self(&mut self) { + *self = self.invert(); + } +} + /// A two-dimensional rotation pub trait Rotation2 < S > -: Eq -+ ApproxEq +: Rotation, Point2> + ToMat2 + ToBasis2 -{ - fn rotate_point2(&self, point: &Point2) -> Point2; - fn rotate_vec2(&self, vec: &Vec2) -> Vec2; - fn rotate_ray2(&self, ray: &Ray2) -> Ray2; - fn concat(&self, other: &Self) -> Self; - fn concat_self(&mut self, other: &Self); - fn invert(&self) -> Self; - fn invert_self(&mut self); -} +{} /// A three-dimensional rotation pub trait Rotation3 < S > -: Eq -+ ApproxEq +: Rotation, Point3> + ToMat3 + ToBasis3 + ToQuat -{ - fn rotate_point3(&self, point: &Point3) -> Point3; - fn rotate_vec3(&self, vec: &Vec3) -> Vec3; - fn rotate_ray3(&self, ray: &Ray3) -> Ray3; - fn concat(&self, other: &Self) -> Self; - fn concat_self(&mut self, other: &Self); - fn invert(&self) -> Self; - fn invert_self(&mut self); -} +{} + /// A two-dimensional rotation matrix. /// @@ -91,15 +107,15 @@ impl ToMat2 for Basis2 { fn to_mat2(&self) -> Mat2 { self.mat.clone() } } -impl Rotation2 for Basis2 { +impl Rotation, Point2> for Basis2 { #[inline] - fn rotate_point2(&self, _point: &Point2) -> Point2 { fail!("Not yet implemented") } + fn rotate_point(&self, _point: &Point2) -> Point2 { fail!("Not yet implemented") } #[inline] - fn rotate_vec2(&self, vec: &Vec2) -> Vec2 { self.mat.mul_v(vec) } + fn rotate_vec(&self, vec: &Vec2) -> Vec2 { self.mat.mul_v(vec) } #[inline] - fn rotate_ray2(&self, _ray: &Ray2) -> Ray2 { fail!("Not yet implemented") } + fn rotate_ray(&self, _ray: &Ray2) -> Ray2 { fail!("Not yet implemented") } #[inline] fn concat(&self, other: &Basis2) -> Basis2 { Basis2 { mat: self.mat.mul_m(&other.mat) } } @@ -136,6 +152,8 @@ impl ApproxEq for Basis2 { } } +impl Rotation2 for Basis2 {} + /// A three-dimensional rotation matrix. /// /// The matrix is guaranteed to be orthogonal, so some operations, specifically @@ -207,15 +225,15 @@ impl ToQuat for Basis3 { fn to_quat(&self) -> Quat { self.mat.to_quat() } } -impl Rotation3 for Basis3 { +impl Rotation, Point3> for Basis3 { #[inline] - fn rotate_point3(&self, _point: &Point3) -> Point3 { fail!("Not yet implemented") } + fn rotate_point(&self, _point: &Point3) -> Point3 { fail!("Not yet implemented") } #[inline] - fn rotate_vec3(&self, vec: &Vec3) -> Vec3 { self.mat.mul_v(vec) } + fn rotate_vec(&self, vec: &Vec3) -> Vec3 { self.mat.mul_v(vec) } #[inline] - fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { fail!("Not yet implemented") } + fn rotate_ray(&self, _ray: &Ray3) -> Ray3 { fail!("Not yet implemented") } #[inline] fn concat(&self, other: &Basis3) -> Basis3 { Basis3 { mat: self.mat.mul_m(&other.mat) } } @@ -252,6 +270,8 @@ impl ApproxEq for Basis3 { } } +impl Rotation3 for Basis3 {} + // Quaternion Rotation impls impl ToBasis3 for Quat { @@ -264,15 +284,15 @@ impl ToQuat for Quat { fn to_quat(&self) -> Quat { self.clone() } } -impl Rotation3 for Quat { +impl Rotation, Point3> for Quat { #[inline] - fn rotate_point3(&self, _point: &Point3) -> Point3 { fail!("Not yet implemented") } + fn rotate_point(&self, _point: &Point3) -> Point3 { fail!("Not yet implemented") } #[inline] - fn rotate_vec3(&self, vec: &Vec3) -> Vec3 { self.mul_v(vec) } + fn rotate_vec(&self, vec: &Vec3) -> Vec3 { self.mul_v(vec) } #[inline] - fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { fail!("Not yet implemented") } + fn rotate_ray(&self, _ray: &Ray3) -> Ray3 { fail!("Not yet implemented") } #[inline] fn concat(&self, other: &Quat) -> Quat { self.mul_q(other) } @@ -286,3 +306,5 @@ impl Rotation3 for Quat { #[inline] fn invert_self(&mut self) { *self = self.invert() } } + +impl Rotation3 for Quat {} \ No newline at end of file diff --git a/src/cgmath/transform.rs b/src/cgmath/transform.rs index 2eefb44..08ae398 100644 --- a/src/cgmath/transform.rs +++ b/src/cgmath/transform.rs @@ -14,10 +14,10 @@ // limitations under the License. use matrix::Mat4; -use point::{Point,Point3}; +use point::{Point, Point3}; use ray::Ray; use rotation::Rotation3; -use vector::{Vector,Vec3}; +use vector::{Vector, Vec3}; /// A trait of affine transformation, that can be applied to points or vectors pub trait Transform @@ -60,11 +60,11 @@ impl> Transform3 { impl > Transform, Point3> for Transform3 { #[inline] fn transform_vec(&self, vec: &Vec3) -> Vec3 { - self.rot.rotate_vec3( &vec.mul_s( self.scale.clone() )) + self.rot.rotate_vec( &vec.mul_s( self.scale.clone() )) } #[inline] fn transform_point(&self, point: &Point3) -> Point3 { - self.rot.rotate_point3( &point.mul_s( self.scale.clone() )).add_v( &self.disp ) + self.rot.rotate_point( &point.mul_s( self.scale.clone() )).add_v( &self.disp ) } } From 6dd06103fcad869dc5edfef13de310787ae1509c Mon Sep 17 00:00:00 2001 From: kvark Date: Fri, 1 Nov 2013 08:29:01 -0400 Subject: [PATCH 3/5] Generalized transform trait over any-dimensional vectors and points --- src/cgmath/array.rs | 12 +++++++++++ src/cgmath/rotation.rs | 9 +++++--- src/cgmath/transform.rs | 46 +++++++++++++++++++++++++++-------------- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/cgmath/array.rs b/src/cgmath/array.rs index 6e06df9..b50c9c4 100644 --- a/src/cgmath/array.rs +++ b/src/cgmath/array.rs @@ -44,6 +44,18 @@ pub trait Array fn each_mut(&mut self, f: &fn(i: uint, x: &mut T)); } +/*impl //TODO +< + T: Clone, + Slice, + A: Array +> +Clone for A { + fn clone(&self) -> A { + self.build(|i| self.i(i).clone()) + } +}*/ + macro_rules! array( (impl<$S:ident> $Self:ty -> [$T:ty, ..$n:expr] $_n:ident) => ( impl<$S: Clone> Array<$T, [$T,..$n]> for $Self { diff --git a/src/cgmath/rotation.rs b/src/cgmath/rotation.rs index 4da5b96..1673055 100644 --- a/src/cgmath/rotation.rs +++ b/src/cgmath/rotation.rs @@ -14,6 +14,7 @@ // limitations under the License. use angle::Rad; +use array::Array; use matrix::Matrix; use matrix::{Mat2, ToMat2}; use matrix::{Mat3, ToMat3}; @@ -25,10 +26,10 @@ use vector::{Vector, Vec2, Vec3}; /// A trait for generic rotation pub trait Rotation < - S: Primitive + Clone, + S: Primitive, Slice, V: Vector, - P: Point + Clone + P: Point > : Eq + ApproxEq @@ -38,7 +39,9 @@ pub trait Rotation #[inline] fn rotate_ray(&self, ray: &Ray) -> Ray { - Ray::new( ray.origin.clone(), self.rotate_vec(&ray.direction) ) + Ray::new( //FIXME: use clone derived from Array + Array::build(|i| ray.origin.i(i).clone()), + self.rotate_vec(&ray.direction) ) } fn concat(&self, other: &Self) -> Self; diff --git a/src/cgmath/transform.rs b/src/cgmath/transform.rs index 08ae398..1fd94af 100644 --- a/src/cgmath/transform.rs +++ b/src/cgmath/transform.rs @@ -14,9 +14,10 @@ // limitations under the License. use matrix::Mat4; -use point::{Point, Point3}; +use point::Point; use ray::Ray; -use rotation::Rotation3; +use rotation::Rotation; +use quaternion::Quat; use vector::{Vector, Vec3}; /// A trait of affine transformation, that can be applied to points or vectors @@ -42,29 +43,42 @@ pub struct AffineMatrix3 { mat: Mat4, } -/// A transformation in three dimensions consisting of a rotation, +/// A generic transformation consisting of a rotation, /// displacement vector and scale amount. -pub struct Transform3 { - rot: R, - disp: Vec3, +pub struct Decomposed { scale: S, + rot: R, + disp: V, } -impl> Transform3 { +impl +< + S: Float, + Slice, + V: Vector, + P: Point, + R: Rotation +> +Transform for Decomposed { #[inline] - pub fn new(rot: R, disp: Vec3, scale: S) -> Transform3 { - Transform3 { rot: rot, disp: disp, scale: scale } - } -} - -impl > Transform, Point3> for Transform3 { - #[inline] - fn transform_vec(&self, vec: &Vec3) -> Vec3 { + fn transform_vec(&self, vec: &V) -> V { self.rot.rotate_vec( &vec.mul_s( self.scale.clone() )) } #[inline] - fn transform_point(&self, point: &Point3) -> Point3 { + fn transform_point(&self, point: &P) -> P { self.rot.rotate_point( &point.mul_s( self.scale.clone() )).add_v( &self.disp ) } } + +/// A transformation in three dimensions consisting of a rotation, +/// displacement vector and scale amount. +pub struct Transform3( Decomposed,Quat> ); + +impl Transform3 { + #[inline] + pub fn new(scale: S, rot: Quat, disp: Vec3) -> Transform3 { + Transform3( Decomposed { scale: scale, rot: rot, disp: disp }) + } +} + From 04b257e217bbb07f6187da9b01f60ef40ee63255 Mon Sep 17 00:00:00 2001 From: kvark Date: Fri, 1 Nov 2013 10:32:29 -0400 Subject: [PATCH 4/5] Homogeneous transformations added for Point3; extend/truncate added for vectors; Transform3 is implemented for AffineMatrix3 --- src/cgmath/plane.rs | 3 +- src/cgmath/point.rs | 15 ++++++++- src/cgmath/transform.rs | 69 ++++++++++++++++++++++++++++++++--------- src/cgmath/vector.rs | 24 +++++++++++++- src/tests/point.rs | 22 +++++++++++++ src/tests/test.rs | 2 +- 6 files changed, 115 insertions(+), 20 deletions(-) create mode 100644 src/tests/point.rs diff --git a/src/cgmath/plane.rs b/src/cgmath/plane.rs index 85ee3a2..b744a08 100644 --- a/src/cgmath/plane.rs +++ b/src/cgmath/plane.rs @@ -14,6 +14,7 @@ // limitations under the License. use std::cast::transmute; +use std::fmt; use intersect::Intersect; use point::{Point, Point3}; @@ -21,8 +22,6 @@ use ray::Ray3; use vector::{Vec3, Vec4}; use vector::{Vector, EuclideanVector}; -use std::fmt; - /// A 3-dimendional plane formed from the equation: `a*x + b*y + c*z - d = 0`. /// /// # Fields diff --git a/src/cgmath/point.rs b/src/cgmath/point.rs index bc2cfb6..388d7be 100644 --- a/src/cgmath/point.rs +++ b/src/cgmath/point.rs @@ -18,7 +18,7 @@ //! not have a fixed position. use std::fmt; -use std::num::zero; +use std::num::{one,zero}; use array::*; use vector::*; @@ -54,6 +54,19 @@ impl Point3 { pub fn origin() -> Point3 { zero() } } +impl Point3 { + #[inline] + pub fn from_homogeneous(v: &Vec4) -> Point3 { + let _1 :S = one(); + let e = v.truncate().mul_s( _1 / v.w ); + Point3::new(e.x.clone(), e.y.clone(), e.z.clone()) //FIXME + } + #[inline] + pub fn to_homogeneous(&self) -> Vec4 { + Vec4::new(self.x.clone(), self.y.clone(), self.z.clone(), one()) + } +} + /// Specifies the numeric operations for point types. pub trait Point < diff --git a/src/cgmath/transform.rs b/src/cgmath/transform.rs index 1fd94af..613f12c 100644 --- a/src/cgmath/transform.rs +++ b/src/cgmath/transform.rs @@ -13,10 +13,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use matrix::Mat4; -use point::Point; +use std::num; + +use matrix::{Matrix, Mat4, ToMat4}; +use point::{Point, Point3}; use ray::Ray; -use rotation::Rotation; +use rotation::{Rotation, Rotation3}; use quaternion::Quat; use vector::{Vector, Vec3}; @@ -38,11 +40,6 @@ pub trait Transform } } -/// A homogeneous transformation matrix. -pub struct AffineMatrix3 { - mat: Mat4, -} - /// A generic transformation consisting of a rotation, /// displacement vector and scale amount. pub struct Decomposed { @@ -71,14 +68,56 @@ Transform for Decomposed { } } -/// A transformation in three dimensions consisting of a rotation, -/// displacement vector and scale amount. -pub struct Transform3( Decomposed,Quat> ); +pub trait Transform3 +: Transform, Point3> ++ ToMat4 +{} -impl Transform3 { - #[inline] - pub fn new(scale: S, rot: Quat, disp: Vec3) -> Transform3 { - Transform3( Decomposed { scale: scale, rot: rot, disp: disp }) +impl> +ToMat4 for Decomposed, R> { + fn to_mat4(&self) -> Mat4 { + let mut m = self.rot.to_mat3().mul_s( self.scale.clone() ).to_mat4(); + m.w = self.disp.extend( num::one() ); + m + } +} + +impl> +Transform3 for Decomposed,R> {} + +/// A homogeneous transformation matrix. +pub struct AffineMatrix3 { + mat: Mat4, +} + +impl +Transform, Point3> for AffineMatrix3 { + #[inline] + fn transform_vec(&self, vec: &Vec3) -> Vec3 { + self.mat.mul_v( &vec.extend(num::zero()) ).truncate() + } + + #[inline] + fn transform_point(&self, point: &Point3) -> Point3 { + Point3::from_homogeneous( &self.mat.mul_v( &point.to_homogeneous() )) + } +} + +impl +ToMat4 for AffineMatrix3 { + #[inline] fn to_mat4(&self) -> Mat4 { self.mat.clone() } +} + + + +/// A transformation in three dimensions consisting of a rotation, +/// displacement vector and scale amount. +pub struct Transform3D( Decomposed,Quat> ); + +impl Transform3D { + #[inline] + pub fn new(scale: S, rot: Quat, disp: Vec3) -> Transform3D { + Transform3D( Decomposed { scale: scale, rot: rot, disp: disp }) } } diff --git a/src/cgmath/vector.rs b/src/cgmath/vector.rs index bc8f8b5..9ff3ed3 100644 --- a/src/cgmath/vector.rs +++ b/src/cgmath/vector.rs @@ -31,7 +31,7 @@ pub struct Vec3 { x: S, y: S, z: S } #[deriving(Eq, Clone, Zero)] pub struct Vec4 { x: S, y: S, z: S, w: S } -// Conversion traits +// Conversion traits //FIXME: not used anywhere? pub trait ToVec2 { fn to_vec2(&self) -> Vec2; } pub trait ToVec3 { fn to_vec3(&self) -> Vec3; } pub trait ToVec4 { fn to_vec4(&self) -> Vec4; } @@ -70,12 +70,28 @@ impl Vec2 { #[inline] pub fn unit_x() -> Vec2 { Vec2::new(one(), zero()) } #[inline] pub fn unit_y() -> Vec2 { Vec2::new(zero(), one()) } } +impl Vec2 { + #[inline] + pub fn extend(&self, z: S)-> Vec3 { + Vec3::new(self.x.clone(), self.y.clone(), z) + } +} impl Vec3 { #[inline] pub fn unit_x() -> Vec3 { Vec3::new(one(), zero(), zero()) } #[inline] pub fn unit_y() -> Vec3 { Vec3::new(zero(), one(), zero()) } #[inline] pub fn unit_z() -> Vec3 { Vec3::new(zero(), zero(), one()) } } +impl Vec3 { + #[inline] + pub fn extend(&self, w: S)-> Vec4 { + Vec4::new(self.x.clone(), self.y.clone(), self.z.clone(), w) + } + #[inline] + pub fn truncate(&self)-> Vec2 { + Vec2::new(self.x.clone(), self.y.clone()) //ignore Z + } +} impl Vec4 { #[inline] pub fn unit_x() -> Vec4 { Vec4::new(one(), zero(), zero(), zero()) } @@ -83,6 +99,12 @@ impl Vec4 { #[inline] pub fn unit_z() -> Vec4 { Vec4::new(zero(), zero(), one(), zero()) } #[inline] pub fn unit_w() -> Vec4 { Vec4::new(zero(), zero(), zero(), one()) } } +impl Vec4 { + #[inline] + pub fn truncate(&self)-> Vec3 { + Vec3::new(self.x.clone(), self.y.clone(), self.z.clone()) //ignore W + } +} array!(impl Vec2 -> [S, ..2] _2) array!(impl Vec3 -> [S, ..3] _3) diff --git a/src/tests/point.rs b/src/tests/point.rs new file mode 100644 index 0000000..2079c64 --- /dev/null +++ b/src/tests/point.rs @@ -0,0 +1,22 @@ +// Copyright 2013 The CGMath Developers. For a full listing of the authors, +// refer to the AUTHORS file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use cgmath::point::*; + +#[test] +fn test_homogeneous() { + let p = Point3::new(1.0, 2.0, 3.0); + assert_eq!(p, Point3::from_homogeneous( &p.to_homogeneous() )); +} diff --git a/src/tests/test.rs b/src/tests/test.rs index 693cedf..223ff9d 100644 --- a/src/tests/test.rs +++ b/src/tests/test.rs @@ -22,7 +22,7 @@ pub mod vector; pub mod angle; pub mod plane; -// pub mod point; +pub mod point; // pub mod ray; // pub mod rotation; From 364d9597840c0ece433af53ee86f6273e0ff1a09 Mon Sep 17 00:00:00 2001 From: kvark Date: Fri, 1 Nov 2013 19:42:09 -0400 Subject: [PATCH 5/5] Fixed tests to compile; added Point homogeneous transform & test; added Transform inversion & test; Implemented Transform for AffineMatrix3 --- src/cgmath/rotation.rs | 12 +++++++- src/cgmath/transform.rs | 47 +++++++++++++++++++++++++++- src/cgmath/vector.rs | 2 +- src/tests/matrix.rs | 4 +++ src/tests/plane.rs | 14 +++++---- src/tests/point.rs | 2 +- src/tests/test.rs | 3 ++ src/tests/transform.rs | 27 ++++++++++++++++ src/tests/vector.rs | 68 ++++++++++++++++++++--------------------- 9 files changed, 135 insertions(+), 44 deletions(-) create mode 100644 src/tests/transform.rs diff --git a/src/cgmath/rotation.rs b/src/cgmath/rotation.rs index 1673055..6eba8fc 100644 --- a/src/cgmath/rotation.rs +++ b/src/cgmath/rotation.rs @@ -34,6 +34,7 @@ pub trait Rotation : Eq + ApproxEq { + fn identity() -> Self; fn rotate_point(&self, point: &P) -> P; fn rotate_vec(&self, vec: &V) -> V; @@ -111,6 +112,9 @@ impl ToMat2 for Basis2 { } impl Rotation, Point2> for Basis2 { + #[inline] + fn identity() -> Basis2 { Basis2{ mat: Mat2::identity() } } + #[inline] fn rotate_point(&self, _point: &Point2) -> Point2 { fail!("Not yet implemented") } @@ -229,6 +233,9 @@ impl ToQuat for Basis3 { } impl Rotation, Point3> for Basis3 { + #[inline] + fn identity() -> Basis3 { Basis3{ mat: Mat3::identity() } } + #[inline] fn rotate_point(&self, _point: &Point3) -> Point3 { fail!("Not yet implemented") } @@ -288,6 +295,9 @@ impl ToQuat for Quat { } impl Rotation, Point3> for Quat { + #[inline] + fn identity() -> Quat { Quat::identity() } + #[inline] fn rotate_point(&self, _point: &Point3) -> Point3 { fail!("Not yet implemented") } @@ -310,4 +320,4 @@ impl Rotation, Point3> for Quat { fn invert_self(&mut self) { *self = self.invert() } } -impl Rotation3 for Quat {} \ No newline at end of file +impl Rotation3 for Quat {} diff --git a/src/cgmath/transform.rs b/src/cgmath/transform.rs index 613f12c..e7e7847 100644 --- a/src/cgmath/transform.rs +++ b/src/cgmath/transform.rs @@ -31,13 +31,23 @@ pub trait Transform P: Point > { + fn identity() -> Self; fn transform_vec(&self, vec: &V) -> V; fn transform_point(&self, point: &P) -> P; + fn invert(&self) -> Option; #[inline] fn transform_ray(&self, ray: &Ray) -> Ray { Ray::new( self.transform_point(&ray.origin), self.transform_vec(&ray.direction) ) } + + #[inline] + fn invert_self(&mut self)-> bool { + match self.invert() { + Some(t) => {*self = t; true}, + None => false, + } + } } /// A generic transformation consisting of a rotation, @@ -57,6 +67,15 @@ impl R: Rotation > Transform for Decomposed { + #[inline] + fn identity() -> Decomposed { + Decomposed { + scale: num::one(), + rot: Rotation::identity(), + disp: num::zero(), + } + } + #[inline] fn transform_vec(&self, vec: &V) -> V { self.rot.rotate_vec( &vec.mul_s( self.scale.clone() )) @@ -66,6 +85,23 @@ Transform for Decomposed { fn transform_point(&self, point: &P) -> P { self.rot.rotate_point( &point.mul_s( self.scale.clone() )).add_v( &self.disp ) } + + #[inline] + fn invert(&self) -> Option> { + if self.scale.approx_eq( &num::zero() ) { + None + }else { + let _1 : S = num::one(); + let s = _1 / self.scale; + let r = self.rot.invert(); + let d = r.rotate_vec( &self.disp ).mul_s( -s ); + Some( Decomposed { + scale: s, + rot: r, + disp: d, + }) + } + } } pub trait Transform3 @@ -92,6 +128,11 @@ pub struct AffineMatrix3 { impl Transform, Point3> for AffineMatrix3 { + #[inline] + fn identity() -> AffineMatrix3 { + AffineMatrix3 { mat: Mat4::identity() } + } + #[inline] fn transform_vec(&self, vec: &Vec3) -> Vec3 { self.mat.mul_v( &vec.extend(num::zero()) ).truncate() @@ -100,6 +141,11 @@ Transform, Point3> for AffineMatrix3 { #[inline] fn transform_point(&self, point: &Point3) -> Point3 { Point3::from_homogeneous( &self.mat.mul_v( &point.to_homogeneous() )) + } + + #[inline] + fn invert(&self) -> Option> { + self.mat.invert().map(|m| AffineMatrix3{ mat: m }) } } @@ -120,4 +166,3 @@ impl Transform3D { Transform3D( Decomposed { scale: scale, rot: rot, disp: disp }) } } - diff --git a/src/cgmath/vector.rs b/src/cgmath/vector.rs index 9ff3ed3..1ecd665 100644 --- a/src/cgmath/vector.rs +++ b/src/cgmath/vector.rs @@ -55,7 +55,7 @@ macro_rules! vec( #[inline] pub fn zero() -> $Self<$S> { $Self::from_value(zero()) } - /// The additive identity of the vector. + /// The multiplicative identity of the vector. #[inline] pub fn ident() -> $Self<$S> { $Self::from_value(one()) } } diff --git a/src/tests/matrix.rs b/src/tests/matrix.rs index dbdf74b..0ca38c2 100644 --- a/src/tests/matrix.rs +++ b/src/tests/matrix.rs @@ -15,10 +15,12 @@ use cgmath::matrix::*; use cgmath::vector::*; +type float = f64; pub mod mat2 { use cgmath::matrix::*; use cgmath::vector::*; + type float = f64; pub static A: Mat2 = Mat2 { x: Vec2 { x: 1.0, y: 3.0 }, y: Vec2 { x: 2.0, y: 4.0 } }; @@ -34,6 +36,7 @@ pub mod mat2 { pub mod mat3 { use cgmath::matrix::*; use cgmath::vector::*; + type float = f64; pub static A: Mat3 = Mat3 { x: Vec3 { x: 1.0, y: 4.0, z: 7.0 }, y: Vec3 { x: 2.0, y: 5.0, z: 8.0 }, @@ -55,6 +58,7 @@ pub mod mat3 { pub mod mat4 { use cgmath::matrix::*; use cgmath::vector::*; + type float = f64; pub static A: Mat4 = Mat4 { x: Vec4 { x: 1.0, y: 5.0, z: 9.0, w: 13.0 }, y: Vec4 { x: 2.0, y: 6.0, z: 10.0, w: 14.0 }, diff --git a/src/tests/plane.rs b/src/tests/plane.rs index 61830ad..422e352 100644 --- a/src/tests/plane.rs +++ b/src/tests/plane.rs @@ -18,11 +18,13 @@ use cgmath::point::*; #[test] fn test_from_points() { - assert_eq!(Plane::from_points(Point3::new(5f, 0f, 5f), - Point3::new(5f, 5f, 5f), - Point3::new(5f, 0f, -1f)), Some(Plane::from_abcd(-1f, 0f, 0f, 5f))); + assert_eq!(Plane::from_points(Point3::new(5.0, 0.0, 5.0), + Point3::new(5.0, 5.0, 5.0), + Point3::new(5.0, 0.0, -1.0)), + Some(Plane::from_abcd(-1.0, 0.0, 0.0, 5.0))); - assert_eq!(Plane::from_points(Point3::new(0f, 5f, -5f), - Point3::new(0f, 5f, 0f), - Point3::new(0f, 5f, 5f)), None); // The points are parallel + assert_eq!(Plane::from_points(Point3::new(0.0, 5.0, -5.0), + Point3::new(0.0, 5.0, 0.0), + Point3::new(0.0, 5.0, 5.0)), + None); // The points are parallel } diff --git a/src/tests/point.rs b/src/tests/point.rs index 2079c64..b61954e 100644 --- a/src/tests/point.rs +++ b/src/tests/point.rs @@ -18,5 +18,5 @@ use cgmath::point::*; #[test] fn test_homogeneous() { let p = Point3::new(1.0, 2.0, 3.0); - assert_eq!(p, Point3::from_homogeneous( &p.to_homogeneous() )); + assert_approx_eq!(p, Point3::from_homogeneous( &p.to_homogeneous() )); } diff --git a/src/tests/test.rs b/src/tests/test.rs index 223ff9d..020ef75 100644 --- a/src/tests/test.rs +++ b/src/tests/test.rs @@ -13,6 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[feature(globs)]; + extern mod cgmath; // pub mod array; @@ -25,6 +27,7 @@ pub mod plane; pub mod point; // pub mod ray; // pub mod rotation; +pub mod transform; // pub mod projection; diff --git a/src/tests/transform.rs b/src/tests/transform.rs new file mode 100644 index 0000000..be81359 --- /dev/null +++ b/src/tests/transform.rs @@ -0,0 +1,27 @@ +// Copyright 2013 The CGMath Developers. For a full listing of the authors, +// refer to the AUTHORS file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use cgmath::quaternion::*; +use cgmath::transform::*; +use cgmath::vector::*; + +#[test] +fn test_invert() { + let v = Vec3::new(1.0, 2.0, 3.0); + let t = Transform3D::new( 1.5, Quat::new(0.5,0.5,0.5,0.5), Vec3::new(6.0,-7.0,8.0) ); + let ti = t.invert().expect("Expected successful inversion"); + let vt = t.transform_vec( &v ); + assert_approx_eq!(v, ti.transform_vec( &vt )); +} diff --git a/src/tests/vector.rs b/src/tests/vector.rs index 5e7159b..457b4c2 100644 --- a/src/tests/vector.rs +++ b/src/tests/vector.rs @@ -36,9 +36,9 @@ fn test_comp_add() { assert_eq!(Vec3::new(1, 2, 3).comp_add(), 6); assert_eq!(Vec4::new(1, 2, 3, 4).comp_add(), 10); - assert_eq!(Vec2::new(3f, 4f).comp_add(), 7f); - assert_eq!(Vec3::new(4f, 5f, 6f).comp_add(), 15f); - assert_eq!(Vec4::new(5f, 6f, 7f, 8f).comp_add(), 26f); + assert_eq!(Vec2::new(3.0, 4.0).comp_add(), 7.0); + assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_add(), 15.0); + assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_add(), 26.0); } #[test] @@ -47,9 +47,9 @@ fn test_comp_mul() { assert_eq!(Vec3::new(1, 2, 3).comp_mul(), 6); assert_eq!(Vec4::new(1, 2, 3, 4).comp_mul(), 24); - assert_eq!(Vec2::new(3f, 4f).comp_mul(), 12f); - assert_eq!(Vec3::new(4f, 5f, 6f).comp_mul(), 120f); - assert_eq!(Vec4::new(5f, 6f, 7f, 8f).comp_mul(), 1680f); + assert_eq!(Vec2::new(3.0, 4.0).comp_mul(), 12.0); + assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_mul(), 120.0); + assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_mul(), 1680.0); } #[test] @@ -58,9 +58,9 @@ fn test_comp_min() { assert_eq!(Vec3::new(1, 2, 3).comp_min(), 1); assert_eq!(Vec4::new(1, 2, 3, 4).comp_min(), 1); - assert_eq!(Vec2::new(3f, 4f).comp_min(), 3f); - assert_eq!(Vec3::new(4f, 5f, 6f).comp_min(), 4f); - assert_eq!(Vec4::new(5f, 6f, 7f, 8f).comp_min(), 5f); + assert_eq!(Vec2::new(3.0, 4.0).comp_min(), 3.0); + assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_min(), 4.0); + assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_min(), 5.0); } #[test] @@ -69,9 +69,9 @@ fn test_comp_max() { assert_eq!(Vec3::new(1, 2, 3).comp_max(), 3); assert_eq!(Vec4::new(1, 2, 3, 4).comp_max(), 4); - assert_eq!(Vec2::new(3f, 4f).comp_max(), 4f); - assert_eq!(Vec3::new(4f, 5f, 6f).comp_max(), 6f); - assert_eq!(Vec4::new(5f, 6f, 7f, 8f).comp_max(), 8f); + assert_eq!(Vec2::new(3.0, 4.0).comp_max(), 4.0); + assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_max(), 6.0); + assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_max(), 8.0); } #[test] @@ -88,9 +88,9 @@ fn test_cross() { #[test] fn test_is_perpendicular() { - assert!(Vec2::new(1f, 0f).is_perpendicular(&Vec2::new(0f, 1f))); - assert!(Vec3::new(0f, 1f, 0f).is_perpendicular(&Vec3::new(0f, 0f, 1f))); - assert!(Vec4::new(1f, 0f, 0f, 0f).is_perpendicular(&Vec4::new(0f, 0f, 0f, 1f))); + assert!(Vec2::new(1.0, 0.0).is_perpendicular(&Vec2::new(0.0, 1.0))); + assert!(Vec3::new(0.0, 1.0, 0.0).is_perpendicular(&Vec3::new(0.0, 0.0, 1.0))); + assert!(Vec4::new(1.0, 0.0, 0.0, 0.0).is_perpendicular(&Vec4::new(0.0, 0.0, 0.0, 1.0))); } #[cfg(test)] @@ -99,8 +99,8 @@ mod test_length { #[test] fn test_vec2(){ - let (a, a_res) = (Vec2::new(3f, 4f), 5f); // (3, 4, 5) Pythagorean triple - let (b, b_res) = (Vec2::new(5f, 12f), 13f); // (5, 12, 13) Pythagorean triple + let (a, a_res) = (Vec2::new(3.0, 4.0), 5.0); // (3, 4, 5) Pythagorean triple + let (b, b_res) = (Vec2::new(5.0, 12.0), 13.0); // (5, 12, 13) Pythagorean triple assert_eq!(a.length2(), a_res * a_res); assert_eq!(b.length2(), b_res * b_res); @@ -111,8 +111,8 @@ mod test_length { #[test] fn test_vec3(){ - let (a, a_res) = (Vec3::new(2f, 3f, 6f), 7f); // (2, 3, 6, 7) Pythagorean quadruple - let (b, b_res) = (Vec3::new(1f, 4f, 8f), 9f); // (1, 4, 8, 9) Pythagorean quadruple + let (a, a_res) = (Vec3::new(2.0, 3.0, 6.0), 7.0); // (2, 3, 6, 7) Pythagorean quadruple + let (b, b_res) = (Vec3::new(1.0, 4.0, 8.0), 9.0); // (1, 4, 8, 9) Pythagorean quadruple assert_eq!(a.length2(), a_res * a_res); assert_eq!(b.length2(), b_res * b_res); @@ -123,8 +123,8 @@ mod test_length { #[test] fn test_vec4(){ - let (a, a_res) = (Vec4::new(1f, 2f, 4f, 10f), 11f); // (1, 2, 4, 10, 11) Pythagorean quintuple - let (b, b_res) = (Vec4::new(1f, 2f, 8f, 10f), 13f); // (1, 2, 8, 10, 13) Pythagorean quintuple + let (a, a_res) = (Vec4::new(1.0, 2.0, 4.0, 10.0), 11.0); // (1, 2, 4, 10, 11) Pythagorean quintuple + let (b, b_res) = (Vec4::new(1.0, 2.0, 8.0, 10.0), 13.0); // (1, 2, 8, 10, 13) Pythagorean quintuple assert_eq!(a.length2(), a_res * a_res); assert_eq!(b.length2(), b_res * b_res); @@ -136,23 +136,23 @@ mod test_length { #[test] fn test_angle() { - assert_approx_eq!(Vec2::new(1f, 0f).angle(&Vec2::new(0f, 1f)), rad(Real::frac_pi_2())); - assert_approx_eq!(Vec2::new(10f, 0f).angle(&Vec2::new(0f, 5f)), rad(Real::frac_pi_2())); - assert_approx_eq!(Vec2::new(-1f, 0f).angle(&Vec2::new(0f, 1f)), -rad(Real::frac_pi_2())); + assert_approx_eq!(Vec2::new(1.0, 0.0).angle(&Vec2::new(0.0, 1.0)), rad(Real::frac_pi_2())); + assert_approx_eq!(Vec2::new(10.0, 0.0).angle(&Vec2::new(0.0, 5.0)), rad(Real::frac_pi_2())); + assert_approx_eq!(Vec2::new(-1.0, 0.0).angle(&Vec2::new(0.0, 1.0)), -rad(Real::frac_pi_2())); - assert_approx_eq!(Vec3::new(1f, 0f, 1f).angle(&Vec3::new(1f, 1f, 0f)), rad(Real::frac_pi_3())); - assert_approx_eq!(Vec3::new(10f, 0f, 10f).angle(&Vec3::new(5f, 5f, 0f)), rad(Real::frac_pi_3())); - assert_approx_eq!(Vec3::new(-1f, 0f, -1f).angle(&Vec3::new(1f, -1f, 0f)), rad(2f * Real::frac_pi_3())); + assert_approx_eq!(Vec3::new(1.0, 0.0, 1.0).angle(&Vec3::new(1.0, 1.0, 0.0)), rad(Real::frac_pi_3())); + assert_approx_eq!(Vec3::new(10.0, 0.0, 10.0).angle(&Vec3::new(5.0, 5.0, 0.0)), rad(Real::frac_pi_3())); + assert_approx_eq!(Vec3::new(-1.0, 0.0, -1.0).angle(&Vec3::new(1.0, -1.0, 0.0)), rad(2.0 * Real::frac_pi_3())); - assert_approx_eq!(Vec4::new(1f, 0f, 1f, 0f).angle(&Vec4::new(0f, 1f, 0f, 1f)), rad(Real::frac_pi_2())); - assert_approx_eq!(Vec4::new(10f, 0f, 10f, 0f).angle(&Vec4::new(0f, 5f, 0f, 5f)), rad(Real::frac_pi_2())); - assert_approx_eq!(Vec4::new(-1f, 0f, -1f, 0f).angle(&Vec4::new(0f, 1f, 0f, 1f)), rad(Real::frac_pi_2())); + assert_approx_eq!(Vec4::new(1.0, 0.0, 1.0, 0.0).angle(&Vec4::new(0.0, 1.0, 0.0, 1.0)), rad(Real::frac_pi_2())); + assert_approx_eq!(Vec4::new(10.0, 0.0, 10.0, 0.0).angle(&Vec4::new(0.0, 5.0, 0.0, 5.0)), rad(Real::frac_pi_2())); + assert_approx_eq!(Vec4::new(-1.0, 0.0, -1.0, 0.0).angle(&Vec4::new(0.0, 1.0, 0.0, 1.0)), rad(Real::frac_pi_2())); } #[test] fn test_normalize() { - // TODO: test normalize_to, normalize_self, and normalize_self_to - assert_approx_eq!(Vec2::new(3f, 4f).normalize(), Vec2::new(3f/5f, 4f/5f)); - assert_approx_eq!(Vec3::new(2f, 3f, 6f).normalize(), Vec3::new(2f/7f, 3f/7f, 6f/7f)); - assert_approx_eq!(Vec4::new(1f, 2f, 4f, 10f).normalize(), Vec4::new(1f/11f, 2f/11f, 4f/11f, 10f/11f)); + // TODO: test normalize_to, normalize_sel.0, and normalize_self_to + assert_approx_eq!(Vec2::new(3.0, 4.0).normalize(), Vec2::new(3.0/5.0, 4.0/5.0)); + assert_approx_eq!(Vec3::new(2.0, 3.0, 6.0).normalize(), Vec3::new(2.0/7.0, 3.0/7.0, 6.0/7.0)); + assert_approx_eq!(Vec4::new(1.0, 2.0, 4.0, 10.0).normalize(), Vec4::new(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0)); }