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/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/ray.rs b/src/cgmath/ray.rs index ec6c06a..f9d4125 100644 --- a/src/cgmath/ray.rs +++ b/src/cgmath/ray.rs @@ -13,33 +13,29 @@ // 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}; +/// A generic ray #[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/rotation.rs b/src/cgmath/rotation.rs index 28dc015..6eba8fc 100644 --- a/src/cgmath/rotation.rs +++ b/src/cgmath/rotation.rs @@ -14,52 +14,72 @@ // limitations under the License. use angle::Rad; +use array::Array; 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, + Slice, + V: Vector, + P: Point +> +: Eq ++ ApproxEq +{ + fn identity() -> Self; + fn rotate_point(&self, point: &P) -> P; + fn rotate_vec(&self, vec: &V) -> V; + + #[inline] + fn rotate_ray(&self, ray: &Ray) -> Ray { + 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; + 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 +111,18 @@ 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 identity() -> Basis2 { Basis2{ mat: Mat2::identity() } } + + #[inline] + 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 +159,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 +232,18 @@ 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 identity() -> Basis3 { Basis3{ mat: Mat3::identity() } } + + #[inline] + 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 +280,8 @@ impl ApproxEq for Basis3 { } } +impl Rotation3 for Basis3 {} + // Quaternion Rotation impls impl ToBasis3 for Quat { @@ -264,15 +294,18 @@ 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 identity() -> Quat { Quat::identity() } + + #[inline] + 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 +319,5 @@ impl Rotation3 for Quat { #[inline] fn invert_self(&mut self) { *self = self.invert() } } + +impl Rotation3 for Quat {} diff --git a/src/cgmath/transform.rs b/src/cgmath/transform.rs index bb60df7..e7e7847 100644 --- a/src/cgmath/transform.rs +++ b/src/cgmath/transform.rs @@ -13,51 +13,156 @@ // See the License for the specific language governing permissions and // limitations under the License. -use matrix::Mat4; -use point::{Point,Point3}; -use ray::Ray3; -use rotation::Rotation3; -use vector::{Vector,Vec3}; +use std::num; +use matrix::{Matrix, Mat4, ToMat4}; +use point::{Point, Point3}; +use ray::Ray; +use rotation::{Rotation, Rotation3}; +use quaternion::Quat; +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 identity() -> Self; + fn transform_vec(&self, vec: &V) -> V; + fn transform_point(&self, point: &P) -> P; + fn invert(&self) -> Option; -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) ) + } + + #[inline] + fn invert_self(&mut self)-> bool { + match self.invert() { + Some(t) => {*self = t; true}, + None => false, + } } } +/// A generic transformation consisting of a rotation, +/// displacement vector and scale amount. +pub struct Decomposed { + scale: S, + rot: R, + disp: V, +} + +impl +< + S: Float, + Slice, + V: Vector, + P: Point, + 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() )) + } + + #[inline] + 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 +: Transform, Point3> ++ ToMat4 +{} + +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 identity() -> AffineMatrix3 { + AffineMatrix3 { mat: Mat4::identity() } + } + + #[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() )) + } + + #[inline] + fn invert(&self) -> Option> { + self.mat.invert().map(|m| AffineMatrix3{ mat: m }) + } +} + +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 { - rot: R, - disp: Vec3, - scale: S, -} +pub struct Transform3D( Decomposed,Quat> ); -impl> Transform3D { +impl Transform3D { #[inline] - pub fn new(rot: R, disp: Vec3, scale: S) -> Transform3D { - Transform3D { rot: rot, disp: disp, scale: scale } - } -} - -impl > Transform3 for Transform3D { - #[inline] - fn transform_vec3(&self, vec: &Vec3) -> Vec3 { - self.rot.rotate_vec3( &vec.mul_s( self.scale.clone() )) - } - - #[inline] - fn transform_point3(&self, point: &Point3) -> Point3 { - self.rot.rotate_point3( &point.mul_s( self.scale.clone() )).add_v( &self.disp ) + 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..1ecd665 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; } @@ -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()) } } @@ -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/matrix.rs b/src/tests/matrix.rs index 6d67e4a..7edda32 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 cceefc4..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(5f64, 0f64, 5f64), - Point3::new(5f64, 5f64, 5f64), - Point3::new(5f64, 0f64, -1f64)), Some(Plane::from_abcd(-1f64, 0f64, 0f64, 5f64))); + 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(0f64, 5f64, -5f64), - Point3::new(0f64, 5f64, 0f64), - Point3::new(0f64, 5f64, 5f64)), 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 new file mode 100644 index 0000000..b61954e --- /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_approx_eq!(p, Point3::from_homogeneous( &p.to_homogeneous() )); +} diff --git a/src/tests/test.rs b/src/tests/test.rs index b2a4f6e..1621767 100644 --- a/src/tests/test.rs +++ b/src/tests/test.rs @@ -14,6 +14,8 @@ // limitations under the License. #[feature(globs)]; +#[feature(globs)]; + extern mod cgmath; // pub mod array; @@ -23,9 +25,10 @@ pub mod vector; pub mod angle; pub mod plane; -// pub mod point; +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 b1e5e19..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(3f64, 4f64).comp_add(), 7f64); - assert_eq!(Vec3::new(4f64, 5f64, 6f64).comp_add(), 15f64); - assert_eq!(Vec4::new(5f64, 6f64, 7f64, 8f64).comp_add(), 26f64); + 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(3f64, 4f64).comp_mul(), 12f64); - assert_eq!(Vec3::new(4f64, 5f64, 6f64).comp_mul(), 120f64); - assert_eq!(Vec4::new(5f64, 6f64, 7f64, 8f64).comp_mul(), 1680f64); + 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(3f64, 4f64).comp_min(), 3f64); - assert_eq!(Vec3::new(4f64, 5f64, 6f64).comp_min(), 4f64); - assert_eq!(Vec4::new(5f64, 6f64, 7f64, 8f64).comp_min(), 5f64); + 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(3f64, 4f64).comp_max(), 4f64); - assert_eq!(Vec3::new(4f64, 5f64, 6f64).comp_max(), 6f64); - assert_eq!(Vec4::new(5f64, 6f64, 7f64, 8f64).comp_max(), 8f64); + 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(1f64, 0f64).is_perpendicular(&Vec2::new(0f64, 1f64))); - assert!(Vec3::new(0f64, 1f64, 0f64).is_perpendicular(&Vec3::new(0f64, 0f64, 1f64))); - assert!(Vec4::new(1f64, 0f64, 0f64, 0f64).is_perpendicular(&Vec4::new(0f64, 0f64, 0f64, 1f64))); + 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(3f64, 4f64), 5f64); // (3, 4, 5) Pythagorean triple - let (b, b_res) = (Vec2::new(5f64, 12f64), 13f64); // (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(2f64, 3f64, 6f64), 7f64); // (2, 3, 6, 7) Pythagorean quadruple - let (b, b_res) = (Vec3::new(1f64, 4f64, 8f64), 9f64); // (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(1f64, 2f64, 4f64, 10f64), 11f64); // (1, 2, 4, 10, 11) Pythagorean quintuple - let (b, b_res) = (Vec4::new(1f64, 2f64, 8f64, 10f64), 13f64); // (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(1f64, 0f64).angle(&Vec2::new(0f64, 1f64)), rad(Real::frac_pi_2())); - assert_approx_eq!(Vec2::new(10f64, 0f64).angle(&Vec2::new(0f64, 5f64)), rad(Real::frac_pi_2())); - assert_approx_eq!(Vec2::new(-1f64, 0f64).angle(&Vec2::new(0f64, 1f64)), -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(1f64, 0f64, 1f64).angle(&Vec3::new(1f64, 1f64, 0f64)), rad(Real::frac_pi_3())); - assert_approx_eq!(Vec3::new(10f64, 0f64, 10f64).angle(&Vec3::new(5f64, 5f64, 0f64)), rad(Real::frac_pi_3())); - assert_approx_eq!(Vec3::new(-1f64, 0f64, -1f64).angle(&Vec3::new(1f64, -1f64, 0f64)), rad(2f64 * 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(1f64, 0f64, 1f64, 0f64).angle(&Vec4::new(0f64, 1f64, 0f64, 1f64)), rad(Real::frac_pi_2())); - assert_approx_eq!(Vec4::new(10f64, 0f64, 10f64, 0f64).angle(&Vec4::new(0f64, 5f64, 0f64, 5f64)), rad(Real::frac_pi_2())); - assert_approx_eq!(Vec4::new(-1f64, 0f64, -1f64, 0f64).angle(&Vec4::new(0f64, 1f64, 0f64, 1f64)), 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(3f64, 4f64).normalize(), Vec2::new(3f64/5f64, 4f64/5f64)); - assert_approx_eq!(Vec3::new(2f64, 3f64, 6f64).normalize(), Vec3::new(2f64/7f64, 3f64/7f64, 6f64/7f64)); - assert_approx_eq!(Vec4::new(1f64, 2f64, 4f64, 10f64).normalize(), Vec4::new(1f64/11f64, 2f64/11f64, 4f64/11f64, 10f64/11f64)); + // 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)); }