From 0e0107837d9c6a8b88d6737419ed5d70048ab542 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 20 Sep 2013 16:01:37 +1000 Subject: [PATCH] Remove old code Yayy! --- src-old/bounds/aabb.rs | 72 - src-old/bounds/bounds.rs | 27 - src-old/bounds/cylinder.rs | 25 - src-old/bounds/frustum.rs | 104 -- src-old/bounds/obb.rs | 32 - src-old/bounds/sphere.rs | 33 - src-old/lmath.rs | 45 - src-old/macros.rs | 73 -- src-old/math/macros.rs | 133 -- src-old/math/mat.rs | 1677 ------------------------ src-old/math/math.rs | 124 -- src-old/math/plane.rs | 187 --- src-old/math/point.rs | 357 ----- src-old/math/quat.rs | 269 ---- src-old/math/ray.rs | 51 - src-old/math/vec.rs | 2161 ------------------------------- src-old/space/bsp.rs | 16 - src-old/space/octree.rs | 23 - src-old/space/quadtree.rs | 19 - src-old/space/space.rs | 24 - src-old/transform/projection.rs | 326 ----- src-old/transform/rotation.rs | 645 --------- src-old/transform/transform.rs | 35 - 23 files changed, 6458 deletions(-) delete mode 100644 src-old/bounds/aabb.rs delete mode 100644 src-old/bounds/bounds.rs delete mode 100644 src-old/bounds/cylinder.rs delete mode 100644 src-old/bounds/frustum.rs delete mode 100644 src-old/bounds/obb.rs delete mode 100644 src-old/bounds/sphere.rs delete mode 100644 src-old/lmath.rs delete mode 100644 src-old/macros.rs delete mode 100644 src-old/math/macros.rs delete mode 100644 src-old/math/mat.rs delete mode 100644 src-old/math/math.rs delete mode 100644 src-old/math/plane.rs delete mode 100644 src-old/math/point.rs delete mode 100644 src-old/math/quat.rs delete mode 100644 src-old/math/ray.rs delete mode 100644 src-old/math/vec.rs delete mode 100644 src-old/space/bsp.rs delete mode 100644 src-old/space/octree.rs delete mode 100644 src-old/space/quadtree.rs delete mode 100644 src-old/space/space.rs delete mode 100644 src-old/transform/projection.rs delete mode 100644 src-old/transform/rotation.rs delete mode 100644 src-old/transform/transform.rs diff --git a/src-old/bounds/aabb.rs b/src-old/bounds/aabb.rs deleted file mode 100644 index 5dec48d..0000000 --- a/src-old/bounds/aabb.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Axis-aligned bounding boxes - -use math::*; - -#[deriving(Clone, Eq)] -pub struct AABB2 { - center: Point2, - size: Vec2, -} - -impl_approx!(AABB2 { center, size }) - -impl AABB2 { - #[inline] - pub fn new(center: Point2, size: Vec2) -> AABB2 { - AABB2 { center: center, size: size } - } -} - -impl AABB2 { - pub fn from_bounds(mn: Point2, mx: Point2) -> AABB2 { - AABB2 { - center: Point2::from_vec2( - mn.as_vec2().add_v(mx.as_vec2()).div_s(two!(T)) - ), - size: mx - mn, - } - } -} - -#[deriving(Clone, Eq)] -pub struct AABB3 { - center: Point3, - size: Vec3, -} - -impl_approx!(AABB3 { center, size }) - -impl AABB3 { - #[inline] - pub fn new(center: Point3, size: Vec3) -> AABB3 { - AABB3 { center: center, size: size } - } -} - -impl AABB3 { - pub fn from_bounds(mn: Point3, mx: Point3) -> AABB3 { - AABB3 { - center: Point3::from_vec3( - mn.as_vec3().add_v(mx.as_vec3()).div_s(two!(T)) - ), - size: mx - mn, - } - } - - // pub fn intersects_aabb3(&self, other: &AABB3) -> bool {} -} diff --git a/src-old/bounds/bounds.rs b/src-old/bounds/bounds.rs deleted file mode 100644 index ad44fd1..0000000 --- a/src-old/bounds/bounds.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Bounding volumes - -pub use self::aabb::{AABB2, AABB3}; -pub use self::frustum::{Frustum, FrustumPoints}; -pub use self::obb::{OBB2, OBB3}; -pub use self::sphere::Sphere; - -pub mod aabb; -pub mod cylinder; -pub mod frustum; -pub mod obb; -pub mod sphere; diff --git a/src-old/bounds/cylinder.rs b/src-old/bounds/cylinder.rs deleted file mode 100644 index e749ab0..0000000 --- a/src-old/bounds/cylinder.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Oriented bounding cylinder - -use math::*; - -#[deriving(Clone, Eq)] -pub struct Cylinder3 { - center: Point3, - axis: Vec3, - radius: T, -} diff --git a/src-old/bounds/frustum.rs b/src-old/bounds/frustum.rs deleted file mode 100644 index d23d307..0000000 --- a/src-old/bounds/frustum.rs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! View frustum for visibility determination - -use math::*; - -#[deriving(Clone, Eq)] -pub struct Frustum { - left: Plane3, - right: Plane3, - bottom: Plane3, - top: Plane3, - near: Plane3, - far: Plane3, -} - -impl_dimensioned!(Frustum, Plane3, 6) -impl_approx!(Frustum { - left, right, - top, bottom, - near, far -}) - -#[deriving(Clone, Eq)] -pub struct FrustumPoints { - near_top_left: Point3, - near_top_right: Point3, - near_bottom_left: Point3, - near_bottom_right: Point3, - far_top_left: Point3, - far_top_right: Point3, - far_bottom_left: Point3, - far_bottom_right: Point3, -} - -impl_dimensioned!(FrustumPoints, Point3, 8) -impl_approx!(FrustumPoints { - near_top_left, - near_top_right, - near_bottom_left, - near_bottom_right, - far_top_left, - far_top_right, - far_bottom_left, - far_bottom_right -}) - -impl Frustum { - /// Constructs a frustum - pub fn from_planes(left: Plane3, right: Plane3, - bottom: Plane3, top: Plane3, - near: Plane3, far: Plane3) -> Frustum { - Frustum { - left: left, - right: right, - bottom: bottom, - top: top, - near: near, - far: far, - } - } - - /// Extracts frustum planes from a projection matrix - pub fn from_matrix(mat: Mat4) -> Frustum { - Frustum { - left: Plane3::from_vec4(mat.r(3).add_v(&mat.r(0)).normalize()), - right: Plane3::from_vec4(mat.r(3).sub_v(&mat.r(0)).normalize()), - bottom: Plane3::from_vec4(mat.r(3).add_v(&mat.r(1)).normalize()), - top: Plane3::from_vec4(mat.r(3).sub_v(&mat.r(1)).normalize()), - near: Plane3::from_vec4(mat.r(3).add_v(&mat.r(2)).normalize()), - far: Plane3::from_vec4(mat.r(3).sub_v(&mat.r(2)).normalize()), - } - } -} - -impl Frustum { - /// Computes where the frustum planes intersect to form corners and returns - /// a struct containing the eight resulting position vectors. - pub fn to_points(&self) -> FrustumPoints { - FrustumPoints { - near_top_left: self.near.intersection_3pl(&self.top, &self.left).unwrap(), - near_top_right: self.near.intersection_3pl(&self.top, &self.right).unwrap(), - near_bottom_left: self.near.intersection_3pl(&self.bottom, &self.left).unwrap(), - near_bottom_right: self.near.intersection_3pl(&self.bottom, &self.right).unwrap(), - far_top_left: self.far.intersection_3pl(&self.top, &self.left).unwrap(), - far_top_right: self.far.intersection_3pl(&self.top, &self.right).unwrap(), - far_bottom_left: self.far.intersection_3pl(&self.bottom, &self.left).unwrap(), - far_bottom_right: self.far.intersection_3pl(&self.bottom, &self.right).unwrap(), - } - } -} diff --git a/src-old/bounds/obb.rs b/src-old/bounds/obb.rs deleted file mode 100644 index fabbd7c..0000000 --- a/src-old/bounds/obb.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Oriented bounding boxes - -use math::*; - -#[deriving(Clone, Eq)] -pub struct OBB2 { - center: Point2, - axis: Vec2, - extents: Vec2, -} - -#[deriving(Clone, Eq)] -pub struct OBB3 { - center: Point3, - axis: Vec3, - extents: Vec3, -} diff --git a/src-old/bounds/sphere.rs b/src-old/bounds/sphere.rs deleted file mode 100644 index bc45876..0000000 --- a/src-old/bounds/sphere.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Bounding sphere - -use math::*; - -#[deriving(Clone, Eq)] -pub struct Sphere { - center: Point3, - radius: T, -} - -impl_approx!(Sphere { center, radius }) - -impl Sphere { - #[inline] - pub fn new(center: Point3, radius: T) -> Sphere { - Sphere { center: center, radius: radius } - } -} diff --git a/src-old/lmath.rs b/src-old/lmath.rs deleted file mode 100644 index 2dcf25d..0000000 --- a/src-old/lmath.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 The Lmath 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. - -#[link(name = "lmath", - vers = "0.1.0", - uuid = "A2DEEB53-EB35-4B44-B247-9044B57E3BA5", - author = "Brendan Zabarauskas", - url = "https://github.com/bjz/lmath-rs")]; - -#[comment = "A mathematics library for computer graphics."]; -#[license = "ASL2"]; -#[crate_type = "lib"]; - -// Macros - -mod macros; -#[path = "math/macros.rs"] -mod math_macros; - -#[path = "math/math.rs"] -pub mod math; - -#[cfg(bounds)] -#[path = "bounds/bounds.rs"] -pub mod bounds; - -#[cfg(transform)] -#[path = "transform/transform.rs"] -pub mod transform; - -#[cfg(space)] -#[path = "space/space.rs"] -pub mod space; diff --git a/src-old/macros.rs b/src-old/macros.rs deleted file mode 100644 index a27c906..0000000 --- a/src-old/macros.rs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2013 The Lmath 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. - -#[macro_escape]; - -macro_rules! zero( - ($T:ty) => ({ - use std::num::Zero; - Zero::zero::<$T>() - }); -) - -macro_rules! one( - ($T:ty) => ({ - use std::num::One; - One::one::<$T>() - }); -) - -macro_rules! two( - ($T:ty) => (one!(T) + one!(T)); -) - -macro_rules! impl_approx( - ($T:ident { $($field:ident),+ }) => ( - impl> ApproxEq for $T { - #[inline] - pub fn approx_epsilon() -> T { - ApproxEq::approx_epsilon::() - } - - #[inline] - pub fn approx_eq(&self, other: &$T) -> bool { - self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) - } - - #[inline] - pub fn approx_eq_eps(&self, other: &$T, epsilon: &T) -> bool { - $( self.$field.approx_eq_eps(&other.$field, epsilon) )&&+ - } - } - ); - ($T:ident) => ( - impl> ApproxEq for $T { - #[inline] - pub fn approx_epsilon() -> T { - ApproxEq::approx_epsilon::() - } - - #[inline] - pub fn approx_eq(&self, other: &$T) -> bool { - self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) - } - - #[inline] - pub fn approx_eq_eps(&self, other: &$T, epsilon: &T) -> bool { - (**self).approx_eq_eps(&**other, epsilon) - } - } - ) -) diff --git a/src-old/math/macros.rs b/src-old/math/macros.rs deleted file mode 100644 index ba8ddf2..0000000 --- a/src-old/math/macros.rs +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2013 The Lmath 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. - -#[macro_escape]; - -macro_rules! impl_dimensioned( - ($Self:ident, $T:ty, $n:expr) => ( - impl Dimensioned<$T,[$T,..$n]> for $Self { - #[inline] - pub fn i<'a>(&'a self, i: uint) -> &'a $T { - &'a self.as_slice()[i] - } - - #[inline] - pub fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut $T { - &'a mut self.as_mut_slice()[i] - } - - #[inline] - pub fn as_slice<'a>(&'a self) -> &'a [$T,..$n] { - use std::cast::transmute; - unsafe { transmute(self) } - } - - #[inline] - pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [$T,..$n] { - use std::cast::transmute; - unsafe { transmute(self) } - } - } - ); - ($Self:ident) => ( - impl Dimensioned<$Self,[$Self,..1]> for $Self { - #[inline] - pub fn i<'a>(&'a self, i: uint) -> &'a $Self { - &'a self.as_slice()[i] - } - - #[inline] - pub fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut $Self { - &'a mut self.as_mut_slice()[i] - } - - #[inline] - pub fn as_slice<'a>(&'a self) -> &'a [$Self,..1] { - use std::cast::transmute; - unsafe { transmute(self) } - } - - #[inline] - pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [$Self,..1] { - use std::cast::transmute; - unsafe { transmute(self) } - } - } - ) -) - -macro_rules! impl_to_vec( - ($Self:ident, 2) => (impl_to_vec_helper!(ToVec2, $Self, Vec2, to_vec2, as_vec2)); - ($Self:ident, 3) => (impl_to_vec_helper!(ToVec3, $Self, Vec3, to_vec3, as_vec3)); - ($Self:ident, 4) => (impl_to_vec_helper!(ToVec4, $Self, Vec4, to_vec4, as_vec4)); -) - -macro_rules! impl_to_vec_helper( - ($ToVec:ident, $Self:ident, $Vec:ident, $to_vec:ident, $as_vec:ident) => ( - impl $ToVec for $Self { - #[inline] - pub fn $to_vec(&self) -> $Vec { - self.$as_vec().clone() - } - } - ) -) - -macro_rules! impl_as_vec( - ($Self:ident, 2) => (impl_as_vec_helper!(AsVec2, $Self, Vec2, as_vec2, as_mut_vec2, with_vec2)); - ($Self:ident, 3) => (impl_as_vec_helper!(AsVec3, $Self, Vec3, as_vec3, as_mut_vec3, with_vec3)); - ($Self:ident, 4) => (impl_as_vec_helper!(AsVec4, $Self, Vec4, as_vec4, as_mut_vec4, with_vec4)); -) - -macro_rules! impl_as_vec_helper( - ($AsVec:ident, $Self:ident, $Vec:ident, $as_vec:ident, $as_mut_vec:ident, $with_vec:ident) => ( - impl $AsVec for $Self { - /// Safely transmute to a vec. - #[inline] - pub fn $as_vec<'a>(&'a self) -> &'a $Vec { - use std::cast::transmute; - unsafe { transmute(self) } - } - - /// Safely transmute to a mutable vec. - #[inline] - pub fn $as_mut_vec<'a>(&'a mut self) -> &'a mut $Vec { - use std::cast::transmute; - unsafe { transmute(self) } - } - - /// Operate on `self` transmuted to a vec, then return the result as - /// transmuted back to the `Self` type. - #[inline] - pub fn $with_vec<'a>(&'a self, f: &fn(&'a $Vec) -> $Vec) -> $Self { - use std::cast::transmute; - unsafe { transmute(f(self.$as_vec())) } - } - } - ) -) - -macro_rules! impl_swap_components( - ($Self:ident) => ( - impl SwapComponents for $Self { - #[inline] - pub fn swap(&mut self, a: uint, b: uint) { - let tmp = self.i(a).clone(); - *self.mut_i(a) = self.i(b).clone(); - *self.mut_i(b) = tmp; - } - } - ) -) diff --git a/src-old/math/mat.rs b/src-old/math/mat.rs deleted file mode 100644 index c2e0f77..0000000 --- a/src-old/math/mat.rs +++ /dev/null @@ -1,1677 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Matrix types - -use math::{Dimensioned, SwapComponents}; -use math::{Quat, ToQuat}; -use math::{Vec2, Vec3, Vec4}; - -pub trait Mat: Dimensioned - + SwapComponents { - pub fn c<'a>(&'a self, c: uint) -> &'a Vec; - pub fn r(&self, r: uint) -> Vec; - pub fn cr<'a>(&'a self, c: uint, r: uint) -> &'a T; - pub fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vec; - pub fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut T; - pub fn swap_c(&mut self, a: uint, b: uint); - pub fn swap_r(&mut self, a: uint, b: uint); - pub fn swap_cr(&mut self, a: (uint, uint), b: (uint, uint)); - pub fn transpose(&self) -> Self; - pub fn transpose_self(&mut self); -} - -pub trait NumMat: Mat + Neg { - pub fn mul_s(&self, value: T) -> Self; - pub fn mul_v(&self, vec: &Vec) -> Vec; - pub fn add_m(&self, other: &Self) -> Self; - pub fn sub_m(&self, other: &Self) -> Self; - pub fn mul_m(&self, other: &Self) -> Self; - pub fn mul_self_s(&mut self, value: T); - pub fn add_self_m(&mut self, other: &Self); - pub fn sub_self_m(&mut self, other: &Self); - pub fn dot(&self, other: &Self) -> T; - pub fn determinant(&self) -> T; - pub fn trace(&self) -> T; - pub fn to_identity(&mut self); - pub fn to_zero(&mut self); -} - -pub trait FloatMat: NumMat { - pub fn inverse(&self) -> Option; - pub fn invert_self(&mut self); - pub fn is_identity(&self) -> bool; - pub fn is_diagonal(&self) -> bool; - pub fn is_rotated(&self) -> bool; - pub fn is_symmetric(&self) -> bool; - pub fn is_invertible(&self) -> bool; -} - -#[deriving(Clone, Eq)] -pub struct Mat2 { - x: Vec2, - y: Vec2, -} - -// GLSL-style type aliases -pub type mat2 = Mat2; -pub type dmat2 = Mat2; - -// Rust-style type aliases -pub type Mat2f = Mat2; -pub type Mat2f32 = Mat2; -pub type Mat2f64 = Mat2; - -impl_dimensioned!(Mat2, Vec2, 2) -impl_swap_components!(Mat2) -impl_approx!(Mat3 { x, y, z }) - -pub trait ToMat2 { - pub fn to_mat2(&self) -> Mat2; -} - -impl Mat2 { - #[inline] - pub fn new(c0r0: T, c0r1: T, - c1r0: T, c1r1: T) -> Mat2 { - Mat2::from_cols(Vec2::new(c0r0, c0r1), - Vec2::new(c1r0, c1r1)) - } - - #[inline] - pub fn from_cols(c0: Vec2, - c1: Vec2) -> Mat2 { - Mat2 { x: c0, y: c1 } - } -} - -impl Mat,[Vec2,..2]> for Mat2 { - #[inline] - pub fn c<'a>(&'a self, c: uint) -> &'a Vec2 { - self.i(c) - } - - #[inline] - pub fn r(&self, r: uint) -> Vec2 { - Vec2::new(self.i(0).i(r).clone(), - self.i(1).i(r).clone()) - } - - #[inline] - pub fn cr<'a>(&'a self, c: uint, r: uint) -> &'a T { - self.i(c).i(r) - } - - #[inline] - pub fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vec2 { - self.mut_i(c) - } - - #[inline] - pub fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut T { - self.mut_i(c).mut_i(r) - } - - #[inline] - pub fn swap_c(&mut self, a: uint, b: uint) { - let tmp = self.c(a).clone(); - *self.mut_c(a) = self.c(b).clone(); - *self.mut_c(b) = tmp; - } - - #[inline] - pub fn swap_r(&mut self, a: uint, b: uint) { - self.mut_c(0).swap(a, b); - self.mut_c(1).swap(a, b); - } - - #[inline] - pub fn swap_cr(&mut self, (col_a, row_a): (uint, uint), - (col_b, row_b): (uint, uint)) { - let tmp = self.cr(col_a, row_a).clone(); - *self.mut_cr(col_a, row_a) = self.cr(col_b, row_b).clone(); - *self.mut_cr(col_b, row_b) = tmp; - } - - #[inline] - pub fn transpose(&self) -> Mat2 { - Mat2::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), - self.cr(0, 1).clone(), self.cr(1, 1).clone()) - } - - #[inline] - pub fn transpose_self(&mut self) { - self.swap_cr((0, 1), (1, 0)); - } -} - -impl ToMat3 for Mat2 { - #[inline] - pub fn to_mat3(&self) -> Mat3 { - Mat3::new(self.cr(0, 0).clone(), self.cr(0, 1).clone(), zero!(T), - self.cr(1, 0).clone(), self.cr(1, 1).clone(), zero!(T), - zero!(T), zero!(T), one!(T)) - } -} - -impl ToMat4 for Mat2 { - #[inline] - pub fn to_mat4(&self) -> Mat4 { - Mat4::new(self.cr(0, 0).clone(), self.cr(0, 1).clone(), zero!(T), zero!(T), - self.cr(1, 0).clone(), self.cr(1, 1).clone(), zero!(T), zero!(T), - zero!(T), zero!(T), one!(T), zero!(T), - zero!(T), zero!(T), zero!(T), one!(T)) - } -} - -impl Mat2 { - #[inline] - pub fn identity() -> Mat2 { - Mat2::from_cols(Vec2::unit_x(), - Vec2::unit_y()) - } - - #[inline] - pub fn zero() -> Mat2 { - Mat2::from_cols(Vec2::zero(), - Vec2::zero()) - } -} - -impl Mat2 { - #[inline] - pub fn from_value(value: T) -> Mat2 { - Mat2::new(value.clone(), zero!(T), - zero!(T), value.clone()) - } -} - -impl NumMat,[Vec2,..2]> for Mat2 { - #[inline] - pub fn mul_s(&self, value: T) -> Mat2 { - Mat2::from_cols(self.c(0).mul_s(value.clone()), - self.c(1).mul_s(value.clone())) - } - - #[inline] - pub fn mul_v(&self, vec: &Vec2) -> Vec2 { - Vec2::new(self.r(0).dot(vec), - self.r(1).dot(vec)) - } - - #[inline] - pub fn add_m(&self, other: &Mat2) -> Mat2 { - Mat2::from_cols(self.c(0).add_v(other.c(0)), - self.c(1).add_v(other.c(1))) - } - - #[inline] - pub fn sub_m(&self, other: &Mat2) -> Mat2 { - Mat2::from_cols(self.c(0).sub_v(other.c(0)), - self.c(1).sub_v(other.c(1))) - } - - #[inline] - pub fn mul_m(&self, other: &Mat2) -> Mat2 { - Mat2::new(self.r(0).dot(other.c(0)), self.r(1).dot(other.c(0)), - self.r(0).dot(other.c(1)), self.r(1).dot(other.c(1))) - } - - #[inline] - pub fn mul_self_s(&mut self, value: T) { - self.mut_c(0).mul_self_s(value.clone()); - self.mut_c(1).mul_self_s(value.clone()); - } - - #[inline] - pub fn add_self_m(&mut self, other: &Mat2) { - self.mut_c(0).add_self_v(other.c(0)); - self.mut_c(1).add_self_v(other.c(1)); - } - - #[inline] - pub fn sub_self_m(&mut self, other: &Mat2) { - self.mut_c(0).sub_self_v(other.c(0)); - self.mut_c(1).sub_self_v(other.c(1)); - } - - pub fn dot(&self, other: &Mat2) -> T { - other.transpose().mul_m(self).trace() - } - - pub fn determinant(&self) -> T { - *self.cr(0, 0) * *self.cr(1, 1) - *self.cr(1, 0) * *self.cr(0, 1) - } - - pub fn trace(&self) -> T { - *self.cr(0, 0) + *self.cr(1, 1) - } - - #[inline] - pub fn to_identity(&mut self) { - *self = Mat2::identity(); - } - - #[inline] - pub fn to_zero(&mut self) { - *self = Mat2::zero(); - } -} - -impl Neg> for Mat2 { - #[inline] - pub fn neg(&self) -> Mat2 { - Mat2::from_cols(-*self.c(0), - -*self.c(1)) - } -} - -impl Mat2 { - #[inline] - pub fn from_angle(radians: T) -> Mat2 { - let cos_theta = radians.cos(); - let sin_theta = radians.sin(); - - Mat2::new(cos_theta.clone(), -sin_theta.clone(), - sin_theta.clone(), cos_theta.clone()) - } -} - -impl FloatMat,[Vec2,..2]> for Mat2 { - #[inline] - pub fn inverse(&self) -> Option> { - let d = self.determinant(); - if d.approx_eq(&zero!(T)) { - None - } else { - Some(Mat2::new(self.cr(1, 1) / d, -self.cr(0, 1) / d, - -self.cr(1, 0) / d, self.cr(0, 0) / d)) - } - } - - #[inline] - pub fn invert_self(&mut self) { - *self = self.inverse().expect("Couldn't invert the matrix!"); - } - - #[inline] - pub fn is_identity(&self) -> bool { - self.approx_eq(&Mat2::identity()) - } - - #[inline] - pub fn is_diagonal(&self) -> bool { - self.cr(0, 1).approx_eq(&zero!(T)) && - self.cr(1, 0).approx_eq(&zero!(T)) - } - - #[inline] - pub fn is_rotated(&self) -> bool { - !self.approx_eq(&Mat2::identity()) - } - - #[inline] - pub fn is_symmetric(&self) -> bool { - self.cr(0, 1).approx_eq(self.cr(1, 0)) && - self.cr(1, 0).approx_eq(self.cr(0, 1)) - } - - #[inline] - pub fn is_invertible(&self) -> bool { - !self.determinant().approx_eq(&zero!(T)) - } -} - -#[cfg(test)] -mod mat2_tests{ - use math::mat::*; - use math::vec::*; - - static A: Mat2 = Mat2 { x: Vec2 { x: 1.0, y: 3.0 }, - y: Vec2 { x: 2.0, y: 4.0 } }; - static B: Mat2 = Mat2 { x: Vec2 { x: 2.0, y: 4.0 }, - y: Vec2 { x: 3.0, y: 5.0 } }; - static C: Mat2 = Mat2 { x: Vec2 { x: 2.0, y: 1.0 }, - y: Vec2 { x: 1.0, y: 2.0 } }; - - static V: Vec2 = Vec2 { x: 1.0, y: 2.0 }; - static F: float = 0.5; - - #[test] - fn test_swap_c() { - let mut mut_a = A; - mut_a.swap_c(0, 1); - assert_eq!(mut_a.c(0), A.c(1)); - assert_eq!(mut_a.c(1), A.c(0)); - } - - #[test] - fn test_swap_r() { - let mut mut_a = A; - mut_a.swap_r(0, 1); - assert_eq!(mut_a.r(0), A.r(1)); - assert_eq!(mut_a.r(1), A.r(0)); - } - - #[test] - fn test_identity() { - assert_eq!(Mat2::identity::(), - Mat2::new::(1.0, 0.0, - 0.0, 1.0)); - let mut mut_a = A; - mut_a.to_identity(); - assert!(mut_a.is_identity()); - } - - #[test] - fn test_zero() { - assert_eq!(Mat2::zero::(), - Mat2::new::(0.0, 0.0, - 0.0, 0.0)); - let mut mut_a = A; - mut_a.to_zero(); - assert_eq!(mut_a, Mat2::zero::()); - } - - #[test] - fn test_determinant() { - assert_eq!(A.determinant(), -2.0); - } - - #[test] - fn test_trace() { - assert_eq!(A.trace(), 5.0); - } - - #[test] - fn test_neg() { - assert_eq!(A.neg(), - Mat2::new::(-1.0, -3.0, - -2.0, -4.0)); - assert_eq!(-A, A.neg()); - } - - #[test] - fn test_mul_s() { - assert_eq!(A.mul_s(F), - Mat2::new::(0.5, 1.5, - 1.0, 2.0)); - let mut mut_a = A; - mut_a.mul_self_s(F); - assert_eq!(mut_a, A.mul_s(F)); - } - - #[test] - fn test_mul_v() { - assert_eq!(A.mul_v(&V), Vec2::new::(5.0, 11.0)); - } - - #[test] - fn test_add_m() { - assert_eq!(A.add_m(&B), - Mat2::new::(3.0, 7.0, - 5.0, 9.0)); - let mut mut_a = A; - mut_a.add_self_m(&B); - assert_eq!(mut_a, A.add_m(&B)); - } - - #[test] - fn test_sub_m() { - assert_eq!(A.sub_m(&B), - Mat2::new::(-1.0, -1.0, - -1.0, -1.0)); - let mut mut_a = A; - mut_a.sub_self_m(&B); - assert_eq!(mut_a, A.sub_m(&B)); - } - - #[test] - fn test_mul_m() { - assert_eq!(A.mul_m(&B), - Mat2::new::(10.0, 22.0, - 13.0, 29.0)); - } - - #[test] - fn test_dot() { - assert_eq!(A.dot(&B), 40.0); - } - - #[test] - fn test_transpose() { - assert_eq!(A.transpose(), - Mat2::new::(1.0, 2.0, - 3.0, 4.0)); - let mut mut_a = A; - mut_a.transpose_self(); - assert_eq!(mut_a, A.transpose()); - } - - #[test] - fn test_inverse() { - assert!(Mat2::identity::().inverse().unwrap().is_identity()); - - assert_eq!(A.inverse().unwrap(), - Mat2::new::(-2.0, 1.5, - 1.0, -0.5)); - assert!(Mat2::new::(0.0, 2.0, - 0.0, 5.0).inverse().is_none()); - let mut mut_a = A; - mut_a.invert_self(); - assert_eq!(mut_a, A.inverse().unwrap()); - } - - #[test] - fn test_predicates() { - assert!(Mat2::identity::().is_identity()); - assert!(Mat2::identity::().is_symmetric()); - assert!(Mat2::identity::().is_diagonal()); - assert!(!Mat2::identity::().is_rotated()); - assert!(Mat2::identity::().is_invertible()); - - assert!(!A.is_identity()); - assert!(!A.is_symmetric()); - assert!(!A.is_diagonal()); - assert!(A.is_rotated()); - assert!(A.is_invertible()); - - assert!(!C.is_identity()); - assert!(C.is_symmetric()); - assert!(!C.is_diagonal()); - assert!(C.is_rotated()); - assert!(C.is_invertible()); - - assert!(Mat2::from_value::(6.0).is_diagonal()); - } - - #[test] - fn test_to_mat3() { - assert_eq!(A.to_mat3(), - Mat3::new::(1.0, 3.0, 0.0, - 2.0, 4.0, 0.0, - 0.0, 0.0, 1.0)); - } - - #[test] - fn test_to_mat4() { - assert_eq!(A.to_mat4(), - Mat4::new::(1.0, 3.0, 0.0, 0.0, - 2.0, 4.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0)); - } - - #[test] - fn test_approx() { - assert!(!Mat2::new::(0.000001, 0.000001, - 0.000001, 0.000001).approx_eq(&Mat2::zero::())); - assert!(Mat2::new::(0.0000001, 0.0000001, - 0.0000001, 0.0000001).approx_eq(&Mat2::zero::())); - } -} - -#[deriving(Clone, Eq)] -pub struct Mat3 { - x: Vec3, - y: Vec3, - z: Vec3, -} - -// GLSL-style type aliases -pub type mat3 = Mat3; -pub type dmat3 = Mat3; - -// Rust-style type aliases -pub type Mat3f = Mat3; -pub type Mat3f32 = Mat3; -pub type Mat3f64 = Mat3; - -impl_dimensioned!(Mat3, Vec3, 3) -impl_swap_components!(Mat3) -impl_approx!(Mat2 { x, y }) - -pub trait ToMat3 { - pub fn to_mat3(&self) -> Mat3; -} - -impl Mat3 { - #[inline] - pub fn new(c0r0:T, c0r1:T, c0r2:T, - c1r0:T, c1r1:T, c1r2:T, - c2r0:T, c2r1:T, c2r2:T) -> Mat3 { - Mat3::from_cols(Vec3::new(c0r0, c0r1, c0r2), - Vec3::new(c1r0, c1r1, c1r2), - Vec3::new(c2r0, c2r1, c2r2)) - } - - #[inline] - pub fn from_cols(c0: Vec3, - c1: Vec3, - c2: Vec3) -> Mat3 { - Mat3 { x: c0, y: c1, z: c2 } - } - - #[inline] - pub fn from_axes(x: Vec3, - y: Vec3, - z: Vec3) -> Mat3 { - Mat3 { x: x, y: y, z: z } - } -} - -impl Mat,[Vec3,..3]> for Mat3 { - #[inline] - pub fn c<'a>(&'a self, c: uint) -> &'a Vec3 { - self.i(c) - } - - #[inline] - pub fn r(&self, r: uint) -> Vec3 { - Vec3::new(self.i(0).i(r).clone(), - self.i(1).i(r).clone(), - self.i(2).i(r).clone()) - } - - #[inline] - pub fn cr<'a>(&'a self, c: uint, r: uint) -> &'a T { - self.i(c).i(r) - } - - #[inline] - pub fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vec3 { - self.mut_i(c) - } - - #[inline] - pub fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut T { - self.mut_i(c).mut_i(r) - } - - #[inline] - pub fn swap_c(&mut self, a: uint, b: uint) { - let tmp = self.c(a).clone(); - *self.mut_c(a) = self.c(b).clone(); - *self.mut_c(b) = tmp; - } - - #[inline] - pub fn swap_r(&mut self, a: uint, b: uint) { - self.mut_c(0).swap(a, b); - self.mut_c(1).swap(a, b); - self.mut_c(2).swap(a, b); - } - - #[inline] - pub fn swap_cr(&mut self, (col_a, row_a): (uint, uint), - (col_b, row_b): (uint, uint)) { - let tmp = self.cr(col_a, row_a).clone(); - *self.mut_cr(col_a, row_a) = self.cr(col_b, row_b).clone(); - *self.mut_cr(col_b, row_b) = tmp; - } - - #[inline] - pub fn transpose(&self) -> Mat3 { - Mat3::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(), - self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(), - self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(2, 2).clone()) - } - - #[inline] - pub fn transpose_self(&mut self) { - self.swap_cr((0, 1), (1, 0)); - self.swap_cr((0, 2), (2, 0)); - self.swap_cr((1, 2), (2, 1)); - } -} - -impl ToMat4 for Mat3 { - #[inline] - pub fn to_mat4(&self) -> Mat4 { - Mat4::new(self.cr(0, 0).clone(), self.cr(0, 1).clone(), self.cr(0, 2).clone(), zero!(T), - self.cr(1, 0).clone(), self.cr(1, 1).clone(), self.cr(1, 2).clone(), zero!(T), - self.cr(2, 0).clone(), self.cr(2, 1).clone(), self.cr(2, 2).clone(), zero!(T), - zero!(T), zero!(T), zero!(T), one!(T)) - } -} - -impl Mat3 { - #[inline] - pub fn identity() -> Mat3 { - Mat3::from_cols(Vec3::unit_x(), - Vec3::unit_y(), - Vec3::unit_z()) - } - - #[inline] - pub fn zero() -> Mat3 { - Mat3::from_cols(Vec3::zero(), - Vec3::zero(), - Vec3::zero()) - } -} - -impl Mat3 { - #[inline] - pub fn from_value(value: T) -> Mat3 { - Mat3::new(value.clone(), zero!(T), zero!(T), - zero!(T), value.clone(), zero!(T), - zero!(T), zero!(T), value.clone()) - } -} - -impl NumMat,[Vec3,..3]> for Mat3 { - #[inline] - pub fn mul_s(&self, value: T) -> Mat3 { - Mat3::from_cols(self.c(0).mul_s(value.clone()), - self.c(1).mul_s(value.clone()), - self.c(2).mul_s(value.clone())) - } - - #[inline] - pub fn mul_v(&self, vec: &Vec3) -> Vec3 { - Vec3::new(self.r(0).dot(vec), - self.r(1).dot(vec), - self.r(2).dot(vec)) - } - - #[inline] - pub fn add_m(&self, other: &Mat3) -> Mat3 { - Mat3::from_cols(self.c(0).add_v(other.c(0)), - self.c(1).add_v(other.c(1)), - self.c(2).add_v(other.c(2))) - } - - #[inline] - pub fn sub_m(&self, other: &Mat3) -> Mat3 { - Mat3::from_cols(self.c(0).sub_v(other.c(0)), - self.c(1).sub_v(other.c(1)), - self.c(2).sub_v(other.c(2))) - } - - #[inline] - pub fn mul_m(&self, other: &Mat3) -> Mat3 { - Mat3::new(self.r(0).dot(other.c(0)),self.r(1).dot(other.c(0)),self.r(2).dot(other.c(0)), - self.r(0).dot(other.c(1)),self.r(1).dot(other.c(1)),self.r(2).dot(other.c(1)), - self.r(0).dot(other.c(2)),self.r(1).dot(other.c(2)),self.r(2).dot(other.c(2))) - } - - #[inline] - pub fn mul_self_s(&mut self, value: T) { - self.mut_c(0).mul_self_s(value.clone()); - self.mut_c(1).mul_self_s(value.clone()); - self.mut_c(2).mul_self_s(value.clone()); - } - - #[inline] - pub fn add_self_m(&mut self, other: &Mat3) { - self.mut_c(0).add_self_v(other.c(0)); - self.mut_c(1).add_self_v(other.c(1)); - self.mut_c(2).add_self_v(other.c(2)); - } - - #[inline] - pub fn sub_self_m(&mut self, other: &Mat3) { - self.mut_c(0).sub_self_v(other.c(0)); - self.mut_c(1).sub_self_v(other.c(1)); - self.mut_c(2).sub_self_v(other.c(2)); - } - - pub fn dot(&self, other: &Mat3) -> T { - other.transpose().mul_m(self).trace() - } - - pub fn determinant(&self) -> T { - *self.cr(0, 0) * (*self.cr(1, 1) * *self.cr(2, 2) - *self.cr(2, 1) * *self.cr(1, 2)) - - *self.cr(1, 0) * (*self.cr(0, 1) * *self.cr(2, 2) - *self.cr(2, 1) * *self.cr(0, 2)) - + *self.cr(2, 0) * (*self.cr(0, 1) * *self.cr(1, 2) - *self.cr(1, 1) * *self.cr(0, 2)) - } - - pub fn trace(&self) -> T { - (*self.cr(0, 0)) + (*self.cr(1, 1)) + (*self.cr(2, 2)) - } - - #[inline] - pub fn to_identity(&mut self) { - *self = Mat3::identity(); - } - - #[inline] - pub fn to_zero(&mut self) { - *self = Mat3::zero(); - } -} - -impl Neg> for Mat3 { - #[inline] - pub fn neg(&self) -> Mat3 { - Mat3::from_cols(-*self.c(0), - -*self.c(1), - -*self.c(2)) - } -} - -impl Mat3 { - pub fn look_at(dir: &Vec3, up: &Vec3) -> Mat3 { - let dir_ = dir.normalize(); - let side = dir_.cross(&up.normalize()); - let up_ = side.cross(&dir_).normalize(); - - Mat3::from_axes(up_, side, dir_) - } -} - -impl ToQuat for Mat3 { - /// Convert the matrix to a quaternion - pub fn to_quat(&self) -> Quat { - // Implemented using a mix of ideas from jMonkeyEngine and Ken Shoemake's - // paper on Quaternions: http://www.cs.ucr.edu/~vbz/resources/Quatut.pdf - - let mut s; - let w; let x; let y; let z; - let trace = self.trace(); - - // FIXME: We don't have any numeric conversions in std yet :P - let half = one!(T) / two!(T); - - cond! ( - (trace >= zero!(T)) { - s = (one!(T) + trace).sqrt(); - w = half * s; - s = half / s; - x = (*self.cr(1, 2) - *self.cr(2, 1)) * s; - y = (*self.cr(2, 0) - *self.cr(0, 2)) * s; - z = (*self.cr(0, 1) - *self.cr(1, 0)) * s; - } - ((*self.cr(0, 0) > *self.cr(1, 1)) - && (*self.cr(0, 0) > *self.cr(2, 2))) { - s = (half + (*self.cr(0, 0) - *self.cr(1, 1) - *self.cr(2, 2))).sqrt(); - w = half * s; - s = half / s; - x = (*self.cr(0, 1) - *self.cr(1, 0)) * s; - y = (*self.cr(2, 0) - *self.cr(0, 2)) * s; - z = (*self.cr(1, 2) - *self.cr(2, 1)) * s; - } - (*self.cr(1, 1) > *self.cr(2, 2)) { - s = (half + (*self.cr(1, 1) - *self.cr(0, 0) - *self.cr(2, 2))).sqrt(); - w = half * s; - s = half / s; - x = (*self.cr(0, 1) - *self.cr(1, 0)) * s; - y = (*self.cr(1, 2) - *self.cr(2, 1)) * s; - z = (*self.cr(2, 0) - *self.cr(0, 2)) * s; - } - _ { - s = (half + (*self.cr(2, 2) - *self.cr(0, 0) - *self.cr(1, 1))).sqrt(); - w = half * s; - s = half / s; - x = (*self.cr(2, 0) - *self.cr(0, 2)) * s; - y = (*self.cr(1, 2) - *self.cr(2, 1)) * s; - z = (*self.cr(0, 1) - *self.cr(1, 0)) * s; - } - ) - Quat::new(w, x, y, z) - } -} - -impl FloatMat,[Vec3,..3]> for Mat3 { - #[inline] - pub fn inverse(&self) -> Option> { - let d = self.determinant(); - if d.approx_eq(&zero!(T)) { - None - } else { - Some(Mat3::from_cols(self.c(1).cross(self.c(2)).div_s(d.clone()), - self.c(2).cross(self.c(0)).div_s(d.clone()), - self.c(0).cross(self.c(1)).div_s(d.clone())).transpose()) - } - } - - #[inline] - pub fn invert_self(&mut self) { - *self = self.inverse().expect("Couldn't invert the matrix!"); - } - - #[inline] - pub fn is_identity(&self) -> bool { - self.approx_eq(&Mat3::identity()) - } - - #[inline] - pub fn is_diagonal(&self) -> bool { - self.cr(0, 1).approx_eq(&zero!(T)) && - self.cr(0, 2).approx_eq(&zero!(T)) && - - self.cr(1, 0).approx_eq(&zero!(T)) && - self.cr(1, 2).approx_eq(&zero!(T)) && - - self.cr(2, 0).approx_eq(&zero!(T)) && - self.cr(2, 1).approx_eq(&zero!(T)) - } - - #[inline] - pub fn is_rotated(&self) -> bool { - !self.approx_eq(&Mat3::identity()) - } - - #[inline] - pub fn is_symmetric(&self) -> bool { - self.cr(0, 1).approx_eq(self.cr(1, 0)) && - self.cr(0, 2).approx_eq(self.cr(2, 0)) && - - self.cr(1, 0).approx_eq(self.cr(0, 1)) && - self.cr(1, 2).approx_eq(self.cr(2, 1)) && - - self.cr(2, 0).approx_eq(self.cr(0, 2)) && - self.cr(2, 1).approx_eq(self.cr(1, 2)) - } - - #[inline] - pub fn is_invertible(&self) -> bool { - !self.determinant().approx_eq(&zero!(T)) - } -} - -#[cfg(test)] -mod mat3_tests{ - use math::mat::*; - use math::vec::*; - - 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 }, - z: Vec3 { x: 3.0, y: 6.0, z: 9.0 } }; - static B: Mat3 = Mat3 { x: Vec3 { x: 2.0, y: 5.0, z: 8.0 }, - y: Vec3 { x: 3.0, y: 6.0, z: 9.0 }, - z: Vec3 { x: 4.0, y: 7.0, z: 10.0 } }; - static C: Mat3 = Mat3 { x: Vec3 { x: 2.0, y: 4.0, z: 6.0 }, - y: Vec3 { x: 0.0, y: 2.0, z: 4.0 }, - z: Vec3 { x: 0.0, y: 0.0, z: 1.0 } }; - static D: Mat3 = Mat3 { x: Vec3 { x: 3.0, y: 2.0, z: 1.0 }, - y: Vec3 { x: 2.0, y: 3.0, z: 2.0 }, - z: Vec3 { x: 1.0, y: 2.0, z: 3.0 } }; - - static V: Vec3 = Vec3 { x: 1.0, y: 2.0, z: 3.0 }; - static F: float = 0.5; - - #[test] - fn test_swap_c() { - let mut mut_a0 = A; - mut_a0.swap_c(0, 2); - assert_eq!(mut_a0.c(0), A.c(2)); - assert_eq!(mut_a0.c(2), A.c(0)); - - let mut mut_a1 = A; - mut_a1.swap_c(1, 2); - assert_eq!(mut_a1.c(1), A.c(2)); - assert_eq!(mut_a1.c(2), A.c(1)); - } - - #[test] - fn test_swap_r() { - let mut mut_a0 = A; - mut_a0.swap_r(0, 2); - assert_eq!(mut_a0.r(0), A.r(2)); - assert_eq!(mut_a0.r(2), A.r(0)); - - let mut mut_a1 = A; - mut_a1.swap_r(1, 2); - assert_eq!(mut_a1.r(1), A.r(2)); - assert_eq!(mut_a1.r(2), A.r(1)); - } - - #[test] - fn test_identity() { - assert_eq!(Mat3::identity::(), - Mat3::new::(1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0)); - let mut mut_a = A; - mut_a.to_identity(); - assert!(mut_a.is_identity()); - } - - #[test] - fn test_zero() { - assert_eq!(Mat3::zero::(), - Mat3::new::(0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0)); - let mut mut_a = A; - mut_a.to_zero(); - assert_eq!(mut_a, Mat3::zero::()); - } - - #[test] - fn test_determinant() { - // assert_eq!(A.determinant(), 0.0); - // TODO - } - - #[test] - fn test_trace() { - assert_eq!(A.trace(), 15.0); - } - - #[test] - fn test_neg() { - assert_eq!(A.neg(), - Mat3::new::(-1.0, -4.0, -7.0, - -2.0, -5.0, -8.0, - -3.0, -6.0, -9.0)); - assert_eq!(-A, A.neg()); - } - - #[test] - fn test_mul_s() { - assert_eq!(A.mul_s(F), - Mat3::new::(0.5, 2.0, 3.5, - 1.0, 2.5, 4.0, - 1.5, 3.0, 4.5)); - let mut mut_a = A; - mut_a.mul_self_s(F); - assert_eq!(mut_a, A.mul_s(F)); - } - - #[test] - fn test_mul_v() { - assert_eq!(A.mul_v(&V), - Vec3::new::(14.0, 32.0, 50.0)); - } - - #[test] - fn test_add_m() { - assert_eq!(A.add_m(&B), - Mat3::new::(3.0, 9.0, 15.0, - 5.0, 11.0, 17.0, - 7.0, 13.0, 19.0)); - let mut mut_a = A; - mut_a.add_self_m(&B); - assert_eq!(mut_a, A.add_m(&B)); - } - - #[test] - fn test_sub_m() { - assert_eq!(A.sub_m(&B), - Mat3::new::(-1.0, -1.0, -1.0, - -1.0, -1.0, -1.0, - -1.0, -1.0, -1.0)); - let mut mut_a = A; - mut_a.sub_self_m(&B); - assert_eq!(mut_a, A.sub_m(&B)); - } - - #[test] - fn test_mul_m() { - assert_eq!(A.mul_m(&B), - Mat3::new::(36.0, 81.0, 126.0, - 42.0, 96.0, 150.0, - 48.0, 111.0, 174.0)); - } - - #[test] - fn test_dot() { - assert_eq!(A.dot(&B), 330.0); - } - - #[test] - fn test_transpose() { - assert_eq!(A.transpose(), - Mat3::new::(1.0, 2.0, 3.0, - 4.0, 5.0, 6.0, - 7.0, 8.0, 9.0)); - let mut mut_a = A; - mut_a.transpose_self(); - assert_eq!(mut_a, A.transpose()); - } - - #[test] - fn test_inverse() { - assert!(Mat3::identity::().inverse().unwrap().is_identity()); - - assert_eq!(A.inverse(), None); - - assert_eq!(C.inverse().unwrap(), - Mat3::new::(0.5, -1.0, 1.0, - 0.0, 0.5, -2.0, - 0.0, 0.0, 1.0)); - let mut mut_c = C; - mut_c.invert_self(); - assert_eq!(mut_c, C.inverse().unwrap()); - } - - #[test] - fn test_predicates() { - assert!(Mat3::identity::().is_identity()); - assert!(Mat3::identity::().is_symmetric()); - assert!(Mat3::identity::().is_diagonal()); - assert!(!Mat3::identity::().is_rotated()); - assert!(Mat3::identity::().is_invertible()); - - assert!(!A.is_identity()); - assert!(!A.is_symmetric()); - assert!(!A.is_diagonal()); - assert!(A.is_rotated()); - assert!(!A.is_invertible()); - - assert!(!D.is_identity()); - assert!(D.is_symmetric()); - assert!(!D.is_diagonal()); - assert!(D.is_rotated()); - assert!(D.is_invertible()); - - assert!(Mat3::from_value::(6.0).is_diagonal()); - } - - #[test] - fn test_to_mat4() { - assert_eq!(A.to_mat4(), - Mat4::new::(1.0, 4.0, 7.0, 0.0, - 2.0, 5.0, 8.0, 0.0, - 3.0, 6.0, 9.0, 0.0, - 0.0, 0.0, 0.0, 1.0)); - } - - #[test] - fn test_approx() { - assert!(!Mat3::new::(0.000001, 0.000001, 0.000001, - 0.000001, 0.000001, 0.000001, - 0.000001, 0.000001, 0.000001) - .approx_eq(&Mat3::zero::())); - assert!(Mat3::new::(0.0000001, 0.0000001, 0.0000001, - 0.0000001, 0.0000001, 0.0000001, - 0.0000001, 0.0000001, 0.0000001) - .approx_eq(&Mat3::zero::())); - } -} - -#[deriving(Clone, Eq)] -pub struct Mat4 { - x: Vec4, - y: Vec4, - z: Vec4, - w: Vec4, -} - -// GLSL-style type aliases -pub type mat4 = Mat4; -pub type dmat4 = Mat4; - -// Rust-style type aliases -pub type Mat4f = Mat4; -pub type Mat4f32 = Mat4; -pub type Mat4f64 = Mat4; - -impl_dimensioned!(Mat4, Vec4, 4) -impl_swap_components!(Mat4) -impl_approx!(Mat4 { x, y, z, w }) - -pub trait ToMat4 { - pub fn to_mat4(&self) -> Mat4; -} - -impl Mat4 { - #[inline] - pub fn new(c0r0: T, c0r1: T, c0r2: T, c0r3: T, - c1r0: T, c1r1: T, c1r2: T, c1r3: T, - c2r0: T, c2r1: T, c2r2: T, c2r3: T, - c3r0: T, c3r1: T, c3r2: T, c3r3: T) -> Mat4 { - Mat4::from_cols(Vec4::new(c0r0, c0r1, c0r2, c0r3), - Vec4::new(c1r0, c1r1, c1r2, c1r3), - Vec4::new(c2r0, c2r1, c2r2, c2r3), - Vec4::new(c3r0, c3r1, c3r2, c3r3)) - } - - #[inline] - pub fn from_cols(c0: Vec4, - c1: Vec4, - c2: Vec4, - c3: Vec4) -> Mat4 { - Mat4 { x: c0, y: c1, z: c2, w: c3 } - } -} - -impl Mat,[Vec4,..4]> for Mat4 { - #[inline] - pub fn c<'a>(&'a self, c: uint) -> &'a Vec4 { - self.i(c) - } - - #[inline] - pub fn r(&self, r: uint) -> Vec4 { - Vec4::new(self.i(0).i(r).clone(), - self.i(1).i(r).clone(), - self.i(2).i(r).clone(), - self.i(3).i(r).clone()) - } - - #[inline] - pub fn cr<'a>(&'a self, c: uint, r: uint) -> &'a T { - self.i(c).i(r) - } - - #[inline] - pub fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vec4 { - self.mut_i(c) - } - - #[inline] - pub fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut T { - self.mut_i(c).mut_i(r) - } - - #[inline] - pub fn swap_c(&mut self, a: uint, b: uint) { - let tmp = self.c(a).clone(); - *self.mut_c(a) = self.c(b).clone(); - *self.mut_c(b) = tmp; - } - - #[inline] - pub fn swap_r(&mut self, a: uint, b: uint) { - self.mut_c(0).swap(a, b); - self.mut_c(1).swap(a, b); - self.mut_c(2).swap(a, b); - self.mut_c(3).swap(a, b); - } - - #[inline] - pub fn swap_cr(&mut self, (col_a, row_a): (uint, uint), - (col_b, row_b): (uint, uint)) { - let tmp = self.cr(col_a, row_a).clone(); - *self.mut_cr(col_a, row_a) = self.cr(col_b, row_b).clone(); - *self.mut_cr(col_b, row_b) = tmp; - } - - #[inline] - pub fn transpose(&self) -> Mat4 { - Mat4::new(self.cr(0, 0).clone(),self.cr(1, 0).clone(),self.cr(2, 0).clone(),self.cr(3, 0).clone(), - self.cr(0, 1).clone(),self.cr(1, 1).clone(),self.cr(2, 1).clone(),self.cr(3, 1).clone(), - self.cr(0, 2).clone(),self.cr(1, 2).clone(),self.cr(2, 2).clone(),self.cr(3, 2).clone(), - self.cr(0, 3).clone(),self.cr(1, 3).clone(),self.cr(2, 3).clone(),self.cr(3, 3).clone()) - } - - #[inline] - pub fn transpose_self(&mut self) { - self.swap_cr((0, 1), (1, 0)); - self.swap_cr((0, 2), (2, 0)); - self.swap_cr((0, 3), (3, 0)); - self.swap_cr((1, 2), (2, 1)); - self.swap_cr((1, 3), (3, 1)); - self.swap_cr((2, 3), (3, 2)); - } -} - -impl Mat4 { - #[inline] - pub fn identity() -> Mat4 { - Mat4::from_cols(Vec4::unit_x(), - Vec4::unit_y(), - Vec4::unit_z(), - Vec4::unit_w()) - } - - #[inline] - pub fn zero() -> Mat4 { - Mat4::from_cols(Vec4::zero(), - Vec4::zero(), - Vec4::zero(), - Vec4::zero()) - } -} - -impl Mat4 { - #[inline] - pub fn from_value(value: T) -> Mat4 { - Mat4::new(value.clone(), zero!(T), zero!(T), zero!(T), - zero!(T), value.clone(), zero!(T), zero!(T), - zero!(T), zero!(T), value.clone(), zero!(T), - zero!(T), zero!(T), zero!(T), value.clone()) - } -} - -impl NumMat,[Vec4,..4]> for Mat4 { - #[inline] - pub fn mul_s(&self, value: T) -> Mat4 { - Mat4::from_cols(self.c(0).mul_s(value.clone()), - self.c(1).mul_s(value.clone()), - self.c(2).mul_s(value.clone()), - self.c(3).mul_s(value.clone())) - } - - #[inline] - pub fn mul_v(&self, vec: &Vec4) -> Vec4 { - Vec4::new(self.r(0).dot(vec), - self.r(1).dot(vec), - self.r(2).dot(vec), - self.r(3).dot(vec)) - } - - #[inline] - pub fn add_m(&self, other: &Mat4) -> Mat4 { - Mat4::from_cols(self.c(0).add_v(other.c(0)), - self.c(1).add_v(other.c(1)), - self.c(2).add_v(other.c(2)), - self.c(3).add_v(other.c(3))) - } - - #[inline] - pub fn sub_m(&self, other: &Mat4) -> Mat4 { - Mat4::from_cols(self.c(0).sub_v(other.c(0)), - self.c(1).sub_v(other.c(1)), - self.c(2).sub_v(other.c(2)), - self.c(3).sub_v(other.c(3))) - } - - #[inline] - pub fn mul_m(&self, other: &Mat4) -> Mat4 { - Mat4::new(self.r(0).dot(other.c(0)), self.r(1).dot(other.c(0)), self.r(2).dot(other.c(0)), self.r(3).dot(other.c(0)), - self.r(0).dot(other.c(1)), self.r(1).dot(other.c(1)), self.r(2).dot(other.c(1)), self.r(3).dot(other.c(1)), - self.r(0).dot(other.c(2)), self.r(1).dot(other.c(2)), self.r(2).dot(other.c(2)), self.r(3).dot(other.c(2)), - self.r(0).dot(other.c(3)), self.r(1).dot(other.c(3)), self.r(2).dot(other.c(3)), self.r(3).dot(other.c(3))) - } - - #[inline] - pub fn mul_self_s(&mut self, value: T) { - self.mut_c(0).mul_self_s(value.clone()); - self.mut_c(1).mul_self_s(value.clone()); - self.mut_c(2).mul_self_s(value.clone()); - self.mut_c(3).mul_self_s(value.clone()); - } - - #[inline] - pub fn add_self_m(&mut self, other: &Mat4) { - self.mut_c(0).add_self_v(other.c(0)); - self.mut_c(1).add_self_v(other.c(1)); - self.mut_c(2).add_self_v(other.c(2)); - self.mut_c(3).add_self_v(other.c(3)); - } - - #[inline] - pub fn sub_self_m(&mut self, other: &Mat4) { - self.mut_c(0).sub_self_v(other.c(0)); - self.mut_c(1).sub_self_v(other.c(1)); - self.mut_c(2).sub_self_v(other.c(2)); - self.mut_c(3).sub_self_v(other.c(3)); - } - - pub fn dot(&self, other: &Mat4) -> T { - other.transpose().mul_m(self).trace() - } - - pub fn determinant(&self) -> T { - let m0 = Mat3::new(self.cr(1, 1).clone(), self.cr(2, 1).clone(), self.cr(3, 1).clone(), - self.cr(1, 2).clone(), self.cr(2, 2).clone(), self.cr(3, 2).clone(), - self.cr(1, 3).clone(), self.cr(2, 3).clone(), self.cr(3, 3).clone()); - let m1 = Mat3::new(self.cr(0, 1).clone(), self.cr(2, 1).clone(), self.cr(3, 1).clone(), - self.cr(0, 2).clone(), self.cr(2, 2).clone(), self.cr(3, 2).clone(), - self.cr(0, 3).clone(), self.cr(2, 3).clone(), self.cr(3, 3).clone()); - let m2 = Mat3::new(self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(3, 1).clone(), - self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(3, 2).clone(), - self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(3, 3).clone()); - let m3 = Mat3::new(self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(), - self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(2, 2).clone(), - self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone()); - - self.cr(0, 0) * m0.determinant() - - self.cr(1, 0) * m1.determinant() + - self.cr(2, 0) * m2.determinant() - - self.cr(3, 0) * m3.determinant() - } - - pub fn trace(&self) -> T { - *self.cr(0, 0) + *self.cr(1, 1) + *self.cr(2, 2) + *self.cr(3, 3) - } - - #[inline] - pub fn to_identity(&mut self) { - *self = Mat4::identity(); - } - - #[inline] - pub fn to_zero(&mut self) { - *self = Mat4::zero(); - } -} - -impl Neg> for Mat4 { - #[inline] - pub fn neg(&self) -> Mat4 { - Mat4::from_cols(-*self.c(0), - -*self.c(1), - -*self.c(2), - -*self.c(3)) - } -} - -impl FloatMat,[Vec4,..4]> for Mat4 { - #[inline] - pub fn inverse(&self) -> Option> { - use std::uint; - - if self.is_invertible() { - // Gauss Jordan Elimination with partial pivoting - // So take this matrix, A, augmented with the identity - // and essentially reduce [A|I] - - let mut A = self.clone(); - let mut I = Mat4::identity::(); - - for uint::range(0, 4) |j| { - // Find largest element in col j - let mut i1 = j; - for uint::range(j + 1, 4) |i| { - if A.cr(j, i).abs() > A.cr(j, i1).abs() { - i1 = i; - } - } - - // SwapComponents columns i1 and j in A and I to - // put pivot on diagonal - A.swap_c(i1, j); - I.swap_c(i1, j); - - // Scale col j to have a unit diagonal - let ajj = A.cr(j, j).clone(); - I.mut_c(j).div_self_s(ajj.clone()); - A.mut_c(j).div_self_s(ajj.clone()); - - // Eliminate off-diagonal elems in col j of A, - // doing identical ops to I - for uint::range(0, 4) |i| { - if i != j { - let ij_mul_aij = I.c(j).mul_s(A.cr(i, j).clone()); - let aj_mul_aij = A.c(j).mul_s(A.cr(i, j).clone()); - I.mut_c(i).sub_self_v(&ij_mul_aij); - A.mut_c(i).sub_self_v(&aj_mul_aij); - } - } - } - Some(I) - } else { - None - } - } - - #[inline] - pub fn invert_self(&mut self) { - *self = self.inverse().expect("Couldn't invert the matrix!"); - } - - #[inline] - pub fn is_identity(&self) -> bool { - self.approx_eq(&Mat4::identity()) - } - - #[inline] - pub fn is_diagonal(&self) -> bool { - self.cr(0, 1).approx_eq(&zero!(T)) && - self.cr(0, 2).approx_eq(&zero!(T)) && - self.cr(0, 3).approx_eq(&zero!(T)) && - - self.cr(1, 0).approx_eq(&zero!(T)) && - self.cr(1, 2).approx_eq(&zero!(T)) && - self.cr(1, 3).approx_eq(&zero!(T)) && - - self.cr(2, 0).approx_eq(&zero!(T)) && - self.cr(2, 1).approx_eq(&zero!(T)) && - self.cr(2, 3).approx_eq(&zero!(T)) && - - self.cr(3, 0).approx_eq(&zero!(T)) && - self.cr(3, 1).approx_eq(&zero!(T)) && - self.cr(3, 2).approx_eq(&zero!(T)) - } - - #[inline] - pub fn is_rotated(&self) -> bool { - !self.approx_eq(&Mat4::identity()) - } - - #[inline] - pub fn is_symmetric(&self) -> bool { - self.cr(0, 1).approx_eq(self.cr(1, 0)) && - self.cr(0, 2).approx_eq(self.cr(2, 0)) && - self.cr(0, 3).approx_eq(self.cr(3, 0)) && - - self.cr(1, 0).approx_eq(self.cr(0, 1)) && - self.cr(1, 2).approx_eq(self.cr(2, 1)) && - self.cr(1, 3).approx_eq(self.cr(3, 1)) && - - self.cr(2, 0).approx_eq(self.cr(0, 2)) && - self.cr(2, 1).approx_eq(self.cr(1, 2)) && - self.cr(2, 3).approx_eq(self.cr(3, 2)) && - - self.cr(3, 0).approx_eq(self.cr(0, 3)) && - self.cr(3, 1).approx_eq(self.cr(1, 3)) && - self.cr(3, 2).approx_eq(self.cr(2, 3)) - } - - #[inline] - pub fn is_invertible(&self) -> bool { - !self.determinant().approx_eq(&zero!(T)) - } -} - -#[cfg(test)] -mod mat4_tests { - use math::mat::*; - use math::vec::*; - - 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 }, - z: Vec4 { x: 3.0, y: 7.0, z: 11.0, w: 15.0 }, - w: Vec4 { x: 4.0, y: 8.0, z: 12.0, w: 16.0 } }; - static B: Mat4 = Mat4 { x: Vec4 { x: 2.0, y: 6.0, z: 10.0, w: 14.0 }, - y: Vec4 { x: 3.0, y: 7.0, z: 11.0, w: 15.0 }, - z: Vec4 { x: 4.0, y: 8.0, z: 12.0, w: 16.0 }, - w: Vec4 { x: 5.0, y: 9.0, z: 13.0, w: 17.0 } }; - static C: Mat4 = Mat4 { x: Vec4 { x: 3.0, y: 2.0, z: 1.0, w: 1.0 }, - y: Vec4 { x: 2.0, y: 3.0, z: 2.0, w: 2.0 }, - z: Vec4 { x: 1.0, y: 2.0, z: 3.0, w: 3.0 }, - w: Vec4 { x: 0.0, y: 1.0, z: 1.0, w: 0.0 } }; - static D: Mat4 = Mat4 { x: Vec4 { x: 4.0, y: 3.0, z: 2.0, w: 1.0 }, - y: Vec4 { x: 3.0, y: 4.0, z: 3.0, w: 2.0 }, - z: Vec4 { x: 2.0, y: 3.0, z: 4.0, w: 3.0 }, - w: Vec4 { x: 1.0, y: 2.0, z: 3.0, w: 4.0 } }; - - static V: Vec4 = Vec4 { x: 1.0, y: 2.0, z: 3.0, w: 4.0 }; - static F: float = 0.5; - - #[test] - fn test_swap_c() { - let mut mut_a0 = A; - mut_a0.swap_c(0, 2); - assert_eq!(mut_a0.c(0), A.c(2)); - assert_eq!(mut_a0.c(2), A.c(0)); - - let mut mut_a1 = A; - mut_a1.swap_c(1, 2); - assert_eq!(mut_a1.c(1), A.c(2)); - assert_eq!(mut_a1.c(2), A.c(1)); - } - - #[test] - fn test_swap_r() { - let mut mut_a0 = A; - mut_a0.swap_r(0, 2); - assert_eq!(mut_a0.r(0), A.r(2)); - assert_eq!(mut_a0.r(2), A.r(0)); - - let mut mut_a1 = A; - mut_a1.swap_r(1, 2); - assert_eq!(mut_a1.r(1), A.r(2)); - assert_eq!(mut_a1.r(2), A.r(1)); - } - - #[test] - fn test_identity() { - assert_eq!(Mat4::identity::(), - Mat4::new::(1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0)); - let mut mut_a = A; - mut_a.to_identity(); - assert!(mut_a.is_identity()); - } - - #[test] - fn test_zero() { - assert_eq!(Mat4::zero::(), - Mat4::new::(0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0)); - let mut mut_a = A; - mut_a.to_zero(); - assert_eq!(mut_a, Mat4::zero::()); - } - #[test] - fn test_determinant() { - assert_eq!(A.determinant(), 0.0); - } - - #[test] - fn test_trace() { - assert_eq!(A.trace(), 34.0); - } - - #[test] - fn test_neg() { - assert_eq!(A.neg(), - Mat4::new::(-1.0, -5.0, -9.0, -13.0, - -2.0, -6.0, -10.0, -14.0, - -3.0, -7.0, -11.0, -15.0, - -4.0, -8.0, -12.0, -16.0)); - assert_eq!(-A, A.neg()); - } - - #[test] - fn test_mul_s() { - assert_eq!(A.mul_s(F), - Mat4::new::(0.5, 2.5, 4.5, 6.5, - 1.0, 3.0, 5.0, 7.0, - 1.5, 3.5, 5.5, 7.5, - 2.0, 4.0, 6.0, 8.0)); - let mut mut_a = A; - mut_a.mul_self_s(F); - assert_eq!(mut_a, A.mul_s(F)); - } - - #[test] - fn test_mul_v() { - assert_eq!(A.mul_v(&V), - Vec4::new::(30.0, 70.0, 110.0, 150.0)); - } - - #[test] - fn test_add_m() { - assert_eq!(A.add_m(&B), - Mat4::new::(3.0, 11.0, 19.0, 27.0, - 5.0, 13.0, 21.0, 29.0, - 7.0, 15.0, 23.0, 31.0, - 9.0, 17.0, 25.0, 33.0)); - let mut mut_a = A; - mut_a.add_self_m(&B); - assert_eq!(mut_a, A.add_m(&B)); - } - - #[test] - fn test_sub_m() { - assert_eq!(A.sub_m(&B), - Mat4::new::(-1.0, -1.0, -1.0, -1.0, - -1.0, -1.0, -1.0, -1.0, - -1.0, -1.0, -1.0, -1.0, - -1.0, -1.0, -1.0, -1.0)); - let mut mut_a = A; - mut_a.sub_self_m(&B); - assert_eq!(mut_a, A.sub_m(&B)); - } - - #[test] - fn test_mul_m() { - assert_eq!(A.mul_m(&B), - Mat4::new::(100.0, 228.0, 356.0, 484.0, - 110.0, 254.0, 398.0, 542.0, - 120.0, 280.0, 440.0, 600.0, - 130.0, 306.0, 482.0, 658.0)); - } - - #[test] - fn test_dot() { - assert_eq!(A.dot(&B), 1632.0); - } - - #[test] - fn test_transpose() { - assert_eq!(A.transpose(), - Mat4::new::( 1.0, 2.0, 3.0, 4.0, - 5.0, 6.0, 7.0, 8.0, - 9.0, 10.0, 11.0, 12.0, - 13.0, 14.0, 15.0, 16.0)); - let mut mut_a = A; - mut_a.transpose_self(); - assert_eq!(mut_a, A.transpose()); - } - - #[test] - fn test_inverse() { - assert!(Mat4::identity::().inverse().unwrap().is_identity()); - - assert_approx_eq!(C.inverse().unwrap(), - Mat4::new::( 5.0, -4.0, 1.0, 0.0, - -4.0, 8.0, -4.0, 0.0, - 4.0, -8.0, 4.0, 8.0, - -3.0, 4.0, 1.0, -8.0).mul_s(0.125)); - let mut mut_c = C; - mut_c.invert_self(); - assert_eq!(mut_c, C.inverse().unwrap()); - } - - #[test] - fn test_predicates() { - assert!(Mat3::identity::().is_identity()); - assert!(Mat3::identity::().is_symmetric()); - assert!(Mat3::identity::().is_diagonal()); - assert!(!Mat3::identity::().is_rotated()); - assert!(Mat3::identity::().is_invertible()); - - assert!(!A.is_identity()); - assert!(!A.is_symmetric()); - assert!(!A.is_diagonal()); - assert!(A.is_rotated()); - assert!(!A.is_invertible()); - - assert!(!D.is_identity()); - assert!(D.is_symmetric()); - assert!(!D.is_diagonal()); - assert!(D.is_rotated()); - assert!(D.is_invertible()); - - assert!(Mat3::from_value::(6.0).is_diagonal()); - } - - #[test] - fn test_approx() { - assert!(!Mat4::new::(0.000001, 0.000001, 0.000001, 0.000001, - 0.000001, 0.000001, 0.000001, 0.000001, - 0.000001, 0.000001, 0.000001, 0.000001, - 0.000001, 0.000001, 0.000001, 0.000001) - .approx_eq(&Mat4::zero::())); - assert!(Mat4::new::(0.0000001, 0.0000001, 0.0000001, 0.0000001, - 0.0000001, 0.0000001, 0.0000001, 0.0000001, - 0.0000001, 0.0000001, 0.0000001, 0.0000001, - 0.0000001, 0.0000001, 0.0000001, 0.0000001) - .approx_eq(&Mat4::zero::())); - } -} diff --git a/src-old/math/math.rs b/src-old/math/math.rs deleted file mode 100644 index 6a5c18c..0000000 --- a/src-old/math/math.rs +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Core datatypes and conversion traits for 3D mathematics - -pub use self::mat::{Mat, NumMat, FloatMat}; -pub use self::mat::{Mat2, ToMat2}; -pub use self::mat::{Mat3, ToMat3}; -pub use self::mat::{Mat4, ToMat4}; -pub use self::quat::{Quat, ToQuat}; -pub use self::vec::{NumVec, FloatVec}; -pub use self::vec::{OrdVec, EqVec, BoolVec}; -pub use self::vec::{Vec2, ToVec2, AsVec2}; -pub use self::vec::{Vec3, ToVec3, AsVec3}; -pub use self::vec::{Vec4, ToVec4, AsVec4}; - -pub use self::plane::Plane3; -pub use self::point::Point; -pub use self::point::{Point2, AsPoint2}; -pub use self::point::{Point3, AsPoint3}; -pub use self::ray::{Ray2, Ray3}; - -pub mod mat; -pub mod quat; -pub mod vec; - -pub mod plane; -pub mod point; -pub mod ray; - -pub trait Dimensioned { - pub fn i<'a>(&'a self, i: uint) -> &'a T; - pub fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut T; - pub fn as_slice<'a>(&'a self) -> &'a Slice; - pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut Slice; -} - -pub trait SwapComponents { - pub fn swap(&mut self, a: uint, b: uint); -} - -// `Dimensioned` impls for primitive numeric types - -impl_dimensioned!(u8) -impl_dimensioned!(u16) -impl_dimensioned!(u32) -impl_dimensioned!(u64) -impl_dimensioned!(uint) -impl_dimensioned!(i8) -impl_dimensioned!(i16) -impl_dimensioned!(i32) -impl_dimensioned!(i64) -impl_dimensioned!(int) -impl_dimensioned!(f32) -impl_dimensioned!(f64) -impl_dimensioned!(float) - -// Helper type aliases for implementing `Dimendioned` and `SwapComponents` -// for tuples. - -pub type Tuple1 = (T,); -pub type Tuple2 = (T,T); -pub type Tuple3 = (T,T,T); -pub type Tuple4 = (T,T,T,T); -pub type Tuple5 = (T,T,T,T,T); -pub type Tuple6 = (T,T,T,T,T,T); - -// `Dimensioned` impls for tuples - -impl_dimensioned!(Tuple1, T, 1) -impl_dimensioned!(Tuple2, T, 2) -impl_dimensioned!(Tuple3, T, 3) -impl_dimensioned!(Tuple4, T, 4) -impl_dimensioned!(Tuple5, T, 5) -impl_dimensioned!(Tuple6, T, 6) - -// `SwapComponents` impls for tuples - -impl_swap_components!(Tuple1) -impl_swap_components!(Tuple2) -impl_swap_components!(Tuple3) -impl_swap_components!(Tuple4) -impl_swap_components!(Tuple5) -impl_swap_components!(Tuple6) - -// Helper type aliases for implementing `Dimendioned` and `SwapComponents` -// for fixed length vectors. - -pub type Fixed1 = [T, ..1]; -pub type Fixed2 = [T, ..2]; -pub type Fixed3 = [T, ..3]; -pub type Fixed4 = [T, ..4]; -pub type Fixed5 = [T, ..5]; -pub type Fixed6 = [T, ..6]; - -// `Dimensioned` impls for fixed length vectors - -impl_dimensioned!(Fixed1, T, 1) -impl_dimensioned!(Fixed2, T, 2) -impl_dimensioned!(Fixed3, T, 3) -impl_dimensioned!(Fixed4, T, 4) -impl_dimensioned!(Fixed5, T, 5) -impl_dimensioned!(Fixed6, T, 6) - -// `SwapComponents` impls for fixed length vectors - -impl_swap_components!(Fixed1) -impl_swap_components!(Fixed2) -impl_swap_components!(Fixed3) -impl_swap_components!(Fixed4) -impl_swap_components!(Fixed5) -impl_swap_components!(Fixed6) diff --git a/src-old/math/plane.rs b/src-old/math/plane.rs deleted file mode 100644 index 49cac67..0000000 --- a/src-old/math/plane.rs +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Three-dimensional plane type - -use math::{Vec3, Vec4, Mat3}; -use math::{Point, Point3}; -use math::Ray3; - -/// A plane formed from the equation: `Ax + Bx + Cx + D = 0` -/// -/// # Fields -/// -/// - `normal`: the normal of the plane where: -/// - `normal.x`: corresponds to `A` in the plane equation -/// - `normal.y`: corresponds to `B` in the plane equation -/// - `normal.z`: corresponds to `C` in the plane equation -/// - `distance`: the distance value, corresponding to `D` in the plane equation -#[deriving(Clone, Eq)] -pub struct Plane3 { - normal: Vec3, - distance: T, -} - -impl_approx!(Plane3 { normal, distance }) - -impl Plane3 { - /// # Arguments - /// - /// - `a`: the `x` component of the normal - /// - `b`: the `y` component of the normal - /// - `c`: the `z` component of the normal - /// - `d`: the plane's distance value - pub fn from_abcd(a: T, b: T, c: T, d: T) -> Plane3 { - Plane3 { - normal: Vec3::new(a, b, c), - distance: d, - } - } - - /// Construct a plane from a normal vector and a scalar distance - pub fn from_nd(normal: Vec3, distance: T) -> Plane3 { - Plane3 { normal: normal, distance: distance } - } - - /// Construct a plane from the components of a four-dimensional vector - pub fn from_vec4(vec: Vec4) -> Plane3 { - Plane3::from_abcd(vec.x.clone(), vec.y.clone(), vec.z.clone(), vec.w.clone()) - } - - /// Compute the distance from the plane to the point - pub fn distance(&self, pos: &Point3) -> T { - self.normal.dot(pos.as_vec3()) + self.distance - } - - /// Computes the point at which `ray` intersects the plane - pub fn intersection_r(&self, _ray: &Ray3) -> Point3 { - fail!(~"not yet implemented") - } - - /// Returns `true` if the ray intersects the plane - pub fn intersects(&self, _ray: &Ray3) -> bool { - fail!(~"not yet implemented") - } - - /// Returns `true` if `pos` is located behind the plane - otherwise it returns `false` - pub fn contains(&self, pos: &Point3) -> bool { - self.distance(pos) < zero!(T) - } -} - -impl Plane3 { - /// Constructs a plane that passes through the the three points `a`, `b` and `c` - pub fn from_3p(a: Point3, - b: Point3, - c: Point3) -> Option> { - // create two vectors that run parallel to the plane - let v0 = (b - a); - let v1 = (c - a); - // find the vector that is perpendicular to v1 and v2 - let mut normal = v0.cross(&v1); - - if normal.approx_eq(&Vec3::zero()) { - None - } else { - // compute the normal and the distance to the plane - normal.normalize_self(); - let distance = -a.as_vec3().dot(&normal); - - Some(Plane3::from_nd(normal, distance)) - } - } - - /// Computes the ray created from the two-plane intersection of `self` and `other` - /// - /// # Return value - /// - /// - `Some(r)`: The ray `r` where the planes intersect. - /// - `None`: No valid intersection was found. The planes are probably parallel. - pub fn intersection_2pl(&self, other: &Plane3) -> Option> { - let dir = self.normal.cross(&other.normal); - - if dir.approx_eq(&Vec3::zero::()) { - None // the planes are parallel - } else { - // The end-point of the ray is at the three-plane intersection between - // `self`, `other`, and a tempory plane positioned at the origin - do Plane3::from_nd(dir.clone(), zero!(T)).intersection_3pl(self, other).map |origin| { - Ray3 { - origin: origin.clone(), - direction: dir.clone(), - } - } - } - } - - /// Computes the three-plane intersection between `self`, `other_a` and `other_b`. - /// - /// # Return value - /// - /// - `Some(p)`: The position vector `p` where the planes intersect. - /// - `None`: No valid intersection was found. The normals of the three - /// planes are probably coplanar. - pub fn intersection_3pl(&self, other_a: &Plane3, other_b: &Plane3) -> Option> { - let mx = Mat3::new(self.normal.x.clone(), other_a.normal.x.clone(), other_b.normal.x.clone(), - self.normal.y.clone(), other_a.normal.y.clone(), other_b.normal.y.clone(), - self.normal.z.clone(), other_a.normal.z.clone(), other_b.normal.z.clone()); - do mx.inverse().map |m| { - Point3::origin() + m.mul_v(&Vec3::new(self.distance.clone(), - other_a.distance.clone(), - other_b.distance.clone())) - } - } -} - -impl ToStr for Plane3 { - pub fn to_str(&self) -> ~str { - fmt!("%?x + %?y + %?z + %? = 0", - self.normal.x, - self.normal.y, - self.normal.z, - self.distance) - } -} - -#[cfg(test)] -mod tests { - use math::plane::*; - use math::point::*; - - #[test] - fn test_from_3p() { - assert_eq!(Plane3::from_3p(Point3::new(5f, 0f, 5f), - Point3::new(5f, 5f, 5f), - Point3::new(5f, 0f, -1f)), Some(Plane3::from_abcd(-1f, 0f, 0f, 5f))); - - assert_eq!(Plane3::from_3p(Point3::new(0f, 5f, -5f), - Point3::new(0f, 5f, 0f), - Point3::new(0f, 5f, 5f)), None); // The points are parallel - } - - #[test] - fn test_plane_intersection_3pl() { - let p0 = Plane3::from_abcd(1.0, 0.0, 0.0, 1.0); - let p1 = Plane3::from_abcd(0.0, -1.0, 0.0, 2.0); - let p2 = Plane3::from_abcd(0.0, 0.0, 1.0, 1.0); - - assert_eq!(p0.intersection_3pl(&p1, &p2), Some(Point3::new(1.0, -2.0, 1.0))); - } - - #[test] - fn test_to_str() { - assert_eq!(Plane3::from_abcd(1.0, 2.0, 3.0, 4.0).to_str(), ~"1x + 2y + 3z + 4 = 0"); - } -} diff --git a/src-old/math/point.rs b/src-old/math/point.rs deleted file mode 100644 index f95c9e2..0000000 --- a/src-old/math/point.rs +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Coordinate vectors for positional data -//! -//! These types differ from the vector types implemented in `core::vec` because -//! they describe coordinates in geometric space and not a magnitude and a -//! direction. All positional data throughout the library uses these point -//! types, which allows for a clear, self-documenting API. - -use std::cast; - -use math::{Dimensioned, SwapComponents}; -use math::{Ray2, Ray3}; -use math::{Vec2, ToVec2, AsVec2}; -use math::{Vec3, ToVec3, AsVec3}; -use math::{Vec4, ToVec4}; - -/// A coordinate vector -pub trait Point: Eq - + Add - + Sub - + Mul - + ApproxEq - + ToStr { - pub fn translate_v(&self, offset: &Vec) -> Self; - pub fn scale_s(&self, factor: T) -> Self; - pub fn scale_v(&self, factor: &Vec) -> Self; - pub fn displacement(&self, other: &Self) -> Vec; - pub fn distance2(&self, other: &Self) -> T; - pub fn distance(&self, other: &Self) -> T; - pub fn direction(&self, other: &Self) -> Vec; - pub fn ray_to(&self, other: &Self) -> Ray; -} - -/// A two-dimensional coordinate vector -#[deriving(Clone, Eq)] -pub struct Point2 { x: T, y: T } - -impl_dimensioned!(Point2, T, 2) -impl_to_vec!(Point2, 2) -impl_as_vec!(Point2, 2) -impl_swap_components!(Point2) -impl_approx!(Point2 { x, y }) - -pub trait AsPoint2 { - pub fn as_point2<'a>(&'a self) -> &'a Point2; - pub fn as_mut_point2<'a>(&'a mut self) -> &'a mut Point2; -} - -impl AsPoint2 for Vec2 { - #[inline] - pub fn as_point2<'a>(&'a self) -> &'a Point2 { - unsafe { cast::transmute(self) } - } - - #[inline] - pub fn as_mut_point2<'a>(&'a mut self) -> &'a mut Point2 { - unsafe { cast::transmute(self) } - } -} - -impl Point2 { - /// Creates a new point from three coordinates. - #[inline] - pub fn new(x: T, y: T) -> Point2 { - Point2 { x: x, y: y } - } - - /// Converts a vector to a point. - #[inline] - pub fn from_vec2(vec: Vec2) -> Point2 { - unsafe { cast::transmute(vec) } - } - - /// The coordinate [0, 0]. - #[inline] - pub fn origin() -> Point2 { - Point2::new(zero!(T), zero!(T)) - } -} - -impl ToVec3 for Point2 { - /// Converts the point to a three-dimensional homogeneous vector: - /// `[x, y] -> [x, y, 1]` - #[inline] - pub fn to_vec3(&self) -> Vec3 { - Vec3::new(self.x.clone(), - self.y.clone(), - one!(T)) - } -} - -impl Point, Ray2> for Point2 { - /// Applies a displacement vector to the point. - #[inline] - pub fn translate_v(&self, offset: &Vec2) -> Point2 { - Point2::new(self.x + offset.x, - self.y + offset.y) - } - - /// Scales the distance from the point to the origin by a scalar value. - #[inline] - pub fn scale_s(&self, factor: T) -> Point2 { - Point2::new(self.x * factor, - self.y * factor) - } - - /// Scales the distance from the point to the origin using the components - /// of a vector. - #[inline] - pub fn scale_v(&self, factor: &Vec2) -> Point2 { - Point2::new(self.x * factor.x, - self.y * factor.y) - } - - /// Calculates the displacement required to move the point to `other`. - pub fn displacement(&self, other: &Point2) -> Vec2 { - Vec2::new(self.x - other.x, - self.y - other.y) - } - - /// Returns the squared distance from the point to `other`. This does not - /// perform a square root operation like in the `distance` method and can - /// therefore be more efficient for distance comparisons where the actual - /// distance is not needed. - #[inline] - pub fn distance2(&self, other: &Point2) -> T { - ((*other) - (*self)).magnitude2() - } - - /// Returns the scalar distance to the other point. - #[inline] - pub fn distance(&self, other: &Point2) -> T { - other.distance2(self).sqrt() - } - - /// Returns a normalized direction vector pointing to the other point. - #[inline] - pub fn direction(&self, other: &Point2) -> Vec2 { - ((*other) - (*self)).normalize() - } - - /// Projects a normalized ray towards the other point. - #[inline] - pub fn ray_to(&self, other: &Point2) -> Ray2 { - Ray2::new(self.clone(), self.direction(other)) - } -} - -impl Add, Point2> for Point2 { - /// Applies a displacement vector to the point. - fn add(&self, offset: &Vec2) -> Point2 { - self.translate_v(offset) - } -} - -impl Sub, Vec2> for Point2 { - /// Calculates the displacement vector from the point to `other`. - fn sub(&self, other: &Point2) -> Vec2 { - self.displacement(other) - } -} - -impl Mul, Point2> for Point2 { - /// Scales the distance from the point to the origin using the components - /// of a vector. - fn mul(&self, factor: &Vec2) -> Point2 { - self.scale_v(factor) - } -} - -impl ToStr for Point2 { - pub fn to_str(&self) -> ~str { - fmt!("[%?, %?]", self.x, self.y) - } -} - -#[cfg(test)] -mod test_point2 { - use math::point::*; - - #[test] - fn test_to_str() { - assert_eq!(Point2::new(1, 2).to_str(), ~"[1, 2]"); - } -} - -/// A three-dimensional coordinate vector -#[deriving(Clone, Eq)] -pub struct Point3 { x: T, y: T, z: T } - -impl_dimensioned!(Point3, T, 3) -impl_to_vec!(Point3, 3) -impl_as_vec!(Point3, 3) -impl_swap_components!(Point3) -impl_approx!(Point3 { x, y, z }) - -pub trait AsPoint3 { - pub fn as_point3<'a>(&'a self) -> &'a Point3; - pub fn as_mut_point3<'a>(&'a mut self) -> &'a mut Point3; -} - -impl AsPoint3 for Vec3 { - #[inline] - pub fn as_point3<'a>(&'a self) -> &'a Point3 { - unsafe { cast::transmute(self) } - } - - #[inline] - pub fn as_mut_point3<'a>(&'a mut self) -> &'a mut Point3 { - unsafe { cast::transmute(self) } - } -} - -impl Point3 { - /// Creates a new point from three coordinates. - #[inline] - pub fn new(x: T, y: T, z: T) -> Point3 { - Point3 { x: x, y: y, z: z } - } - - /// Converts a vector to a point. - #[inline] - pub fn from_vec3(vec: Vec3) -> Point3 { - unsafe { cast::transmute(vec) } - } - - /// The coordinate [0, 0, 0]. - #[inline] - pub fn origin() -> Point3 { - Point3::new(zero!(T), zero!(T), zero!(T)) - } -} - -impl ToVec4 for Point3 { - /// Converts the point to a four-dimensional homogeneous vector: - /// `[x, y, z] -> [x, y, z, 1]` - #[inline] - pub fn to_vec4(&self) -> Vec4 { - Vec4::new(self.x.clone(), - self.y.clone(), - self.z.clone(), - one!(T)) - } -} - -impl Point, Ray3> for Point3 { - /// Applies a displacement vector to the point. - #[inline] - pub fn translate_v(&self, offset: &Vec3) -> Point3 { - Point3::new(self.x + offset.x, - self.y + offset.y, - self.z + offset.z) - } - - /// Scales the distance from the point to the origin by a scalar value. - #[inline] - pub fn scale_s(&self, factor: T) -> Point3 { - Point3::new(self.x * factor, - self.y * factor, - self.z * factor) - } - - /// Scales the distance from the point to the origin using the components - /// of a vector. - #[inline] - pub fn scale_v(&self, factor: &Vec3) -> Point3 { - Point3::new(self.x * factor.x, - self.y * factor.y, - self.z * factor.z) - } - - /// Calculates the displacement required to move the point to `other`. - pub fn displacement(&self, other: &Point3) -> Vec3 { - Vec3::new(self.x - other.x, - self.y - other.y, - self.z - other.z) - } - - /// Returns the squared distance from the point to `other`. This does not - /// perform a square root operation like in the `distance` method and can - /// therefore be more efficient for distance comparisons where the actual - /// distance is not needed. - #[inline] - pub fn distance2(&self, other: &Point3) -> T { - ((*other) - (*self)).magnitude2() - } - - /// Returns the scalar distance to the other point. - #[inline] - pub fn distance(&self, other: &Point3) -> T { - other.distance2(self).sqrt() - } - - /// Returns a normalized direction vector pointing to the other point. - #[inline] - pub fn direction(&self, other: &Point3) -> Vec3 { - ((*other) - (*self)).normalize() - } - - /// Projects a normalized ray towards the other point. - #[inline] - pub fn ray_to(&self, other: &Point3) -> Ray3 { - Ray3::new(self.clone(), self.direction(other)) - } -} - -impl Add, Point3> for Point3 { - /// Applies a displacement vector to the point - fn add(&self, offset: &Vec3) -> Point3 { - self.translate_v(offset) - } -} - -impl Sub, Vec3> for Point3 { - /// Calculates the displacement required to move the point to `other`. - fn sub(&self, other: &Point3) -> Vec3 { - self.displacement(other) - } -} - -impl Mul, Point3> for Point3 { - /// Scales the distance from the point to the origin using the components - /// of a vector. - fn mul(&self, factor: &Vec3) -> Point3 { - self.scale_v(factor) - } -} - -impl ToStr for Point3 { - pub fn to_str(&self) -> ~str { - fmt!("[%?, %?, %?]", self.x, self.y, self.z) - } -} - -#[cfg(test)] -mod test_point3 { - use math::point::*; - - #[test] - fn test_to_str() { - assert_eq!(Point3::new(1, 2, 3).to_str(), ~"[1, 2, 3]"); - } -} diff --git a/src-old/math/quat.rs b/src-old/math/quat.rs deleted file mode 100644 index ab743f7..0000000 --- a/src-old/math/quat.rs +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Quaternion type - -use math::{Dimensioned, SwapComponents}; -use math::{Mat3, ToMat3}; -use math::Vec3; - -// GLSL-style type aliases - -pub type quat = Quat; -pub type dquat = Quat; - -// Rust-style type aliases - -pub type Quatf = Quat; -pub type Quatf32 = Quat; -pub type Quatf64 = Quat; - -/// A quaternion in scalar/vector form -#[deriving(Clone, Eq)] -pub struct Quat { s: T, v: Vec3 } - -impl_dimensioned!(Quat, T, 4) -impl_swap_components!(Quat) -impl_approx!(Quat { s, v }) - -pub trait ToQuat { - pub fn to_quat(&self) -> Quat; -} - -impl Quat { - /// Construct the quaternion from one scalar component and three - /// imaginary components - /// - /// # Arguments - /// - /// - `w`: the scalar component - /// - `xi`: the fist imaginary component - /// - `yj`: the second imaginary component - /// - `zk`: the third imaginary component - #[inline] - pub fn new(w: T, xi: T, yj: T, zk: T) -> Quat { - Quat::from_sv(w, Vec3::new(xi, yj, zk)) - } - - /// Construct the quaternion from a scalar and a vector - /// - /// # Arguments - /// - /// - `s`: the scalar component - /// - `v`: a vector containing the three imaginary components - #[inline] - pub fn from_sv(s: T, v: Vec3) -> Quat { - Quat { s: s, v: v } - } -} - -impl Quat { - #[inline] - pub fn look_at(dir: &Vec3, up: &Vec3) -> Quat { - Mat3::look_at(dir, up).to_quat() - } - - #[inline] - pub fn from_axes(x: Vec3, y: Vec3, z: Vec3) -> Quat { - Mat3::from_axes(x, y, z).to_quat() - } - - /// The multiplicative identity, ie: `q = 1 + 0i + 0j + 0i` - #[inline] - pub fn identity() -> Quat { - Quat::from_sv(one!(T), Vec3::zero()) - } - - /// The additive identity, ie: `q = 0 + 0i + 0j + 0i` - #[inline] - pub fn zero() -> Quat { - Quat::new(zero!(T), zero!(T), zero!(T), zero!(T)) - } - - /// The result of multiplying the quaternion a scalar - #[inline] - pub fn mul_s(&self, value: T) -> Quat { - Quat::from_sv(self.s * value, self.v.mul_s(value)) - } - - /// The result of dividing the quaternion a scalar - #[inline] - pub fn div_s(&self, value: T) -> Quat { - Quat::from_sv(self.s / value, self.v.div_s(value)) - } - - /// The result of multiplying the quaternion by a vector - #[inline] - pub fn mul_v(&self, vec: &Vec3) -> Vec3 { - let tmp = self.v.cross(vec).add_v(&vec.mul_s(self.s.clone())); - self.v.cross(&tmp).mul_s(two!(T)).add_v(vec) - } - - /// The sum of this quaternion and `other` - #[inline] - pub fn add_q(&self, other: &Quat) -> Quat { - Quat::new(*self.i(0) + *other.i(0), - *self.i(1) + *other.i(1), - *self.i(2) + *other.i(2), - *self.i(3) + *other.i(3)) - } - - /// The sum of this quaternion and `other` - #[inline] - pub fn sub_q(&self, other: &Quat) -> Quat { - Quat::new(*self.i(0) - *other.i(0), - *self.i(1) - *other.i(1), - *self.i(2) - *other.i(2), - *self.i(3) - *other.i(3)) - } - - /// The the result of multipliplying the quaternion by `other` - pub fn mul_q(&self, other: &Quat) -> Quat { - Quat::new(self.s * other.s - self.v.x * other.v.x - self.v.y * other.v.y - self.v.z * other.v.z, - self.s * other.v.x + self.v.x * other.s + self.v.y * other.v.z - self.v.z * other.v.y, - self.s * other.v.y + self.v.y * other.s + self.v.z * other.v.x - self.v.x * other.v.z, - self.s * other.v.z + self.v.z * other.s + self.v.x * other.v.y - self.v.y * other.v.x) - } - - /// The dot product of the quaternion and `other` - #[inline] - pub fn dot(&self, other: &Quat) -> T { - self.s * other.s + self.v.dot(&other.v) - } - - /// The conjugate of the quaternion - #[inline] - pub fn conjugate(&self) -> Quat { - Quat::from_sv(self.s.clone(), -self.v.clone()) - } - - /// The multiplicative inverse of the quaternion - #[inline] - pub fn inverse(&self) -> Quat { - self.conjugate().div_s(self.magnitude2()) - } - - /// The squared magnitude of the quaternion. This is useful for - /// magnitude comparisons where the exact magnitude does not need to be - /// calculated. - #[inline] - pub fn magnitude2(&self) -> T { - self.s * self.s + self.v.magnitude2() - } - - /// The magnitude of the quaternion - /// - /// # Performance notes - /// - /// For instances where the exact magnitude of the quaternion does not need - /// to be known, for example for quaternion-quaternion magnitude comparisons, - /// it is advisable to use the `magnitude2` method instead. - #[inline] - pub fn magnitude(&self) -> T { - self.magnitude2().sqrt() - } - - /// The normalized quaternion - #[inline] - pub fn normalize(&self) -> Quat { - self.mul_s(one!(T) / self.magnitude()) - } - - /// Normalised linear interpolation - /// - /// # Return value - /// - /// The intoperlated quaternion - pub fn nlerp(&self, other: &Quat, amount: T) -> Quat { - self.mul_s(one!(T) - amount).add_q(&other.mul_s(amount)).normalize() - } - - /// Spherical Linear Intoperlation - /// - /// Perform a spherical linear interpolation between the quaternion and - /// `other`. Both quaternions should be normalized first. - /// - /// # Return value - /// - /// The intoperlated quaternion - /// - /// # Performance notes - /// - /// The `acos` operation used in `slerp` is an expensive operation, so unless - /// your quarternions a far away from each other it's generally more advisable - /// to use `nlerp` when you know your rotations are going to be small. - /// - /// - [Understanding Slerp, Then Not Using It] - /// (http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/) - /// - [Arcsynthesis OpenGL tutorial] - /// (http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Interpolation.html) - pub fn slerp(&self, other: &Quat, amount: T) -> Quat { - use std::num::cast; - - let dot = self.dot(other); - let dot_threshold = cast(0.9995); - - // if quaternions are close together use `nlerp` - if dot > dot_threshold { - self.nlerp(other, amount) - } else { - // stay within the domain of acos() - let robust_dot = dot.clamp(&-one!(T), &one!(T)); - - let theta_0 = robust_dot.acos(); // the angle between the quaternions - let theta = theta_0 * amount; // the fraction of theta specified by `amount` - - let q = other.sub_q(&self.mul_s(robust_dot)) - .normalize(); - - self.mul_s(theta.cos()) - .add_q(&q.mul_s(theta.sin())) - } - } -} - -impl ToMat3 for Quat { - /// Convert the quaternion to a 3 x 3 rotation matrix - pub fn to_mat3(&self) -> Mat3 { - let x2 = self.v.x + self.v.x; - let y2 = self.v.y + self.v.y; - let z2 = self.v.z + self.v.z; - - let xx2 = x2 * self.v.x; - let xy2 = x2 * self.v.y; - let xz2 = x2 * self.v.z; - - let yy2 = y2 * self.v.y; - let yz2 = y2 * self.v.z; - let zz2 = z2 * self.v.z; - - let sy2 = y2 * self.s; - let sz2 = z2 * self.s; - let sx2 = x2 * self.s; - - let _1: T = one!(T); - - Mat3::new(_1 - yy2 - zz2, xy2 + sz2, xz2 - sy2, - xy2 - sz2, _1 - xx2 - zz2, yz2 + sx2, - xz2 + sy2, yz2 - sx2, _1 - xx2 - yy2) - } -} - -impl Neg> for Quat { - #[inline] - pub fn neg(&self) -> Quat { - Quat::from_sv(-self.s, -self.v) - } -} diff --git a/src-old/math/ray.rs b/src-old/math/ray.rs deleted file mode 100644 index ec20eef..0000000 --- a/src-old/math/ray.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2013 The Lmath Developers. For a full listing of the authors, -// refer to the AUTHORS file at the top-level directionectory 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. - -//! Ray types - -use math::{Point2, Point3}; -use math::{Vec2, Vec3}; - -#[deriving(Clone, Eq)] -pub struct Ray2 { - origin: Point2, - direction: Vec2, -} - -impl_approx!(Ray2 { origin, direction }) - -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 } - } -} - -#[deriving(Clone, Eq)] -pub struct Ray3 { - origin: Point3, - direction: Vec3, -} - -impl_approx!(Ray3 { origin, direction }) - -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 } - } -} diff --git a/src-old/math/vec.rs b/src-old/math/vec.rs deleted file mode 100644 index c643bcf..0000000 --- a/src-old/math/vec.rs +++ /dev/null @@ -1,2161 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Abstract vector types - -use math::{Dimensioned, SwapComponents}; - -/// Generic vector trait -pub trait Vec: Dimensioned - + SwapComponents {} - -/// Vectors with numeric components -pub trait NumVec: Neg { - pub fn add_s(&self, value: T) -> Self; - pub fn sub_s(&self, value: T) -> Self; - pub fn mul_s(&self, value: T) -> Self; - pub fn div_s(&self, value: T) -> Self; - pub fn rem_s(&self, value: T) -> Self; - - pub fn add_v(&self, other: &Self) -> Self; - pub fn sub_v(&self, other: &Self) -> Self; - pub fn mul_v(&self, other: &Self) -> Self; - pub fn div_v(&self, other: &Self) -> Self; - pub fn rem_v(&self, other: &Self) -> Self; - - pub fn neg_self(&mut self); - pub fn add_self_s(&mut self, value: T); - pub fn sub_self_s(&mut self, value: T); - pub fn mul_self_s(&mut self, value: T); - pub fn div_self_s(&mut self, value: T); - pub fn rem_self_s(&mut self, value: T); - - pub fn add_self_v(&mut self, other: &Self); - pub fn sub_self_v(&mut self, other: &Self); - pub fn mul_self_v(&mut self, other: &Self); - pub fn div_self_v(&mut self, other: &Self); - pub fn rem_self_v(&mut self, other: &Self); - - pub fn dot(&self, other: &Self) -> T; - - pub fn comp_add(&self) -> T; - pub fn comp_mul(&self) -> T; -} - -/// Vectors with floating point components -pub trait FloatVec: NumVec + ApproxEq { - pub fn magnitude2(&self) -> T; - pub fn magnitude(&self) -> T; - pub fn angle(&self, other: &Self) -> T; - pub fn normalize(&self) -> Self; - pub fn normalize_to(&self, magnitude: T) -> Self; - pub fn lerp(&self, other: &Self, amount: T) -> Self; - pub fn normalize_self(&mut self); - pub fn normalize_self_to(&mut self, magnitude: T); - pub fn lerp_self(&mut self, other: &Self, amount: T); -} - -/// Vectors with orderable components -pub trait OrdVec: Vec { - pub fn lt_s(&self, value: T) -> BV; - pub fn le_s(&self, value: T) -> BV; - pub fn ge_s(&self, value: T) -> BV; - pub fn gt_s(&self, value: T) -> BV; - - pub fn lt_v(&self, other: &Self) -> BV; - pub fn le_v(&self, other: &Self) -> BV; - pub fn ge_v(&self, other: &Self) -> BV; - pub fn gt_v(&self, other: &Self) -> BV; - - pub fn min_s(&self, other: T) -> Self; - pub fn max_s(&self, other: T) -> Self; - pub fn clamp_s(&self, mn: T, mx: T) -> Self; - - pub fn min_v(&self, other: &Self) -> Self; - pub fn max_v(&self, other: &Self) -> Self; - pub fn clamp_v(&self, mn: &Self, mx: &Self) -> Self; - - pub fn comp_min(&self) -> T; - pub fn comp_max(&self) -> T; -} - -/// Vectors with components that can be tested for equality -pub trait EqVec: Eq { - pub fn eq_s(&self, value: T) -> BV; - pub fn ne_s(&self, value: T) -> BV; - pub fn eq_v(&self, other: &Self) -> BV; - pub fn ne_v(&self, other: &Self) -> BV; -} - -/// Vectors with boolean components -pub trait BoolVec: Vec + Not { - pub fn any(&self) -> bool; - pub fn all(&self) -> bool; -} - -#[deriving(Clone, Eq)] -pub struct Vec2 { x: T, y: T } - -// GLSL-style type aliases -pub type vec2 = Vec2; -pub type dvec2 = Vec2; -pub type bvec2 = Vec2; -pub type ivec2 = Vec2; -pub type uvec2 = Vec2; - -// Rust-style type aliases -pub type Vec2f = Vec2; -pub type Vec2f32 = Vec2; -pub type Vec2f64 = Vec2; -pub type Vec2i = Vec2; -pub type Vec2i8 = Vec2; -pub type Vec2i16 = Vec2; -pub type Vec2i32 = Vec2; -pub type Vec2i64 = Vec2; -pub type Vec2u = Vec2; -pub type Vec2u8 = Vec2; -pub type Vec2u16 = Vec2; -pub type Vec2u32 = Vec2; -pub type Vec2u64 = Vec2; -pub type Vec2b = Vec2; - -pub trait ToVec2 { - pub fn to_vec2(&self) -> Vec2; -} - -pub trait AsVec2 { - pub fn as_vec2<'a>(&'a self) -> &'a Vec2; - pub fn as_mut_vec2<'a>(&'a mut self) -> &'a mut Vec2; - pub fn with_vec2<'a>(&'a self, f: &fn(&'a Vec2) -> Vec2) -> Self; -} - -impl_dimensioned!(Vec2, T, 2) -impl_swap_components!(Vec2) -impl_approx!(Vec2 { x, y }) - -impl Vec2 { - /// Construct a new vector from the supplied components. - #[inline] - pub fn new(x: T, y: T) -> Vec2 { - Vec2 { x: x, y: y } - } -} - -impl Vec2 { - /// Construct a new vector with each component set to `value`. - #[inline] - pub fn from_value(value: T) -> Vec2 { - Vec2::new(value.clone(), - value.clone()) - } -} - -impl ToVec3 for Vec2 { - /// Converts the vector to a three-dimensional homogeneous vector: - /// `[x, y] -> [x, y, 0]` - pub fn to_vec3(&self) -> Vec3 { - Vec3::new((*self).i(0).clone(), - (*self).i(1).clone(), - zero!(T)) - } -} - -/// Constants for two-dimensional vectors. -impl Vec2 { - /// Returns a two-dimensional vector with each component set to `1`. - #[inline] - pub fn identity() -> Vec2 { - Vec2::new(one!(T), one!(T)) - } - - /// Returns a two-dimensional vector with each component set to `0`. - #[inline] - pub fn zero() -> Vec2 { - Vec2::new(zero!(T), zero!(T)) - } - - /// Returns a zeroed two-dimensional vector with the `x` component set to `1`. - #[inline] - pub fn unit_x() -> Vec2 { - Vec2::new(one!(T), zero!(T)) - } - - /// Returns a zeroed two-dimensional vector with the `y` component set to `1`. - #[inline] - pub fn unit_y() -> Vec2 { - Vec2::new(zero!(T), one!(T)) - } -} - -/// Numeric operations specific to two-dimensional vectors. -impl Vec2 { - /// The perpendicular dot product of the vector and `other`. - #[inline] - pub fn perp_dot(&self, other: &Vec2) -> T { - (*self.i(0) * *other.i(1)) - - (*self.i(1) * *other.i(0)) - } -} - -impl Vec for Vec2 {} - -impl NumVec for Vec2 { - /// Returns a new vector with `value` added to each component. - #[inline] - pub fn add_s(&self, value: T) -> Vec2 { - Vec2::new(*self.i(0) + value, - *self.i(1) + value) - } - - /// Returns a new vector with `value` subtracted from each component. - #[inline] - pub fn sub_s(&self, value: T) -> Vec2 { - Vec2::new(*self.i(0) - value, - *self.i(1) - value) - } - - /// Returns the scalar multiplication of the vector with `value`. - #[inline] - pub fn mul_s(&self, value: T) -> Vec2 { - Vec2::new(*self.i(0) * value, - *self.i(1) * value) - } - - /// Returns a new vector with each component divided by `value`. - #[inline] - pub fn div_s(&self, value: T) -> Vec2 { - Vec2::new(*self.i(0) / value, - *self.i(1) / value) - } - - /// Returns the remainder of each component divided by `value`. - #[inline] - pub fn rem_s(&self, value: T) -> Vec2 { - Vec2::new(*self.i(0) % value, - *self.i(1) % value) - } - - /// Returns the sum of the two vectors. - #[inline] - pub fn add_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(*self.i(0) + *other.i(0), - *self.i(1) + *other.i(1)) - } - - /// Ruturns the result of subtrating `other` from the vector. - #[inline] - pub fn sub_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(*self.i(0) - *other.i(0), - *self.i(1) - *other.i(1)) - } - - /// Returns the component-wise product of the vector and `other`. - #[inline] - pub fn mul_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(*self.i(0) * *other.i(0), - *self.i(1) * *other.i(1)) - } - - /// Returns the component-wise quotient of the vectors. - #[inline] - pub fn div_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(*self.i(0) / *other.i(0), - *self.i(1) / *other.i(1)) - } - - /// Returns the component-wise remainder of the vector divided by `other`. - #[inline] - pub fn rem_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(*self.i(0) % *other.i(0), - *self.i(1) % *other.i(1)) - } - - /// Negates each component of the vector. - #[inline] - pub fn neg_self(&mut self) { - *self.mut_i(0) = -*self.i(0); - *self.mut_i(1) = -*self.i(1); - } - - /// Adds `value` to each component of the vector. - #[inline] - pub fn add_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) + value; - *self.mut_i(1) = *self.i(1) + value; - } - - /// Subtracts `value` from each component of the vector. - #[inline] - pub fn sub_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) - value; - *self.mut_i(1) = *self.i(1) - value; - } - - #[inline] - pub fn mul_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) * value; - *self.mut_i(1) = *self.i(1) * value; - } - - #[inline] - pub fn div_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) / value; - *self.mut_i(1) = *self.i(1) / value; - } - - #[inline] - pub fn rem_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) % value; - *self.mut_i(1) = *self.i(1) % value; - } - - #[inline] - pub fn add_self_v(&mut self, other: &Vec2) { - *self.mut_i(0) = *self.i(0) + *other.i(0); - *self.mut_i(1) = *self.i(1) + *other.i(1); - } - - #[inline] - pub fn sub_self_v(&mut self, other: &Vec2) { - *self.mut_i(0) = *self.i(0) - *other.i(0); - *self.mut_i(1) = *self.i(1) - *other.i(1); - } - - #[inline] - pub fn mul_self_v(&mut self, other: &Vec2) { - *self.mut_i(0) = *self.i(0) * *other.i(0); - *self.mut_i(1) = *self.i(1) * *other.i(1); - } - - #[inline] - pub fn div_self_v(&mut self, other: &Vec2) { - *self.mut_i(0) = *self.i(0) / *other.i(0); - *self.mut_i(1) = *self.i(1) / *other.i(1); - } - - #[inline] - pub fn rem_self_v(&mut self, other: &Vec2) { - *self.mut_i(0) = *self.i(0) % *other.i(0); - *self.mut_i(1) = *self.i(1) % *other.i(1); - } - - /// Returns the dot product of the vector and `other`. - #[inline] - pub fn dot(&self, other: &Vec2) -> T { - *self.i(0) * *other.i(0) + - *self.i(1) * *other.i(1) - } - - /// Returns the sum of the vector's components. - #[inline] - pub fn comp_add(&self) -> T { - *self.i(0) + *self.i(1) - } - - /// Returns the product of the vector's components. - #[inline] - pub fn comp_mul(&self) -> T { - *self.i(0) * *self.i(1) - } -} - -impl Neg> for Vec2 { - /// Returns the vector with each component negated. - #[inline] - pub fn neg(&self) -> Vec2 { - Vec2::new(-*self.i(0), - -*self.i(1)) - } -} - -impl FloatVec for Vec2 { - /// Returns the squared magnitude of the vector. This does not perform a - /// square root operation like in the `magnitude` method and can therefore - /// be more efficient for comparing the magnitudes of two vectors. - #[inline] - pub fn magnitude2(&self) -> T { - self.dot(self) - } - - /// Returns the magnitude (length) of the vector. - #[inline] - pub fn magnitude(&self) -> T { - self.magnitude2().sqrt() - } - - /// Returns the angle between the vector and `other`. - #[inline] - pub fn angle(&self, other: &Vec2) -> T { - self.perp_dot(other).atan2(&self.dot(other)) - } - - /// Returns the result of normalizing the vector to a magnitude of `1`. - #[inline] - pub fn normalize(&self) -> Vec2 { - self.normalize_to(one!(T)) - } - - /// Returns the result of normalizing the vector to `magnitude`. - #[inline] - pub fn normalize_to(&self, magnitude: T) -> Vec2 { - self.mul_s(magnitude / self.magnitude()) - } - - /// Returns the result of linarly interpolating the magnitude of the vector - /// to the magnitude of `other` by the specified amount. - #[inline] - pub fn lerp(&self, other: &Vec2, amount: T) -> Vec2 { - self.add_v(&other.sub_v(self).mul_s(amount)) - } - - /// Normalises the vector to a magnitude of `1`. - #[inline] - pub fn normalize_self(&mut self) { - let rlen = self.magnitude().recip(); - self.mul_self_s(rlen); - } - - /// Normalizes the vector to `magnitude`. - #[inline] - pub fn normalize_self_to(&mut self, magnitude: T) { - let n = magnitude / self.magnitude(); - self.mul_self_s(n); - } - - /// Linearly interpolates the magnitude of the vector to the magnitude of - /// `other` by the specified amount. - pub fn lerp_self(&mut self, other: &Vec2, amount: T) { - let v = other.sub_v(self).mul_s(amount); - self.add_self_v(&v); - } -} - -impl OrdVec> for Vec2 { - #[inline] - pub fn lt_s(&self, value: T) -> Vec2 { - Vec2::new(*self.i(0) < value, - *self.i(1) < value) - } - - #[inline] - pub fn le_s(&self, value: T) -> Vec2 { - Vec2::new(*self.i(0) <= value, - *self.i(1) <= value) - } - - #[inline] - pub fn ge_s(&self, value: T) -> Vec2 { - Vec2::new(*self.i(0) >= value, - *self.i(1) >= value) - } - - #[inline] - pub fn gt_s(&self, value: T) -> Vec2 { - Vec2::new(*self.i(0) > value, - *self.i(1) > value) - } - - #[inline] - pub fn lt_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(*self.i(0) < *other.i(0), - *self.i(1) < *other.i(1)) - } - - #[inline] - pub fn le_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(*self.i(0) <= *other.i(0), - *self.i(1) <= *other.i(1)) - } - - #[inline] - pub fn ge_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(*self.i(0) >= *other.i(0), - *self.i(1) >= *other.i(1)) - } - - #[inline] - pub fn gt_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(*self.i(0) > *other.i(0), - *self.i(1) > *other.i(1)) - } - - #[inline] - pub fn min_s(&self, value: T) -> Vec2 { - Vec2::new(self.i(0).min(&value), - self.i(1).min(&value)) - } - - #[inline] - pub fn max_s(&self, value: T) -> Vec2 { - Vec2::new(self.i(0).max(&value), - self.i(1).max(&value)) - } - - #[inline] - pub fn clamp_s(&self, mn: T, mx: T) -> Vec2 { - Vec2::new(self.i(0).clamp(&mn, &mx), - self.i(1).clamp(&mn, &mx)) - } - - #[inline] - pub fn min_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(self.i(0).min(other.i(0)), - self.i(1).min(other.i(1))) - } - - #[inline] - pub fn max_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(self.i(0).max(other.i(0)), - self.i(1).max(other.i(1))) - } - - #[inline] - pub fn clamp_v(&self, mn: &Vec2, mx: &Vec2) -> Vec2 { - Vec2::new(self.i(0).clamp(mn.i(0), mx.i(0)), - self.i(1).clamp(mn.i(1), mx.i(1))) - } - - /// Returns the smallest component of the vector. - #[inline] - pub fn comp_min(&self) -> T { - self.i(0).min(self.i(1)) - } - - /// Returns the largest component of the vector. - #[inline] - pub fn comp_max(&self) -> T { - self.i(0).max(self.i(1)) - } -} - -impl EqVec> for Vec2 { - #[inline] - pub fn eq_s(&self, value: T) -> Vec2 { - Vec2::new(*self.i(0) == value, - *self.i(1) == value) - } - - #[inline] - pub fn ne_s(&self, value: T) -> Vec2 { - Vec2::new(*self.i(0) != value, - *self.i(1) != value) - } - - #[inline] - pub fn eq_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(*self.i(0) == *other.i(0), - *self.i(1) == *other.i(1)) - } - - #[inline] - pub fn ne_v(&self, other: &Vec2) -> Vec2 { - Vec2::new(*self.i(0) != *other.i(0), - *self.i(1) != *other.i(1)) - } -} - -impl BoolVec<[bool,..2]> for Vec2 { - /// Returns `true` if any of the components of the vector are equal to - /// `true`, otherwise `false`. - #[inline] - pub fn any(&self) -> bool { - *self.i(0) || *self.i(1) - } - - /// Returns `true` if _all_ of the components of the vector are equal to - /// `true`, otherwise `false`. - #[inline] - pub fn all(&self) -> bool { - *self.i(0) && *self.i(1) - } -} - -impl> Not> for Vec2 { - pub fn not(&self) -> Vec2 { - Vec2::new(!*self.i(0), - !*self.i(1)) - } -} - -#[cfg(test)] -mod vec2_tests { - use math::vec::*; - - static A: Vec2 = Vec2 { x: 1.0, y: 2.0 }; - static B: Vec2 = Vec2 { x: 3.0, y: 4.0 }; - static F1: float = 1.5; - static F2: float = 0.5; - - #[test] - fn test_swap() { - let mut mut_a = A; - - mut_a.swap(0, 1); - assert_eq!(*mut_a.i(0), *A.i(1)); - assert_eq!(*mut_a.i(1), *A.i(0)); - } - - #[test] - fn test_num() { - let mut mut_a = A; - - assert_eq!(-A, Vec2::new::(-1.0, -2.0)); - assert_eq!(A.neg(), Vec2::new::(-1.0, -2.0)); - - assert_eq!(A.mul_s(F1), Vec2::new::(1.5, 3.0)); - assert_eq!(A.div_s(F2), Vec2::new::(2.0, 4.0)); - - assert_eq!(A.add_v(&B), Vec2::new::(4.0, 6.0)); - assert_eq!(A.sub_v(&B), Vec2::new::(-2.0, -2.0)); - assert_eq!(A.mul_v(&B), Vec2::new::(3.0, 8.0)); - assert_eq!(A.div_v(&B), Vec2::new::(1.0/3.0, 2.0/4.0)); - - mut_a.neg_self(); - assert_eq!(mut_a, -A); - mut_a = A; - - mut_a.mul_self_s(F1); - assert_eq!(mut_a, A.mul_s(F1)); - mut_a = A; - - mut_a.div_self_s(F2); - assert_eq!(mut_a, A.div_s(F2)); - mut_a = A; - - mut_a.add_self_v(&B); - assert_eq!(mut_a, A.add_v(&B)); - mut_a = A; - - mut_a.sub_self_v(&B); - assert_eq!(mut_a, A.sub_v(&B)); - mut_a = A; - - mut_a.mul_self_v(&B); - assert_eq!(mut_a, A.mul_v(&B)); - mut_a = A; - - mut_a.div_self_v(&B); - assert_eq!(mut_a, A.div_v(&B)); - } - - #[test] - fn test_comp_add() { - assert_eq!(A.comp_add(), 3.0); - assert_eq!(B.comp_add(), 7.0); - } - - #[test] - fn test_comp_mul() { - assert_eq!(A.comp_mul(), 2.0); - assert_eq!(B.comp_mul(), 12.0); - } - - #[test] - fn test_approx_eq() { - assert!(!Vec2::new::(0.000001, 0.000001).approx_eq(&Vec2::new::(0.0, 0.0))); - assert!(Vec2::new::(0.0000001, 0.0000001).approx_eq(&Vec2::new::(0.0, 0.0))); - } - - #[test] - fn test_magnitude() { - let a = Vec2::new(5.0, 12.0); // (5, 12, 13) Pythagorean triple - let b = Vec2::new(3.0, 4.0); // (3, 4, 5) Pythagorean triple - - assert_eq!(a.magnitude(), 13.0); - assert_eq!(a.magnitude2(), 13.0 * 13.0); - - assert_eq!(b.magnitude(), 5.0); - assert_eq!(b.magnitude2(), 5.0 * 5.0); - } - - #[test] - fn test_angle() { - assert!(Vec2::new::(1.0, 0.0).angle(&Vec2::new::(0.0, 1.0)).approx_eq(&Real::frac_pi_2())); - assert!(Vec2::new::(10.0, 0.0).angle(&Vec2::new::(0.0, 5.0)).approx_eq(&Real::frac_pi_2())); - assert!(Vec2::new::(-1.0, 0.0).angle(&Vec2::new::(0.0, 1.0)).approx_eq(&-Real::frac_pi_2::())); - } - - #[test] - fn test_normalize() { - assert!(Vec2::new::(3.0, 4.0).normalize().approx_eq(&Vec2::new::(3.0/5.0, 4.0/5.0))); - // TODO: test normalize_to, normalize_self, and normalize_self_to - } - - #[test] - fn test_lerp() { - let c = Vec2::new::(-2.0, -1.0); - let d = Vec2::new::( 1.0, 0.0); - - assert_eq!(c.lerp(&d, 0.75), Vec2::new::(0.250, -0.250)); - - let mut mut_c = c; - mut_c.lerp_self(&d, 0.75); - assert_eq!(mut_c, c.lerp(&d, 0.75)); - } - - #[test] - fn test_comp_min() { - assert_eq!(A.comp_min(), 1.0); - assert_eq!(B.comp_min(), 3.0); - } - - #[test] - fn test_comp_max() { - assert_eq!(A.comp_max(), 2.0); - assert_eq!(B.comp_max(), 4.0); - } - - #[test] - fn test_boolean() { - let tf = Vec2::new(true, false); - let ff = Vec2::new(false, false); - let tt = Vec2::new(true, true); - - assert_eq!(tf.any(), true); - assert_eq!(tf.all(), false); - assert_eq!(!tf, Vec2::new(false, true)); - - assert_eq!(ff.any(), false); - assert_eq!(ff.all(), false); - assert_eq!(!ff, Vec2::new(true, true)); - - assert_eq!(tt.any(), true); - assert_eq!(tt.all(), true); - assert_eq!(!tt, Vec2::new(false, false)); - } -} - -#[deriving(Clone, Eq)] -pub struct Vec3 { x: T, y: T, z: T } - -// GLSL-style type aliases -pub type vec3 = Vec3; -pub type dvec3 = Vec3; -pub type bvec3 = Vec3; -pub type ivec3 = Vec3; -pub type uvec3 = Vec3; - -// Rust-style type aliases -pub type Vec3f = Vec3; -pub type Vec3f32 = Vec3; -pub type Vec3f64 = Vec3; -pub type Vec3i = Vec3; -pub type Vec3i8 = Vec3; -pub type Vec3i16 = Vec3; -pub type Vec3i32 = Vec3; -pub type Vec3i64 = Vec3; -pub type Vec3u = Vec3; -pub type Vec3u8 = Vec3; -pub type Vec3u16 = Vec3; -pub type Vec3u32 = Vec3; -pub type Vec3u64 = Vec3; -pub type Vec3b = Vec3; - -pub trait ToVec3 { - pub fn to_vec3(&self) -> Vec3; -} - -pub trait AsVec3 { - pub fn as_vec3<'a>(&'a self) -> &'a Vec3; - pub fn as_mut_vec3<'a>(&'a mut self) -> &'a mut Vec3; - pub fn with_vec3<'a>(&'a self, f: &fn(&'a Vec3) -> Vec3) -> Self; -} - -impl_dimensioned!(Vec3, T, 3) -impl_swap_components!(Vec3) -impl_approx!(Vec3 { x, y, z }) - -impl Vec3 { - /// Construct a new vector from the supplied components. - #[inline] - pub fn new(x: T, y: T, z: T) -> Vec3 { - Vec3 { x: x, y: y, z: z } - } -} - -impl Vec3 { - /// Construct a new vector with each component set to `value`. - #[inline] - pub fn from_value(value: T) -> Vec3 { - Vec3::new(value.clone(), - value.clone(), - value.clone()) - } -} - -impl ToVec4 for Vec3 { - /// Converts the vector to a four-dimensional homogeneous vector: - /// `[x, y, z] -> [x, y, z, 0]` - pub fn to_vec4(&self) -> Vec4 { - Vec4::new((*self).i(0).clone(), - (*self).i(1).clone(), - (*self).i(2).clone(), - zero!(T)) - } -} - -/// Constants for three-dimensional vectors. -impl Vec3 { - /// Returns a three-dimensional vector with each component set to `1`. - #[inline] - pub fn identity() -> Vec3 { - Vec3::new(one!(T), one!(T), one!(T)) - } - - /// Returns a three-dimensional vector with each component set to `0`. - #[inline] - pub fn zero() -> Vec3 { - Vec3::new(zero!(T), zero!(T), zero!(T)) - } - - /// Returns a zeroed three-dimensional vector with the `x` component set to `1`. - #[inline] - pub fn unit_x() -> Vec3 { - Vec3::new(one!(T), zero!(T), zero!(T)) - } - - /// Returns a zeroed three-dimensional vector with the `y` component set to `1`. - #[inline] - pub fn unit_y() -> Vec3 { - Vec3::new(zero!(T), one!(T), zero!(T)) - } - - /// Returns a zeroed three-dimensional vector with the `z` component set to `1`. - #[inline] - pub fn unit_z() -> Vec3 { - Vec3::new(zero!(T), zero!(T), one!(T)) - } -} - -/// Numeric operations specific to three-dimensional vectors. -impl Vec3 { - /// Returns the cross product of the vector and `other`. - #[inline] - pub fn cross(&self, other: &Vec3) -> Vec3 { - Vec3::new((*self.i(1) * *other.i(2)) - (*self.i(2) * *other.i(1)), - (*self.i(2) * *other.i(0)) - (*self.i(0) * *other.i(2)), - (*self.i(0) * *other.i(1)) - (*self.i(1) * *other.i(0))) - } - - /// Calculates the cross product of the vector and `other`, then stores the - /// result in `self`. - #[inline] - pub fn cross_self(&mut self, other: &Vec3) { - *self = self.cross(other) - } -} - -impl Vec for Vec3 {} - -impl NumVec for Vec3 { - /// Returns a new vector with `value` added to each component. - #[inline] - pub fn add_s(&self, value: T) -> Vec3 { - Vec3::new(*self.i(0) + value, - *self.i(1) + value, - *self.i(2) + value) - } - - /// Returns a new vector with `value` subtracted from each component. - #[inline] - pub fn sub_s(&self, value: T) -> Vec3 { - Vec3::new(*self.i(0) - value, - *self.i(1) - value, - *self.i(2) - value) - } - - /// Returns the scalar multiplication of the vector with `value`. - #[inline] - pub fn mul_s(&self, value: T) -> Vec3 { - Vec3::new(*self.i(0) * value, - *self.i(1) * value, - *self.i(2) * value) - } - - /// Returns a new vector with each component divided by `value`. - #[inline] - pub fn div_s(&self, value: T) -> Vec3 { - Vec3::new(*self.i(0) / value, - *self.i(1) / value, - *self.i(2) / value) - } - - /// Returns the remainder of each component divided by `value`. - #[inline] - pub fn rem_s(&self, value: T) -> Vec3 { - Vec3::new(*self.i(0) % value, - *self.i(1) % value, - *self.i(2) % value) - } - - /// Returns the sum of the two vectors. - #[inline] - pub fn add_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(*self.i(0) + *other.i(0), - *self.i(1) + *other.i(1), - *self.i(2) + *other.i(2)) - } - - /// Ruturns the result of subtrating `other` from the vector. - #[inline] - pub fn sub_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(*self.i(0) - *other.i(0), - *self.i(1) - *other.i(1), - *self.i(2) - *other.i(2)) - } - - /// Returns the component-wise product of the vector and `other`. - #[inline] - pub fn mul_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(*self.i(0) * *other.i(0), - *self.i(1) * *other.i(1), - *self.i(2) * *other.i(2)) - } - - /// Returns the component-wise quotient of the vectors. - #[inline] - pub fn div_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(*self.i(0) / *other.i(0), - *self.i(1) / *other.i(1), - *self.i(2) / *other.i(2)) - } - - /// Returns the component-wise remainder of the vector divided by `other`. - #[inline] - pub fn rem_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(*self.i(0) % *other.i(0), - *self.i(1) % *other.i(1), - *self.i(2) % *other.i(2)) - } - - /// Negates each component of the vector. - #[inline] - pub fn neg_self(&mut self) { - *self.mut_i(0) = -*self.i(0); - *self.mut_i(1) = -*self.i(1); - *self.mut_i(2) = -*self.i(2); - } - - /// Adds `value` to each component of the vector. - #[inline] - pub fn add_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) + value; - *self.mut_i(1) = *self.i(1) + value; - *self.mut_i(2) = *self.i(2) + value; - } - - /// Subtracts `value` from each component of the vector. - #[inline] - pub fn sub_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) - value; - *self.mut_i(1) = *self.i(1) - value; - *self.mut_i(2) = *self.i(2) - value; - } - - #[inline] - pub fn mul_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) * value; - *self.mut_i(1) = *self.i(1) * value; - *self.mut_i(2) = *self.i(2) * value; - } - - #[inline] - pub fn div_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) / value; - *self.mut_i(1) = *self.i(1) / value; - *self.mut_i(2) = *self.i(2) / value; - } - - #[inline] - pub fn rem_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) % value; - *self.mut_i(1) = *self.i(1) % value; - *self.mut_i(2) = *self.i(2) % value; - } - - #[inline] - pub fn add_self_v(&mut self, other: &Vec3) { - *self.mut_i(0) = *self.i(0) + *other.i(0); - *self.mut_i(1) = *self.i(1) + *other.i(1); - *self.mut_i(2) = *self.i(2) + *other.i(2); - } - - #[inline] - pub fn sub_self_v(&mut self, other: &Vec3) { - *self.mut_i(0) = *self.i(0) - *other.i(0); - *self.mut_i(1) = *self.i(1) - *other.i(1); - *self.mut_i(2) = *self.i(2) - *other.i(2); - } - - #[inline] - pub fn mul_self_v(&mut self, other: &Vec3) { - *self.mut_i(0) = *self.i(0) * *other.i(0); - *self.mut_i(1) = *self.i(1) * *other.i(1); - *self.mut_i(2) = *self.i(2) * *other.i(2); - } - - #[inline] - pub fn div_self_v(&mut self, other: &Vec3) { - *self.mut_i(0) = *self.i(0) / *other.i(0); - *self.mut_i(1) = *self.i(1) / *other.i(1); - *self.mut_i(2) = *self.i(2) / *other.i(2); - } - - #[inline] - pub fn rem_self_v(&mut self, other: &Vec3) { - *self.mut_i(0) = *self.i(0) % *other.i(0); - *self.mut_i(1) = *self.i(1) % *other.i(1); - *self.mut_i(2) = *self.i(2) % *other.i(2); - } - - /// Returns the dot product of the vector and `other`. - #[inline] - pub fn dot(&self, other: &Vec3) -> T { - *self.i(0) * *other.i(0) + - *self.i(1) * *other.i(1) + - *self.i(2) * *other.i(2) - } - - /// Returns the sum of the vector's components. - #[inline] - pub fn comp_add(&self) -> T { - *self.i(0) + *self.i(1) + *self.i(2) - } - - /// Returns the product of the vector's components. - #[inline] - pub fn comp_mul(&self) -> T { - *self.i(0) * *self.i(1) * *self.i(2) - } -} - -impl Neg> for Vec3 { - /// Returns the vector with each component negated. - #[inline] - pub fn neg(&self) -> Vec3 { - Vec3::new(-*self.i(0), - -*self.i(1), - -*self.i(2)) - } -} - -impl FloatVec for Vec3 { - /// Returns the squared magnitude of the vector. This does not perform a - /// square root operation like in the `magnitude` method and can therefore - /// be more efficient for comparing the magnitudes of two vectors. - #[inline] - pub fn magnitude2(&self) -> T { - self.dot(self) - } - - /// Returns the magnitude (length) of the vector. - #[inline] - pub fn magnitude(&self) -> T { - self.magnitude2().sqrt() - } - - /// Returns the angle between the vector and `other`. - #[inline] - pub fn angle(&self, other: &Vec3) -> T { - self.cross(other).magnitude().atan2(&self.dot(other)) - } - - /// Returns the result of normalizing the vector to a magnitude of `1`. - #[inline] - pub fn normalize(&self) -> Vec3 { - self.normalize_to(one!(T)) - } - - /// Returns the result of normalizing the vector to `magnitude`. - #[inline] - pub fn normalize_to(&self, magnitude: T) -> Vec3 { - self.mul_s(magnitude / self.magnitude()) - } - - /// Returns the result of linarly interpolating the magnitude of the vector - /// to the magnitude of `other` by the specified amount. - #[inline] - pub fn lerp(&self, other: &Vec3, amount: T) -> Vec3 { - self.add_v(&other.sub_v(self).mul_s(amount)) - } - - /// Normalises the vector to a magnitude of `1`. - #[inline] - pub fn normalize_self(&mut self) { - let rlen = self.magnitude().recip(); - self.mul_self_s(rlen); - } - - /// Normalizes the vector to `magnitude`. - #[inline] - pub fn normalize_self_to(&mut self, magnitude: T) { - let n = magnitude / self.magnitude(); - self.mul_self_s(n); - } - - /// Linearly interpolates the magnitude of the vector to the magnitude of - /// `other` by the specified amount. - pub fn lerp_self(&mut self, other: &Vec3, amount: T) { - let v = other.sub_v(self).mul_s(amount); - self.add_self_v(&v); - } -} - -impl OrdVec> for Vec3 { - #[inline] - pub fn lt_s(&self, value: T) -> Vec3 { - Vec3::new(*self.i(0) < value, - *self.i(1) < value, - *self.i(2) < value) - } - - #[inline] - pub fn le_s(&self, value: T) -> Vec3 { - Vec3::new(*self.i(0) <= value, - *self.i(1) <= value, - *self.i(2) <= value) - } - - #[inline] - pub fn ge_s(&self, value: T) -> Vec3 { - Vec3::new(*self.i(0) >= value, - *self.i(1) >= value, - *self.i(2) >= value) - } - - #[inline] - pub fn gt_s(&self, value: T) -> Vec3 { - Vec3::new(*self.i(0) > value, - *self.i(1) > value, - *self.i(2) > value) - } - - #[inline] - pub fn lt_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(*self.i(0) < *other.i(0), - *self.i(1) < *other.i(1), - *self.i(2) < *other.i(2)) - } - - #[inline] - pub fn le_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(*self.i(0) <= *other.i(0), - *self.i(1) <= *other.i(1), - *self.i(2) <= *other.i(2)) - } - - #[inline] - pub fn ge_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(*self.i(0) >= *other.i(0), - *self.i(1) >= *other.i(1), - *self.i(2) >= *other.i(2)) - } - - #[inline] - pub fn gt_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(*self.i(0) > *other.i(0), - *self.i(1) > *other.i(1), - *self.i(2) > *other.i(2)) - } - - #[inline] - pub fn min_s(&self, value: T) -> Vec3 { - Vec3::new(self.i(0).min(&value), - self.i(1).min(&value), - self.i(2).min(&value)) - } - - #[inline] - pub fn max_s(&self, value: T) -> Vec3 { - Vec3::new(self.i(0).max(&value), - self.i(1).max(&value), - self.i(2).max(&value)) - } - - #[inline] - pub fn clamp_s(&self, mn: T, mx: T) -> Vec3 { - Vec3::new(self.i(0).clamp(&mn, &mx), - self.i(1).clamp(&mn, &mx), - self.i(2).clamp(&mn, &mx)) - } - - #[inline] - pub fn min_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(self.i(0).min(other.i(0)), - self.i(1).min(other.i(1)), - self.i(2).min(other.i(2))) - } - - #[inline] - pub fn max_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(self.i(0).max(other.i(0)), - self.i(1).max(other.i(1)), - self.i(2).max(other.i(2))) - } - - #[inline] - pub fn clamp_v(&self, mn: &Vec3, mx: &Vec3) -> Vec3 { - Vec3::new(self.i(0).clamp(mn.i(0), mx.i(0)), - self.i(1).clamp(mn.i(1), mx.i(1)), - self.i(2).clamp(mn.i(2), mx.i(2))) - } - - /// Returns the smallest component of the vector. - #[inline] - pub fn comp_min(&self) -> T { - self.i(0).min(self.i(1)).min(self.i(2)) - } - - /// Returns the largest component of the vector. - #[inline] - pub fn comp_max(&self) -> T { - self.i(0).max(self.i(1)).max(self.i(2)) - } -} - -impl EqVec> for Vec3 { - #[inline] - pub fn eq_s(&self, value: T) -> Vec3 { - Vec3::new(*self.i(0) == value, - *self.i(1) == value, - *self.i(2) == value) - } - - #[inline] - pub fn ne_s(&self, value: T) -> Vec3 { - Vec3::new(*self.i(0) != value, - *self.i(1) != value, - *self.i(2) != value) - } - - #[inline] - pub fn eq_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(*self.i(0) == *other.i(0), - *self.i(1) == *other.i(1), - *self.i(2) == *other.i(2)) - } - - #[inline] - pub fn ne_v(&self, other: &Vec3) -> Vec3 { - Vec3::new(*self.i(0) != *other.i(0), - *self.i(1) != *other.i(1), - *self.i(2) != *other.i(2)) - } -} - -impl BoolVec<[bool,..3]> for Vec3 { - /// Returns `true` if any of the components of the vector are equal to - /// `true`, otherwise `false`. - #[inline] - pub fn any(&self) -> bool { - *self.i(0) || *self.i(1) || *self.i(2) - } - - /// Returns `true` if _all_ of the components of the vector are equal to - /// `true`, otherwise `false`. - #[inline] - pub fn all(&self) -> bool { - *self.i(0) && *self.i(1) && *self.i(2) - } -} - -impl> Not> for Vec3 { - pub fn not(&self) -> Vec3 { - Vec3::new(!*self.i(0), - !*self.i(1), - !*self.i(2)) - } -} - -#[cfg(test)] -mod vec3_tests{ - use math::vec::*; - - static A: Vec3 = Vec3 { x: 1.0, y: 2.0, z: 3.0 }; - static B: Vec3 = Vec3 { x: 4.0, y: 5.0, z: 6.0 }; - static F1: float = 1.5; - static F2: float = 0.5; - - #[test] - fn test_swap() { - let mut mut_a = A; - - mut_a.swap(0, 2); - assert_eq!(*mut_a.i(0), *A.i(2)); - assert_eq!(*mut_a.i(2), *A.i(0)); - mut_a = A; - - mut_a.swap(1, 2); - assert_eq!(*mut_a.i(1), *A.i(2)); - assert_eq!(*mut_a.i(2), *A.i(1)); - } - - #[test] - fn test_cross() { - let mut mut_a = A; - - assert_eq!(A.cross(&B), Vec3::new::(-3.0, 6.0, -3.0)); - - mut_a.cross_self(&B); - assert_eq!(mut_a, A.cross(&B)); - } - - #[test] - fn test_num() { - let mut mut_a = A; - - assert_eq!(-A, Vec3::new::(-1.0, -2.0, -3.0)); - assert_eq!(A.neg(), Vec3::new::(-1.0, -2.0, -3.0)); - - assert_eq!(A.mul_s(F1), Vec3::new::(1.5, 3.0, 4.5)); - assert_eq!(A.div_s(F2), Vec3::new::(2.0, 4.0, 6.0)); - - assert_eq!(A.add_v(&B), Vec3::new::(5.0, 7.0, 9.0)); - assert_eq!(A.sub_v(&B), Vec3::new::(-3.0, -3.0, -3.0)); - assert_eq!(A.mul_v(&B), Vec3::new::(4.0, 10.0, 18.0)); - assert_eq!(A.div_v(&B), Vec3::new::(1.0/4.0, 2.0/5.0, 3.0/6.0)); - - mut_a.neg_self(); - assert_eq!(mut_a, -A); - mut_a = A; - - mut_a.mul_self_s(F1); - assert_eq!(mut_a, A.mul_s(F1)); - mut_a = A; - - mut_a.div_self_s(F2); - assert_eq!(mut_a, A.div_s(F2)); - mut_a = A; - - mut_a.add_self_v(&B); - assert_eq!(mut_a, A.add_v(&B)); - mut_a = A; - - mut_a.sub_self_v(&B); - assert_eq!(mut_a, A.sub_v(&B)); - mut_a = A; - - mut_a.mul_self_v(&B); - assert_eq!(mut_a, A.mul_v(&B)); - mut_a = A; - - mut_a.div_self_v(&B); - assert_eq!(mut_a, A.div_v(&B)); - } - - #[test] - fn test_comp_add() { - assert_eq!(A.comp_add(), 6.0); - assert_eq!(B.comp_add(), 15.0); - } - - #[test] - fn test_comp_mul() { - assert_eq!(A.comp_mul(), 6.0); - assert_eq!(B.comp_mul(), 120.0); - } - - #[test] - fn test_approx_eq() { - assert!(!Vec3::new::(0.000001, 0.000001, 0.000001).approx_eq(&Vec3::new::(0.0, 0.0, 0.0))); - assert!(Vec3::new::(0.0000001, 0.0000001, 0.0000001).approx_eq(&Vec3::new::(0.0, 0.0, 0.0))); - } - - - #[test] - fn test_magnitude() { - let a = Vec3::new(2.0, 3.0, 6.0); // (2, 3, 6, 7) Pythagorean quadruple - let b = Vec3::new(1.0, 4.0, 8.0); // (1, 4, 8, 9) Pythagorean quadruple - - assert_eq!(a.magnitude(), 7.0); - assert_eq!(a.magnitude2(), 7.0 * 7.0); - - assert_eq!(b.magnitude(), 9.0); - assert_eq!(b.magnitude2(), 9.0 * 9.0); - } - - #[test] - fn test_angle() { - assert!(Vec3::new::(1.0, 0.0, 1.0).angle(&Vec3::new::(1.0, 1.0, 0.0)).approx_eq(&Real::frac_pi_3())); - assert!(Vec3::new::(10.0, 0.0, 10.0).angle(&Vec3::new::(5.0, 5.0, 0.0)).approx_eq(&Real::frac_pi_3())); - assert!(Vec3::new::(-1.0, 0.0, -1.0).angle(&Vec3::new::(1.0, -1.0, 0.0)).approx_eq(&(2.0 * Real::frac_pi_3()))); - } - - #[test] - fn test_normalize() { - assert!(Vec3::new::(2.0, 3.0, 6.0).normalize().approx_eq(&Vec3::new::(2.0/7.0, 3.0/7.0, 6.0/7.0))); - // TODO: test normalize_to, normalize_self, and normalize_self_to - } - - #[test] - fn test_lerp() { - let c = Vec3::new::(-2.0, -1.0, 1.0); - let d = Vec3::new::( 1.0, 0.0, 0.5); - - assert_eq!(c.lerp(&d, 0.75), Vec3::new::(0.250, -0.250, 0.625)); - - let mut mut_c = c; - mut_c.lerp_self(&d, 0.75); - assert_eq!(mut_c, c.lerp(&d, 0.75)); - } - - #[test] - fn test_comp_min() { - assert_eq!(A.comp_min(), 1.0); - assert_eq!(B.comp_min(), 4.0); - } - - #[test] - fn test_comp_max() { - assert_eq!(A.comp_max(), 3.0); - assert_eq!(B.comp_max(), 6.0); - } - - #[test] - fn test_boolean() { - let tft = Vec3::new(true, false, true); - let fff = Vec3::new(false, false, false); - let ttt = Vec3::new(true, true, true); - - assert_eq!(tft.any(), true); - assert_eq!(tft.all(), false); - assert_eq!(!tft, Vec3::new(false, true, false)); - - assert_eq!(fff.any(), false); - assert_eq!(fff.all(), false); - assert_eq!(!fff, Vec3::new(true, true, true)); - - assert_eq!(ttt.any(), true); - assert_eq!(ttt.all(), true); - assert_eq!(!ttt, Vec3::new(false, false, false)); - } -} - -#[deriving(Clone, Eq)] -pub struct Vec4 { x: T, y: T, z: T, w: T } - -// GLSL-style type aliases -pub type vec4 = Vec4; -pub type dvec4 = Vec4; -pub type bvec4 = Vec4; -pub type ivec4 = Vec4; -pub type uvec4 = Vec4; - -// Rust-style type aliases -pub type Vec4f = Vec4; -pub type Vec4f32 = Vec4; -pub type Vec4f64 = Vec4; -pub type Vec4i = Vec4; -pub type Vec4i8 = Vec4; -pub type Vec4i16 = Vec4; -pub type Vec4i32 = Vec4; -pub type Vec4i64 = Vec4; -pub type Vec4u = Vec4; -pub type Vec4u8 = Vec4; -pub type Vec4u16 = Vec4; -pub type Vec4u32 = Vec4; -pub type Vec4u64 = Vec4; -pub type Vec4b = Vec4; - -pub trait ToVec4 { - pub fn to_vec4(&self) -> Vec4; -} - -pub trait AsVec4 { - pub fn as_vec4<'a>(&'a self) -> &'a Vec4; - pub fn as_mut_vec4<'a>(&'a mut self) -> &'a mut Vec4; - pub fn with_vec4<'a>(&'a self, f: &fn(&'a Vec4) -> Vec4) -> Self; -} - -impl_dimensioned!(Vec4, T, 4) -impl_swap_components!(Vec4) -impl_approx!(Vec4 { x, y, z, w }) - -impl Vec4 { - /// Construct a new vector from the supplied components. - #[inline] - pub fn new(x: T, y: T, z: T, w: T) -> Vec4 { - Vec4 { x: x, y: y, z: z, w: w } - } -} - -impl Vec4 { - /// Construct a new vector with each component set to `value`. - #[inline] - pub fn from_value(value: T) -> Vec4 { - Vec4::new(value.clone(), - value.clone(), - value.clone(), - value.clone()) - } -} - -/// Constants for four-dimensional vectors. -impl Vec4 { - /// Returns a four-dimensional vector with each component set to `1`. - #[inline] - pub fn identity() -> Vec4 { - Vec4::new(one!(T), one!(T), one!(T), one!(T)) - } - - /// Returns a four-dimensional vector with each component set to `0`. - #[inline] - pub fn zero() -> Vec4 { - Vec4::new(zero!(T), zero!(T), zero!(T), zero!(T)) - } - - /// Returns a zeroed four-dimensional vector with the `x` component set to `1`. - #[inline] - pub fn unit_x() -> Vec4 { - Vec4::new(one!(T), zero!(T), zero!(T), zero!(T)) - } - - /// Returns a zeroed four-dimensional vector with the `y` component set to `1`. - #[inline] - pub fn unit_y() -> Vec4 { - Vec4::new(zero!(T), one!(T), zero!(T), zero!(T)) - } - - /// Returns a zeroed four-dimensional vector with the `z` component set to `1`. - #[inline] - pub fn unit_z() -> Vec4 { - Vec4::new(zero!(T), zero!(T), one!(T), zero!(T)) - } - - /// Returns a zeroed four-dimensional vector with the `w` component set to `1`. - #[inline] - pub fn unit_w() -> Vec4 { - Vec4::new(zero!(T), zero!(T), zero!(T), one!(T)) - } -} - -impl Vec for Vec4 {} - -impl NumVec for Vec4 { - /// Returns a new vector with `value` added to each component. - #[inline] - pub fn add_s(&self, value: T) -> Vec4 { - Vec4::new(*self.i(0) + value, - *self.i(1) + value, - *self.i(2) + value, - *self.i(3) + value) - } - - /// Returns a new vector with `value` subtracted from each component. - #[inline] - pub fn sub_s(&self, value: T) -> Vec4 { - Vec4::new(*self.i(0) - value, - *self.i(1) - value, - *self.i(2) - value, - *self.i(3) - value) - } - - /// Returns the scalar multiplication of the vector with `value`. - #[inline] - pub fn mul_s(&self, value: T) -> Vec4 { - Vec4::new(*self.i(0) * value, - *self.i(1) * value, - *self.i(2) * value, - *self.i(3) * value) - } - - /// Returns a new vector with each component divided by `value`. - #[inline] - pub fn div_s(&self, value: T) -> Vec4 { - Vec4::new(*self.i(0) / value, - *self.i(1) / value, - *self.i(2) / value, - *self.i(3) / value) - } - - /// Returns the remainder of each component divided by `value`. - #[inline] - pub fn rem_s(&self, value: T) -> Vec4 { - Vec4::new(*self.i(0) % value, - *self.i(1) % value, - *self.i(2) % value, - *self.i(3) % value) - } - - /// Returns the sum of the two vectors. - #[inline] - pub fn add_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(*self.i(0) + *other.i(0), - *self.i(1) + *other.i(1), - *self.i(2) + *other.i(2), - *self.i(3) + *other.i(3)) - } - - /// Ruturns the result of subtrating `other` from the vector. - #[inline] - pub fn sub_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(*self.i(0) - *other.i(0), - *self.i(1) - *other.i(1), - *self.i(2) - *other.i(2), - *self.i(3) - *other.i(3)) - } - - /// Returns the component-wise product of the vector and `other`. - #[inline] - pub fn mul_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(*self.i(0) * *other.i(0), - *self.i(1) * *other.i(1), - *self.i(2) * *other.i(2), - *self.i(3) * *other.i(3)) - } - - /// Returns the component-wise quotient of the vectors. - #[inline] - pub fn div_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(*self.i(0) / *other.i(0), - *self.i(1) / *other.i(1), - *self.i(2) / *other.i(2), - *self.i(3) / *other.i(3)) - } - - /// Returns the component-wise remainder of the vector divided by `other`. - #[inline] - pub fn rem_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(*self.i(0) % *other.i(0), - *self.i(1) % *other.i(1), - *self.i(2) % *other.i(2), - *self.i(3) % *other.i(3)) - } - - /// Negates each component of the vector. - #[inline] - pub fn neg_self(&mut self) { - *self.mut_i(0) = -*self.i(0); - *self.mut_i(1) = -*self.i(1); - *self.mut_i(2) = -*self.i(2); - *self.mut_i(3) = -*self.i(3); - } - - /// Adds `value` to each component of the vector. - #[inline] - pub fn add_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) + value; - *self.mut_i(1) = *self.i(1) + value; - *self.mut_i(2) = *self.i(2) + value; - *self.mut_i(3) = *self.i(3) + value; - } - - /// Subtracts `value` from each component of the vector. - #[inline] - pub fn sub_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) - value; - *self.mut_i(1) = *self.i(1) - value; - *self.mut_i(2) = *self.i(2) - value; - *self.mut_i(3) = *self.i(3) - value; - } - - #[inline] - pub fn mul_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) * value; - *self.mut_i(1) = *self.i(1) * value; - *self.mut_i(2) = *self.i(2) * value; - *self.mut_i(3) = *self.i(3) * value; - } - - #[inline] - pub fn div_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) / value; - *self.mut_i(1) = *self.i(1) / value; - *self.mut_i(2) = *self.i(2) / value; - *self.mut_i(3) = *self.i(3) / value; - } - - #[inline] - pub fn rem_self_s(&mut self, value: T) { - *self.mut_i(0) = *self.i(0) % value; - *self.mut_i(1) = *self.i(1) % value; - *self.mut_i(2) = *self.i(2) % value; - *self.mut_i(3) = *self.i(3) % value; - } - - #[inline] - pub fn add_self_v(&mut self, other: &Vec4) { - *self.mut_i(0) = *self.i(0) + *other.i(0); - *self.mut_i(1) = *self.i(1) + *other.i(1); - *self.mut_i(2) = *self.i(2) + *other.i(2); - *self.mut_i(3) = *self.i(3) + *other.i(3); - } - - #[inline] - pub fn sub_self_v(&mut self, other: &Vec4) { - *self.mut_i(0) = *self.i(0) - *other.i(0); - *self.mut_i(1) = *self.i(1) - *other.i(1); - *self.mut_i(2) = *self.i(2) - *other.i(2); - *self.mut_i(3) = *self.i(3) - *other.i(3); - } - - #[inline] - pub fn mul_self_v(&mut self, other: &Vec4) { - *self.mut_i(0) = *self.i(0) * *other.i(0); - *self.mut_i(1) = *self.i(1) * *other.i(1); - *self.mut_i(2) = *self.i(2) * *other.i(2); - *self.mut_i(3) = *self.i(3) * *other.i(3); - } - - #[inline] - pub fn div_self_v(&mut self, other: &Vec4) { - *self.mut_i(0) = *self.i(0) / *other.i(0); - *self.mut_i(1) = *self.i(1) / *other.i(1); - *self.mut_i(2) = *self.i(2) / *other.i(2); - *self.mut_i(3) = *self.i(3) / *other.i(3); - } - - #[inline] - pub fn rem_self_v(&mut self, other: &Vec4) { - *self.mut_i(0) = *self.i(0) % *other.i(0); - *self.mut_i(1) = *self.i(1) % *other.i(1); - *self.mut_i(2) = *self.i(2) % *other.i(2); - *self.mut_i(3) = *self.i(3) % *other.i(3); - } - - /// Returns the dot product of the vector and `other`. - #[inline] - pub fn dot(&self, other: &Vec4) -> T { - *self.i(0) * *other.i(0) + - *self.i(1) * *other.i(1) + - *self.i(2) * *other.i(2) + - *self.i(3) * *other.i(3) - } - - /// Returns the sum of the vector's components. - #[inline] - pub fn comp_add(&self) -> T { - *self.i(0) + *self.i(1) + *self.i(2) + *self.i(3) - } - - /// Returns the product of the vector's components. - #[inline] - pub fn comp_mul(&self) -> T { - *self.i(0) * *self.i(1) * *self.i(2) * *self.i(3) - } -} - -impl Neg> for Vec4 { - /// Returns the vector with each component negated. - #[inline] - pub fn neg(&self) -> Vec4 { - Vec4::new(-*self.i(0), - -*self.i(1), - -*self.i(2), - -*self.i(3)) - } -} - -impl FloatVec for Vec4 { - /// Returns the squared magnitude of the vector. This does not perform a - /// square root operation like in the `magnitude` method and can therefore - /// be more efficient for comparing the magnitudes of two vectors. - #[inline] - pub fn magnitude2(&self) -> T { - self.dot(self) - } - - /// Returns the magnitude (length) of the vector. - #[inline] - pub fn magnitude(&self) -> T { - self.magnitude2().sqrt() - } - - /// Returns the angle between the vector and `other`. - #[inline] - pub fn angle(&self, other: &Vec4) -> T { - (self.dot(other) / (self.magnitude() * other.magnitude())).acos() - } - - /// Returns the result of normalizing the vector to a magnitude of `1`. - #[inline] - pub fn normalize(&self) -> Vec4 { - self.normalize_to(one!(T)) - } - - /// Returns the result of normalizing the vector to `magnitude`. - #[inline] - pub fn normalize_to(&self, magnitude: T) -> Vec4 { - self.mul_s(magnitude / self.magnitude()) - } - - /// Returns the result of linarly interpolating the magnitude of the vector - /// to the magnitude of `other` by the specified amount. - #[inline] - pub fn lerp(&self, other: &Vec4, amount: T) -> Vec4 { - self.add_v(&other.sub_v(self).mul_s(amount)) - } - - /// Normalises the vector to a magnitude of `1`. - #[inline] - pub fn normalize_self(&mut self) { - let rlen = self.magnitude().recip(); - self.mul_self_s(rlen); - } - - /// Normalizes the vector to `magnitude`. - #[inline] - pub fn normalize_self_to(&mut self, magnitude: T) { - let n = magnitude / self.magnitude(); - self.mul_self_s(n); - } - - /// Linearly interpolates the magnitude of the vector to the magnitude of - /// `other` by the specified amount. - pub fn lerp_self(&mut self, other: &Vec4, amount: T) { - let v = other.sub_v(self).mul_s(amount); - self.add_self_v(&v); - } -} - -impl OrdVec> for Vec4 { - #[inline] - pub fn lt_s(&self, value: T) -> Vec4 { - Vec4::new(*self.i(0) < value, - *self.i(1) < value, - *self.i(2) < value, - *self.i(3) < value) - } - - #[inline] - pub fn le_s(&self, value: T) -> Vec4 { - Vec4::new(*self.i(0) <= value, - *self.i(1) <= value, - *self.i(2) <= value, - *self.i(3) <= value) - } - - #[inline] - pub fn ge_s(&self, value: T) -> Vec4 { - Vec4::new(*self.i(0) >= value, - *self.i(1) >= value, - *self.i(2) >= value, - *self.i(3) >= value) - } - - #[inline] - pub fn gt_s(&self, value: T) -> Vec4 { - Vec4::new(*self.i(0) > value, - *self.i(1) > value, - *self.i(2) > value, - *self.i(3) > value) - } - - #[inline] - pub fn lt_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(*self.i(0) < *other.i(0), - *self.i(1) < *other.i(1), - *self.i(2) < *other.i(2), - *self.i(3) < *other.i(3)) - } - - #[inline] - pub fn le_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(*self.i(0) <= *other.i(0), - *self.i(1) <= *other.i(1), - *self.i(2) <= *other.i(2), - *self.i(3) <= *other.i(3)) - } - - #[inline] - pub fn ge_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(*self.i(0) >= *other.i(0), - *self.i(1) >= *other.i(1), - *self.i(2) >= *other.i(2), - *self.i(3) >= *other.i(3)) - } - - #[inline] - pub fn gt_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(*self.i(0) > *other.i(0), - *self.i(1) > *other.i(1), - *self.i(2) > *other.i(2), - *self.i(3) > *other.i(3)) - } - - #[inline] - pub fn min_s(&self, value: T) -> Vec4 { - Vec4::new(self.i(0).min(&value), - self.i(1).min(&value), - self.i(2).min(&value), - self.i(3).min(&value)) - } - - #[inline] - pub fn max_s(&self, value: T) -> Vec4 { - Vec4::new(self.i(0).max(&value), - self.i(1).max(&value), - self.i(2).max(&value), - self.i(3).max(&value)) - } - - #[inline] - pub fn clamp_s(&self, mn: T, mx: T) -> Vec4 { - Vec4::new(self.i(0).clamp(&mn, &mx), - self.i(1).clamp(&mn, &mx), - self.i(2).clamp(&mn, &mx), - self.i(3).clamp(&mn, &mx)) - } - - #[inline] - pub fn min_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(self.i(0).min(other.i(0)), - self.i(1).min(other.i(1)), - self.i(2).min(other.i(2)), - self.i(3).min(other.i(3))) - } - - #[inline] - pub fn max_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(self.i(0).max(other.i(0)), - self.i(1).max(other.i(1)), - self.i(2).max(other.i(2)), - self.i(3).max(other.i(3))) - } - - #[inline] - pub fn clamp_v(&self, mn: &Vec4, mx: &Vec4) -> Vec4 { - Vec4::new(self.i(0).clamp(mn.i(0), mx.i(0)), - self.i(1).clamp(mn.i(1), mx.i(1)), - self.i(2).clamp(mn.i(2), mx.i(2)), - self.i(3).clamp(mn.i(3), mx.i(3))) - } - - /// Returns the smallest component of the vector. - #[inline] - pub fn comp_min(&self) -> T { - self.i(0).min(self.i(1)).min(self.i(2)).min(self.i(3)) - } - - /// Returns the largest component of the vector. - #[inline] - pub fn comp_max(&self) -> T { - self.i(0).max(self.i(1)).max(self.i(2)).max(self.i(3)) - } -} - -impl EqVec> for Vec4 { - #[inline] - pub fn eq_s(&self, value: T) -> Vec4 { - Vec4::new(*self.i(0) == value, - *self.i(1) == value, - *self.i(2) == value, - *self.i(3) == value) - } - - #[inline] - pub fn ne_s(&self, value: T) -> Vec4 { - Vec4::new(*self.i(0) != value, - *self.i(1) != value, - *self.i(2) != value, - *self.i(3) != value) - } - - #[inline] - pub fn eq_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(*self.i(0) == *other.i(0), - *self.i(1) == *other.i(1), - *self.i(2) == *other.i(2), - *self.i(3) == *other.i(3)) - } - - #[inline] - pub fn ne_v(&self, other: &Vec4) -> Vec4 { - Vec4::new(*self.i(0) != *other.i(0), - *self.i(1) != *other.i(1), - *self.i(2) != *other.i(2), - *self.i(3) != *other.i(3)) - } -} - -impl BoolVec<[bool,..4]> for Vec4 { - /// Returns `true` if any of the components of the vector are equal to - /// `true`, otherwise `false`. - #[inline] - pub fn any(&self) -> bool { - *self.i(0) || *self.i(1) || *self.i(2) || *self.i(3) - } - - /// Returns `true` if _all_ of the components of the vector are equal to - /// `true`, otherwise `false`. - #[inline] - pub fn all(&self) -> bool { - *self.i(0) && *self.i(1) && *self.i(2) && *self.i(3) - } -} - -impl> Not> for Vec4 { - pub fn not(&self) -> Vec4 { - Vec4::new(!*self.i(0), - !*self.i(1), - !*self.i(2), - !*self.i(3)) - } -} - -#[cfg(test)] -mod vec4_tests { - use math::vec::*; - - static A: Vec4 = Vec4 { x: 1.0, y: 2.0, z: 3.0, w: 4.0 }; - static B: Vec4 = Vec4 { x: 5.0, y: 6.0, z: 7.0, w: 8.0 }; - static F1: float = 1.5; - static F2: float = 0.5; - - #[test] - fn test_swap() { - let mut mut_a = A; - - mut_a.swap(0, 3); - assert_eq!(*mut_a.i(0), *A.i(3)); - assert_eq!(*mut_a.i(3), *A.i(0)); - mut_a = A; - - mut_a.swap(1, 2); - assert_eq!(*mut_a.i(1), *A.i(2)); - assert_eq!(*mut_a.i(2), *A.i(1)); - } - - #[test] - fn test_num() { - let mut mut_a = A; - - assert_eq!(-A, Vec4::new::(-1.0, -2.0, -3.0, -4.0)); - assert_eq!(A.neg(), Vec4::new::(-1.0, -2.0, -3.0, -4.0)); - - assert_eq!(A.mul_s(F1), Vec4::new::(1.5, 3.0, 4.5, 6.0)); - assert_eq!(A.div_s(F2), Vec4::new::(2.0, 4.0, 6.0, 8.0)); - - assert_eq!(A.add_v(&B), Vec4::new::(6.0, 8.0, 10.0, 12.0)); - assert_eq!(A.sub_v(&B), Vec4::new::(-4.0, -4.0, -4.0, -4.0)); - assert_eq!(A.mul_v(&B), Vec4::new::(5.0, 12.0, 21.0, 32.0)); - assert_eq!(A.div_v(&B), Vec4::new::(1.0/5.0, 2.0/6.0, 3.0/7.0, 4.0/8.0)); - - assert_eq!(A.dot(&B), 70.0); - - mut_a.neg_self(); - assert_eq!(mut_a, -A); - mut_a = A; - - mut_a.mul_self_s(F1); - assert_eq!(mut_a, A.mul_s(F1)); - mut_a = A; - - mut_a.div_self_s(F2); - assert_eq!(mut_a, A.div_s(F2)); - mut_a = A; - - mut_a.add_self_v(&B); - assert_eq!(mut_a, A.add_v(&B)); - mut_a = A; - - mut_a.sub_self_v(&B); - assert_eq!(mut_a, A.sub_v(&B)); - mut_a = A; - - mut_a.mul_self_v(&B); - assert_eq!(mut_a, A.mul_v(&B)); - mut_a = A; - - mut_a.div_self_v(&B); - assert_eq!(mut_a, A.div_v(&B)); - } - - #[test] - fn test_comp_add() { - assert_eq!(A.comp_add(), 10.0); - assert_eq!(B.comp_add(), 26.0); - } - - #[test] - fn test_comp_mul() { - assert_eq!(A.comp_mul(), 24.0); - assert_eq!(B.comp_mul(), 1680.0); - } - - #[test] - fn test_approx_eq() { - assert!(!Vec4::new::(0.000001, 0.000001, 0.000001, 0.000001).approx_eq(&Vec4::new::(0.0, 0.0, 0.0, 0.0))); - assert!(Vec4::new::(0.0000001, 0.0000001, 0.0000001, 0.0000001).approx_eq(&Vec4::new::(0.0, 0.0, 0.0, 0.0))); - } - - #[test] - fn test_magnitude() { - let a = Vec4::new(1.0, 2.0, 4.0, 10.0); // (1, 2, 4, 10, 11) Pythagorean quintuple - let b = Vec4::new(1.0, 2.0, 8.0, 10.0); // (1, 2, 8, 10, 13) Pythagorean quintuple - - assert_eq!(a.magnitude(), 11.0); - assert_eq!(a.magnitude2(), 11.0 * 11.0); - - assert_eq!(b.magnitude(), 13.0); - assert_eq!(b.magnitude2(), 13.0 * 13.0); - } - - #[test] - fn test_angle() { - assert!(Vec4::new::(1.0, 0.0, 1.0, 0.0).angle(&Vec4::new::(0.0, 1.0, 0.0, 1.0)).approx_eq(&Real::frac_pi_2())); - assert!(Vec4::new::(10.0, 0.0, 10.0, 0.0).angle(&Vec4::new::(0.0, 5.0, 0.0, 5.0)).approx_eq(&Real::frac_pi_2())); - assert!(Vec4::new::(-1.0, 0.0, -1.0, 0.0).angle(&Vec4::new::(0.0, 1.0, 0.0, 1.0)).approx_eq(&Real::frac_pi_2())); - } - - #[test] - fn test_normalize() { - assert!(Vec4::new::(1.0, 2.0, 4.0, 10.0).normalize().approx_eq(&Vec4::new::(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0))); - // TODO: test normalize_to, normalize_self, and normalize_self_to - } - - #[test] - fn test_lerp() { - let c = Vec4::new::(-2.0, -1.0, 1.0, 2.0); - let d = Vec4::new::( 1.0, 0.0, 0.5, 1.0); - - assert_eq!(c.lerp(&d, 0.75), Vec4::new::(0.250, -0.250, 0.625, 1.250)); - - let mut mut_c = c; - mut_c.lerp_self(&d, 0.75); - assert_eq!(mut_c, c.lerp(&d, 0.75)); - } - - #[test] - fn test_comp_min() { - assert_eq!(A.comp_min(), 1.0); - assert_eq!(B.comp_min(), 5.0); - } - - #[test] - fn test_comp_max() { - assert_eq!(A.comp_max(), 4.0); - assert_eq!(B.comp_max(), 8.0); - } - - #[test] - fn test_boolean() { - let tftf = Vec4::new(true, false, true, false); - let ffff = Vec4::new(false, false, false, false); - let tttt = Vec4::new(true, true, true, true); - - assert_eq!(tftf.any(), true); - assert_eq!(tftf.all(), false); - assert_eq!(!tftf, Vec4::new(false, true, false, true)); - - assert_eq!(ffff.any(), false); - assert_eq!(ffff.all(), false); - assert_eq!(!ffff, Vec4::new(true, true, true, true)); - - assert_eq!(tttt.any(), true); - assert_eq!(tttt.all(), true); - assert_eq!(!tttt, Vec4::new(false, false, false, false)); - } -} diff --git a/src-old/space/bsp.rs b/src-old/space/bsp.rs deleted file mode 100644 index 3c27ef9..0000000 --- a/src-old/space/bsp.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Lmath 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. - -pub struct BSP; diff --git a/src-old/space/octree.rs b/src-old/space/octree.rs deleted file mode 100644 index 0aabc95..0000000 --- a/src-old/space/octree.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 The Lmath 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. - -// http://gameprogrammingpatterns.com/spatial-partition.html - -use bounds::AABB3; - -pub struct Octree { - bounds: AABB3, - octants: [Option<~Octree>, ..8], -} diff --git a/src-old/space/quadtree.rs b/src-old/space/quadtree.rs deleted file mode 100644 index 448bb69..0000000 --- a/src-old/space/quadtree.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 The Lmath 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. - -// http://gameprogrammingpatterns.com/spatial-partition.html -// http://github.com/mozilla/servo/blob/master/src/components/main/compositing/quadtree.rs - -pub struct Quadtree; diff --git a/src-old/space/space.rs b/src-old/space/space.rs deleted file mode 100644 index 17d80ab..0000000 --- a/src-old/space/space.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Various data structures for space partitioning and visibility determination - -pub use self::bsp::BSP; -pub use self::octree::Octree; -pub use self::quadtree::Quadtree; - -pub mod bsp; -pub mod octree; -pub mod quadtree; diff --git a/src-old/transform/projection.rs b/src-old/transform/projection.rs deleted file mode 100644 index 439dde1..0000000 --- a/src-old/transform/projection.rs +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright 2013 The Lmath 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 bounds::Frustum; -use math::Mat4; -use math::Plane3; - -/// -/// Create a perspective projection matrix -/// -/// Note: the fovy parameter should be specified in degrees. -/// -/// This is the equivalent of the gluPerspective function, the algorithm of which -/// can be found [here](http://www.opengl.org/wiki/GluPerspective_code). -/// -pub fn perspective(fovy: T, aspectRatio: T, near: T, far: T) -> Mat4 { - let ymax = near * (fovy / two!(T)).to_radians().tan(); - let xmax = ymax * aspectRatio; - - frustum(-xmax, xmax, -ymax, ymax, near, far) -} - -/// -/// Define a view frustrum -/// -/// This is the equivalent of the now deprecated [glFrustrum] -/// (http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) function. -/// -pub fn frustum(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { - let c0r0 = (two!(T) * near) / (right - left); - let c0r1 = zero!(T); - let c0r2 = zero!(T); - let c0r3 = zero!(T); - - let c1r0 = zero!(T); - let c1r1 = (two!(T) * near) / (top - bottom); - let c1r2 = zero!(T); - let c1r3 = zero!(T); - - let c2r0 = (right + left) / (right - left); - let c2r1 = (top + bottom) / (top - bottom); - let c2r2 = -(far + near) / (far - near); - let c2r3 = -one!(T); - - let c3r0 = zero!(T); - let c3r1 = zero!(T); - let c3r2 = -(two!(T) * far * near) / (far - near); - let c3r3 = zero!(T); - - Mat4::new(c0r0, c0r1, c0r2, c0r3, - c1r0, c1r1, c1r2, c1r3, - c2r0, c2r1, c2r2, c2r3, - c3r0, c3r1, c3r2, c3r3) -} - -/// -/// Create an orthographic projection matrix -/// -/// This is the equivalent of the now deprecated [glOrtho] -/// (http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) function. -/// -pub fn ortho(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { - let c0r0 = two!(T) / (right - left); - let c0r1 = zero!(T); - let c0r2 = zero!(T); - let c0r3 = zero!(T); - - let c1r0 = zero!(T); - let c1r1 = two!(T) / (top - bottom); - let c1r2 = zero!(T); - let c1r3 = zero!(T); - - let c2r0 = zero!(T); - let c2r1 = zero!(T); - let c2r2 = -two!(T) / (far - near); - let c2r3 = zero!(T); - - let c3r0 = -(right + left) / (right - left); - let c3r1 = -(top + bottom) / (top - bottom); - let c3r2 = -(far + near) / (far - near); - let c3r3 = one!(T); - - Mat4::new(c0r0, c0r1, c0r2, c0r3, - c1r0, c1r1, c1r2, c1r3, - c2r0, c2r1, c2r2, c2r3, - c3r0, c3r1, c3r2, c3r3) -} - -pub trait Projection { - pub fn if_valid(&self, f: &fn() -> U) -> Result; - pub fn to_mat4(&self) -> Result, ~str>; - pub fn to_frustum(&self) -> Result, ~str>; -} - -/// A symmetrical perspective projection based on a field-of-view angle -#[deriving(Clone, Eq)] -pub struct PerspectiveFOV { - fovy: T, //radians - aspect: T, - near: T, - far: T, -} - -impl PerspectiveFOV { - pub fn to_perspective(&self) -> Result, ~str> { - do self.if_valid { - let angle = self.fovy / two!(T); - let ymax = self.near * angle.tan(); - let xmax = ymax * self.aspect; - - Perspective { - left: -xmax, - right: xmax, - bottom: -ymax, - top: ymax, - near: self.near.clone(), - far: self.far.clone(), - } - } - } -} - -impl Projection for PerspectiveFOV { - pub fn if_valid(&self, f: &fn() -> U) -> Result { - let frac_pi_2: T = Real::frac_pi_2(); - cond! ( - (self.fovy < zero!(T)) { Err(fmt!("The vertical field of view cannot be below zero, found: %?", self.fovy)) } - (self.fovy > frac_pi_2) { Err(fmt!("The vertical field of view cannot be greater than a half turn, found: %?", self.fovy)) } - (self.aspect < zero!(T)) { Err(fmt!("The aspect ratio cannot be below zero, found: %?", self.aspect)) } - (self.near < zero!(T)) { Err(fmt!("The near plane distance cannot be below zero, found: %?", self.near)) } - (self.far < zero!(T)) { Err(fmt!("The far plane distance cannot be below zero, found: %?", self.far)) } - (self.far < self.near) { Err(fmt!("The far plane cannot be closer than the near plane, found: far: %?, near: %?", self.far, self.near)) } - _ { Ok(f()) } - ) - } - - pub fn to_mat4(&self) -> Result, ~str> { - do self.to_perspective().chain |proj| { proj.to_mat4() } - } - - pub fn to_frustum(&self) -> Result, ~str> { - do self.to_perspective().chain |proj| { proj.to_frustum() } - } -} - -/// A perspective projection with arbitrary left/right/bottom/top distances -#[deriving(Clone, Eq)] -pub struct Perspective { - left: T, - right: T, - bottom: T, - top: T, - near: T, - far: T, -} - -impl Projection for Perspective { - pub fn if_valid(&self, f: &fn() -> U) -> Result { - cond! ( - (self.left > self.right) { Err(fmt!("`left` cannot be greater than `right`, found: left: %? right: %?", self.left, self.right)) } - (self.bottom > self.top) { Err(fmt!("`bottom` cannot be greater than `top`, found: bottom: %? top: %?", self.bottom, self.top)) } - (self.near > self.far) { Err(fmt!("`near` cannot be greater than `far`, found: near: %? far: %?", self.near, self.far)) } - _ { Ok(f()) } - ) - } - - pub fn to_mat4(&self) -> Result, ~str> { - do self.if_valid { - let c0r0 = (two!(T) * self.near) / (self.right - self.left); - let c0r1 = zero!(T); - let c0r2 = zero!(T); - let c0r3 = zero!(T); - - let c1r0 = zero!(T); - let c1r1 = (two!(T) * self.near) / (self.top - self.bottom); - let c1r2 = zero!(T); - let c1r3 = zero!(T); - - let c2r0 = (self.right + self.left) / (self.right - self.left); - let c2r1 = (self.top + self.bottom) / (self.top - self.bottom); - let c2r2 = -(self.far + self.near) / (self.far - self.near); - let c2r3 = -one!(T); - - let c3r0 = zero!(T); - let c3r1 = zero!(T); - let c3r2 = -(two!(T) * self.far * self.near) / (self.far - self.near); - let c3r3 = zero!(T); - - Mat4::new(c0r0, c0r1, c0r2, c0r3, - c1r0, c1r1, c1r2, c1r3, - c2r0, c2r1, c2r2, c2r3, - c3r0, c3r1, c3r2, c3r3) - } - } - - pub fn to_frustum(&self) -> Result, ~str> { - do self.if_valid { - /* - - <---- l --->|<--- r -----> - +-----------+-----------+ ^ - \ | / | - \ | / | - \ + | + / | - \ / Nl | Nr \ / | - \/ | \/ | - left \ | / right f - plane \ | / plane | - ⟨Nl,Dl⟩ \ | / ⟨Nr,Dr⟩ | - \θl|θr/ | - \ | / | - \|/ | - + v - - θl = tan⁻¹(l/f) - - + - / Nl - / - / - \ | / - \θl| / - \ | / - \|/ θl - +- - - - - \ - - Nl = ⟨cos(θl), 0, sin(θl)⟩ - - left plane = ⟨Nl, 0⟩ - = ⟨cos(θl), 0, sin(θl), 0⟩ - - */ - - let theta_l = (self.left / self.far).atan(); - let theta_r = (self.right / self.far).atan(); - let theta_b = (self.bottom / self.far).atan(); - let theta_t = (self.top / self.far).atan(); - - Frustum { - left: Plane3::from_abcd(theta_l.cos(), zero!(T), theta_l.sin(), zero!(T)), - right: Plane3::from_abcd(theta_r.cos(), zero!(T), theta_r.sin(), zero!(T)), - bottom: Plane3::from_abcd(zero!(T), theta_b.cos(), theta_b.sin(), zero!(T)), - top: Plane3::from_abcd(zero!(T), theta_t.cos(), theta_t.sin(), zero!(T)), - near: Plane3::from_abcd(zero!(T), zero!(T), -one!(T), -self.near.clone()), - far: Plane3::from_abcd(zero!(T), zero!(T), one!(T), self.far.clone()), - } - } - } -} - -/// An orthographic projection with arbitrary left/right/bottom/top distances -#[deriving(Clone, Eq)] -pub struct Ortho { - left: T, - right: T, - bottom: T, - top: T, - near: T, - far: T, -} - -impl Projection for Ortho { - pub fn if_valid(&self, f: &fn() -> U) -> Result { - cond! ( - (self.left > self.right) { Err(fmt!("`left` cannot be greater than `right`, found: left: %? right: %?", self.left, self.right)) } - (self.bottom > self.top) { Err(fmt!("`bottom` cannot be greater than `top`, found: bottom: %? top: %?", self.bottom, self.top)) } - (self.near > self.far) { Err(fmt!("`near` cannot be greater than `far`, found: near: %? far: %?", self.near, self.far)) } - _ { Ok(f()) } - ) - } - - pub fn to_mat4(&self) -> Result, ~str> { - do self.if_valid { - let c0r0 = two!(T) / (self.right - self.left); - let c0r1 = zero!(T); - let c0r2 = zero!(T); - let c0r3 = zero!(T); - - let c1r0 = zero!(T); - let c1r1 = two!(T) / (self.top - self.bottom); - let c1r2 = zero!(T); - let c1r3 = zero!(T); - - let c2r0 = zero!(T); - let c2r1 = zero!(T); - let c2r2 = -two!(T) / (self.far - self.near); - let c2r3 = -one!(T); - - let c3r0 = -(self.right + self.left) / (self.right - self.left); - let c3r1 = -(self.top + self.bottom) / (self.top - self.bottom); - let c3r2 = -(self.far + self.near) / (self.far - self.near); - let c3r3 = one!(T); - - Mat4::new(c0r0, c0r1, c0r2, c0r3, - c1r0, c1r1, c1r2, c1r3, - c2r0, c2r1, c2r2, c2r3, - c3r0, c3r1, c3r2, c3r3) - } - } - - pub fn to_frustum(&self) -> Result, ~str> { - do self.if_valid { - Frustum { - left: Plane3::from_abcd(one!(T), zero!(T), zero!(T), self.left.clone()), - right: Plane3::from_abcd(-one!(T), zero!(T), zero!(T), self.right.clone()), - bottom: Plane3::from_abcd(zero!(T), one!(T), zero!(T), self.bottom.clone()), - top: Plane3::from_abcd(zero!(T), -one!(T), zero!(T), self.top.clone()), - near: Plane3::from_abcd(zero!(T), zero!(T), -one!(T), self.near.clone()), - far: Plane3::from_abcd(zero!(T), zero!(T), one!(T),self.far.clone()), - } - } - } -} diff --git a/src-old/transform/rotation.rs b/src-old/transform/rotation.rs deleted file mode 100644 index 0957b90..0000000 --- a/src-old/transform/rotation.rs +++ /dev/null @@ -1,645 +0,0 @@ -// Copyright 2013 The Lmath 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. - -//! Various three-dimensional rotation types and impls. -//! -//! Some of these are more useful for constructing matricies and quaternions. -//! than for general use. For example due to issues with gimble lock, it is -//! not reccomended that Euler rotations be used for translations, but -//! they _are_ useful for intuitively specifying rotations. -//! -//! # Examples -//! -//! ~~~rust -//! Euler::new::(1.0, 2.0, 0.0).to_mat3() -//! ~~~ -//! -//! ~~~rust -//! AxisY::(0.3).to_quat() -//! ~~~ - -use std::cast; - -use math::*; - -use math::{Point3, Ray3}; - -/// A two-dimensional rotation -pub trait Rotation2: Eq - + ApproxEq - + ToMat2 { - pub fn rotate_point2(&self, point: Point2) -> Point2; - pub fn rotate_vec2(&self, vec: &Vec2) -> Vec2; - pub fn rotate_ray2(&self, ray: &Ray2) -> Ray2; - pub fn to_rotation_mat2(&self) -> RotationMat2; -} - -/// A three-dimensional rotation -pub trait Rotation3: Eq - + ApproxEq - + ToMat3 - + ToMat4 - + ToQuat { - pub fn rotate_point3(&self, point: &Point3) -> Point3; - pub fn rotate_vec3(&self, vec: &Vec3) -> Vec3; - pub fn rotate_ray3(&self, ray: &Ray3) -> Ray3; - pub fn to_rotation_mat3(&self) -> RotationMat3; -} - -/// A two-dimensional rotation matrix. -/// -/// The matrix is guaranteed to be orthogonal, so some operations can be -/// implemented more efficiently than the implementations for `math::Mat2`. To -/// enforce orthogonality at the type level the operations have been restricted -/// to a subeset of those implemented on `Mat3`. -#[deriving(Eq, Clone)] -pub struct RotationMat2 { - priv mat: Mat2 -} - -impl_approx!(RotationMat2 { mat }) - -impl RotationMat2 { - #[inline] - pub fn as_mat2<'a>(&'a self) -> & 'a Mat2 { - unsafe { cast::transmute(self) } - } -} - -impl Rotation2 for RotationMat2 { - pub fn rotate_point2(&self, point: Point2) -> Point2 { - point.with_vec2(|vec| self.rotate_vec2(vec)) - } - - pub fn rotate_vec2(&self, vec: &Vec2) -> Vec2 { - self.mat.mul_v(vec) - } - - pub fn rotate_ray2(&self, _ray: &Ray2) -> Ray2 { - fail!("Not yet implemented.") - } - - #[inline] - pub fn to_rotation_mat2(&self) -> RotationMat2 { - RotationMat2 { mat: self.to_mat2() } - } -} - -impl ToMat2 for RotationMat2 { - #[inline] pub fn to_mat2(&self) -> Mat2 { self.mat.clone() } -} - -impl RotationMat2 { - #[inline] - pub fn identity() -> RotationMat2 { - RotationMat2 { mat: Mat2::identity() } - } - - #[inline] - pub fn zero() -> RotationMat2 { - RotationMat2 { mat: Mat2::zero() } - } -} - -impl Neg> for RotationMat2 { - #[inline] - pub fn neg(&self) -> RotationMat2 { - RotationMat2 { mat: -self.mat } - } -} - -impl Rotation3 for Quat { - pub fn rotate_point3(&self, point: &Point3) -> Point3 { - point.with_vec3(|vec| self.rotate_vec3(vec)) - } - - pub fn rotate_vec3(&self, vec: &Vec3) -> Vec3 { - self.mul_v(vec) - } - - pub fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { - fail!("Not yet implemented.") - } - - #[inline] - pub fn to_rotation_mat3(&self) -> RotationMat3 { - RotationMat3 { mat: self.to_mat3() } - } -} - -/// A three-dimensional rotation matrix. -/// -/// The matrix is guaranteed to be orthogonal, so some operations, specifically -/// inversion, can be implemented more efficiently than the implementations for -/// `math::Mat3`. To enforce orthogonality at the type level the operations have -/// been restricted to a subeset of those implemented on `Mat3`. -#[deriving(Eq, Clone)] -pub struct RotationMat3 { - priv mat: Mat3 -} - -impl_approx!(RotationMat3 { mat }) - -impl RotationMat3 { - #[inline] - pub fn as_mat3<'a>(&'a self) -> & 'a Mat3 { - unsafe { cast::transmute(self) } - } -} - -impl Rotation3 for RotationMat3 { - pub fn rotate_point3(&self, point: &Point3) -> Point3 { - point.with_vec3(|vec| self.rotate_vec3(vec)) - } - - pub fn rotate_vec3(&self, vec: &Vec3) -> Vec3 { - self.mat.mul_v(vec) - } - - pub fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { - fail!("Not yet implemented.") - } - - #[inline] - pub fn to_rotation_mat3(&self) -> RotationMat3 { - RotationMat3 { mat: self.to_mat3() } - } -} - -impl ToQuat for RotationMat3 { - #[inline] pub fn to_quat(&self) -> Quat { self.mat.to_quat() } -} - -impl ToMat3 for RotationMat3 { - #[inline] pub fn to_mat3(&self) -> Mat3 { self.mat.clone() } -} - -impl ToMat4 for RotationMat3 { - #[inline] pub fn to_mat4(&self) -> Mat4 { self.mat.to_mat4() } -} - -impl RotationMat3 { - #[inline] - pub fn identity() -> RotationMat3 { - RotationMat3 { mat: Mat3::identity() } - } - - #[inline] - pub fn zero() -> RotationMat3 { - RotationMat3 { mat: Mat3::zero() } - } -} - -impl Neg> for RotationMat3 { - #[inline] - pub fn neg(&self) -> RotationMat3 { - RotationMat3 { mat: -self.mat } - } -} - -impl RotationMat3 { - pub fn look_at(dir: &Vec3, up: &Vec3) -> RotationMat3 { - RotationMat3 { mat: Mat3::look_at(dir, up) } - } -} - -/// Euler angles -/// -/// # Fields -/// -/// - `pitch`: the angular rotation around the `x` axis in radians -/// - `yaw`: the angular rotation around the `y` axis in radians -/// - `roll`: the angular rotation around the `z` axis in radians -#[deriving(Eq, Clone)] -pub struct Euler { pitch: T, yaw: T, roll: T } - -impl_dimensioned!(Euler, T, 3) -impl_to_vec!(Euler, 3) -impl_as_vec!(Euler, 3) -impl_swap_components!(Euler) -impl_approx!(Euler { pitch, yaw, roll }) - -pub trait ToEuler { - pub fn to_euler(&self) -> Euler; -} - -impl Euler { - #[inline] - pub fn new(pitch: T, yaw: T, roll: T) -> Euler { - Euler { pitch: pitch, yaw: yaw, roll: roll } - } -} - -impl Rotation3 for Euler { - pub fn rotate_point3(&self, _point: &Point3) -> Point3 { - fail!("Not yet implemented.") - } - - pub fn rotate_vec3(&self, _vec: &Vec3) -> Vec3 { - fail!("Not yet implemented.") - } - - pub fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { - fail!("Not yet implemented.") - } - - #[inline] - pub fn to_rotation_mat3(&self) -> RotationMat3 { - RotationMat3 { mat: self.to_mat3() } - } -} - -impl ToQuat for Euler { - pub fn to_quat(&self) -> Quat { - // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Conversion - let xdiv2 = self.pitch / two!(T); - let ydiv2 = self.yaw / two!(T); - let zdiv2 = self.roll / two!(T); - Quat::new(zdiv2.cos() * xdiv2.cos() * ydiv2.cos() + zdiv2.sin() * xdiv2.sin() * ydiv2.sin(), - zdiv2.sin() * xdiv2.cos() * ydiv2.cos() - zdiv2.cos() * xdiv2.sin() * ydiv2.sin(), - zdiv2.cos() * xdiv2.sin() * ydiv2.cos() + zdiv2.sin() * xdiv2.cos() * ydiv2.sin(), - zdiv2.cos() * xdiv2.cos() * ydiv2.sin() - zdiv2.sin() * xdiv2.sin() * ydiv2.cos()) - } -} - -impl ToMat3 for Euler { - pub fn to_mat3(&self) -> Mat3 { - // http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations - let cx = self.pitch.cos(); - let sx = self.pitch.sin(); - let cy = self.yaw.cos(); - let sy = self.yaw.sin(); - let cz = self.roll.cos(); - let sz = self.roll.sin(); - - Mat3::new(cy * cz, cy * sz, -sy, - -cx * sz + sx * sy * cz, cx * cz + sx * sy * sz, sx * cy, - sx * sz + cx * sy * cz, -sx * cz + cx * sy * sz, cx * cy) - } -} - -impl ToMat4 for Euler { - pub fn to_mat4(&self) -> Mat4 { - // http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations - let cx = self.pitch.cos(); - let sx = self.pitch.sin(); - let cy = self.yaw.cos(); - let sy = self.yaw.sin(); - let cz = self.roll.cos(); - let sz = self.roll.sin(); - - Mat4::new(cy * cz, cy * sz, -sy, zero!(T), - -cx * sz + sx * sy * cz, cx * cz + sx * sy * sz, sx * cy, zero!(T), - sx * sz + cx * sy * cz, -sx * cz + cx * sy * sz, cx * cy, zero!(T), - zero!(T), zero!(T), zero!(T), one!(T)) - } -} - -#[cfg(test)] -mod euler_tests { - // TODO -} - -/// A rotation about an arbitrary axis -/// -/// # Fields -/// -/// - `axis`: The axis vector about which to rotate. -/// - `angle`: The angle of rotation in radians. -#[deriving(Eq, Clone)] -pub struct AxisAngle { - axis: Vec3, - angle: T, -} - -impl_approx!(AxisAngle { axis, angle }) - -pub trait ToAxisAngle { - pub fn to_axis_angle(&self) -> AxisAngle; -} - -impl AxisAngle { - pub fn new(axis: Vec3, angle: T) -> AxisAngle { - AxisAngle { axis: axis, angle: angle } - } -} - -impl Rotation3 for AxisAngle { - pub fn rotate_point3(&self, point: &Point3) -> Point3 { - point.with_vec3(|vec| self.rotate_vec3(vec)) - } - - pub fn rotate_vec3(&self, vec: &Vec3) -> Vec3 { - // Rodrigues' rotation formula - // http://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula - // - // ~~~ - // v cos θ + (k × v) sin θ + k(k ⋅ v)(1 - cos θ) - // ~~~ - // - // Where: - // - `v` = vec - // - `k` = self.axis - // - `θ` = self.angle - - vec.mul_s(self.angle.cos()) - .add_v(&self.axis.cross(vec)).mul_s(self.angle.sin()) - .add_v(&self.axis.mul_s(self.axis.dot(vec)) - .mul_s(one!(T) - self.angle.cos())) - } - - pub fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { - fail!("Not yet implemented.") - } - - #[inline] - pub fn to_rotation_mat3(&self) -> RotationMat3 { - RotationMat3 { mat: self.to_mat3() } - } -} - -impl ToQuat for AxisAngle { - pub fn to_quat(&self) -> Quat { - let half = self.angle / two!(T); - Quat::from_sv(half.cos(), self.axis.mul_s(half.sin())) - } -} - -impl ToMat3 for AxisAngle { - pub fn to_mat3(&self) -> Mat3 { - let c = self.angle.cos(); - let s = self.angle.sin(); - let _1_c = one!(T) - c; - - Mat3::new(_1_c * self.axis.x * self.axis.x + c, - _1_c * self.axis.x * self.axis.y + s * self.axis.z, - _1_c * self.axis.x * self.axis.z - s * self.axis.y, - - _1_c * self.axis.x * self.axis.y - s * self.axis.z, - _1_c * self.axis.y * self.axis.y + c, - _1_c * self.axis.y * self.axis.z + s * self.axis.x, - - _1_c * self.axis.x * self.axis.z + s * self.axis.y, - _1_c * self.axis.y * self.axis.z - s * self.axis.x, - _1_c * self.axis.z * self.axis.z + c) - } -} - -impl ToMat4 for AxisAngle { - pub fn to_mat4(&self) -> Mat4 { - let c = self.angle.cos(); - let s = self.angle.sin(); - let _1_c = one!(T) - c; - - Mat4::new(_1_c * self.axis.x * self.axis.x + c, - _1_c * self.axis.x * self.axis.y + s * self.axis.z, - _1_c * self.axis.x * self.axis.z - s * self.axis.y, - zero!(T), - - _1_c * self.axis.x * self.axis.y - s * self.axis.z, - _1_c * self.axis.y * self.axis.y + c, - _1_c * self.axis.y * self.axis.z + s * self.axis.x, - zero!(T), - - _1_c * self.axis.x * self.axis.z + s * self.axis.y, - _1_c * self.axis.y * self.axis.z - s * self.axis.x, - _1_c * self.axis.z * self.axis.z + c, - zero!(T), - - zero!(T), zero!(T), zero!(T), one!(T)) - } -} - -#[cfg(test)] -mod axis_angle_tests { - use math::*; - use transform::*; - - #[test] - fn test_to_quat() { - let v = Vec3::new(1f, 0f, 0f); - - let q = AxisAngle::new(Vec3::new(0f, 0f, -1f), (-45f).to_radians()).to_quat(); - - // http://www.wolframalpha.com/input/?i={1,0}+rotate+-45+degrees - assert_approx_eq!(q.mul_v(&v), Vec3::new(1f/2f.sqrt(), 1f/2f.sqrt(), 0f)); - assert_eq!(q.mul_v(&v).magnitude(), v.magnitude()); - assert_approx_eq!(q.to_mat3(), Mat3::new( 1f/2f.sqrt(), 1f/2f.sqrt(), 0f, - -1f/2f.sqrt(), 1f/2f.sqrt(), 0f, - 0f, 0f, 1f)); - } -} - -/// An angle around the X axis (pitch), in radians. -#[deriving(Eq, Clone)] -pub struct AngleX(T); - -impl_approx!(AngleX) - -impl Rotation3 for AngleX { - pub fn rotate_point3(&self, _point: &Point3) -> Point3 { - fail!("Not yet implemented.") - } - - pub fn rotate_vec3(&self, _vec: &Vec3) -> Vec3 { - fail!("Not yet implemented.") - } - - pub fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { - fail!("Not yet implemented.") - } - - #[inline] - pub fn to_rotation_mat3(&self) -> RotationMat3 { - RotationMat3 { mat: self.to_mat3() } - } -} - -impl ToQuat for AngleX { - pub fn to_quat(&self) -> Quat { - Quat::new(((**self) / two!(T)).cos(), (**self).sin(), zero!(T), zero!(T)) - } -} - -impl ToMat3 for AngleX { - pub fn to_mat3(&self) -> Mat3 { - // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations - let cos_theta = (**self).cos(); - let sin_theta = (**self).sin(); - - Mat3::new(one!(T), zero!(T), zero!(T), - zero!(T), cos_theta.clone(), sin_theta.clone(), - zero!(T), -sin_theta.clone(), cos_theta.clone()) - } -} - -impl ToMat4 for AngleX { - pub fn to_mat4(&self) -> Mat4 { - // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations - let cos_theta = (**self).cos(); - let sin_theta = (**self).sin(); - - Mat4::new(one!(T), zero!(T), zero!(T), zero!(T), - zero!(T), cos_theta.clone(), sin_theta.clone(), zero!(T), - zero!(T), -sin_theta.clone(), cos_theta.clone(), zero!(T), - zero!(T), zero!(T), zero!(T), one!(T)) - } -} - -#[cfg(test)] -mod angle_x_tests { - // TODO -} - -/// An angle around the X axis (yaw), in radians. -#[deriving(Eq, Clone)] -pub struct AngleY(T); - -impl_approx!(AngleY) - -impl Rotation3 for AngleY { - pub fn rotate_point3(&self, _point: &Point3) -> Point3 { - fail!("Not yet implemented.") - } - - pub fn rotate_vec3(&self, _vec: &Vec3) -> Vec3 { - fail!("Not yet implemented.") - } - - pub fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { - fail!("Not yet implemented.") - } - - #[inline] - pub fn to_rotation_mat3(&self) -> RotationMat3 { - RotationMat3 { mat: self.to_mat3() } - } -} - -impl ToQuat for AngleY { - pub fn to_quat(&self) -> Quat { - Quat::new(((**self) / two!(T)).cos(), zero!(T), (**self).sin(), zero!(T)) - } -} - -impl ToMat3 for AngleY { - pub fn to_mat3(&self) -> Mat3 { - // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations - let cos_theta = (**self).cos(); - let sin_theta = (**self).sin(); - - Mat3::new(cos_theta.clone(), zero!(T), -sin_theta.clone(), - zero!(T), one!(T), zero!(T), - sin_theta.clone(), zero!(T), cos_theta.clone()) - } -} - -impl ToMat4 for AngleY { - pub fn to_mat4(&self) -> Mat4 { - // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations - let cos_theta = (**self).cos(); - let sin_theta = (**self).sin(); - - Mat4::new(cos_theta.clone(), zero!(T), -sin_theta.clone(), zero!(T), - zero!(T), one!(T), zero!(T), zero!(T), - sin_theta.clone(), zero!(T), cos_theta.clone(), zero!(T), - zero!(T), zero!(T), zero!(T), one!(T)) - } -} - -#[cfg(test)] -mod angle_y_tests { - // TODO -} - -/// An angle around the Z axis (roll), in radians. -#[deriving(Eq, Clone)] -pub struct AngleZ(T); - -impl_approx!(AngleZ) - -impl Rotation2 for AngleZ { - pub fn rotate_point2(&self, _point: Point2) -> Point2 { - fail!("Not yet implemented.") - } - - pub fn rotate_vec2(&self, _vec: &Vec2) -> Vec2 { - fail!("Not yet implemented.") - } - - pub fn rotate_ray2(&self, _ray: &Ray2) -> Ray2 { - fail!("Not yet implemented.") - } - - #[inline] - pub fn to_rotation_mat2(&self) -> RotationMat2 { - fail!("Not yet implemented.") - } -} - -impl Rotation3 for AngleZ { - pub fn rotate_point3(&self, _point: &Point3) -> Point3 { - fail!("Not yet implemented.") - } - - pub fn rotate_vec3(&self, _vec: &Vec3) -> Vec3 { - fail!("Not yet implemented.") - } - - pub fn rotate_ray3(&self, _ray: &Ray3) -> Ray3 { - fail!("Not yet implemented.") - } - - #[inline] - pub fn to_rotation_mat3(&self) -> RotationMat3 { - RotationMat3 { mat: self.to_mat3() } - } -} - -impl ToQuat for AngleZ { - pub fn to_quat(&self) -> Quat { - Quat::new(((**self) / two!(T)).cos(), zero!(T), zero!(T), (**self).sin()) - } -} - -impl ToMat3 for AngleZ { - pub fn to_mat3(&self) -> Mat3 { - // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations - let cos_theta = (**self).cos(); - let sin_theta = (**self).sin(); - - Mat3::new(cos_theta.clone(), sin_theta.clone(), zero!(T), - -sin_theta.clone(), cos_theta.clone(), zero!(T), - zero!(T), zero!(T), one!(T)) - } -} - -impl ToMat4 for AngleZ { - pub fn to_mat4(&self) -> Mat4 { - // http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations - let cos_theta = (**self).cos(); - let sin_theta = (**self).sin(); - - Mat4::new(cos_theta.clone(), sin_theta.clone(), zero!(T), zero!(T), - -sin_theta.clone(), cos_theta.clone(), zero!(T), zero!(T), - zero!(T), zero!(T), one!(T), zero!(T), - zero!(T), zero!(T), zero!(T), one!(T)) - } -} - -#[cfg(test)] -mod angle_z_tests { - // TODO -} diff --git a/src-old/transform/transform.rs b/src-old/transform/transform.rs deleted file mode 100644 index a2e68f6..0000000 --- a/src-old/transform/transform.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 The Lmath 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. - -pub use self::projection::{Projection, Perspective, PerspectiveFOV, Ortho}; -pub use self::rotation::{Rotation2, Rotation3}; -pub use self::rotation::{Euler, ToEuler}; -pub use self::rotation::{AxisAngle, ToAxisAngle}; -pub use self::rotation::{AngleX, AngleY, AngleZ}; - -use math::{Vec3, Quat}; - -pub mod projection; -pub mod rotation; - -pub trait Transform {} - -pub struct QuatTransform { - scale: T, - translation: Vec3, - rotation: Quat, -} - -impl Transform for QuatTransform {}