Remove old code

Yayy!
This commit is contained in:
Brendan Zabarauskas 2013-09-20 16:01:37 +10:00
parent f968784b9b
commit 0e0107837d
23 changed files with 0 additions and 6458 deletions

View file

@ -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<T> {
center: Point2<T>,
size: Vec2<T>,
}
impl_approx!(AABB2 { center, size })
impl<T> AABB2<T> {
#[inline]
pub fn new(center: Point2<T>, size: Vec2<T>) -> AABB2<T> {
AABB2 { center: center, size: size }
}
}
impl<T:Clone + Float> AABB2<T> {
pub fn from_bounds(mn: Point2<T>, mx: Point2<T>) -> AABB2<T> {
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<T> {
center: Point3<T>,
size: Vec3<T>,
}
impl_approx!(AABB3 { center, size })
impl<T> AABB3<T> {
#[inline]
pub fn new(center: Point3<T>, size: Vec3<T>) -> AABB3<T> {
AABB3 { center: center, size: size }
}
}
impl<T:Clone + Float> AABB3<T> {
pub fn from_bounds(mn: Point3<T>, mx: Point3<T>) -> AABB3<T> {
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<T>) -> bool {}
}

View file

@ -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;

View file

@ -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<T> {
center: Point3<T>,
axis: Vec3<T>,
radius: T,
}

View file

@ -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<T> {
left: Plane3<T>,
right: Plane3<T>,
bottom: Plane3<T>,
top: Plane3<T>,
near: Plane3<T>,
far: Plane3<T>,
}
impl_dimensioned!(Frustum, Plane3<T>, 6)
impl_approx!(Frustum {
left, right,
top, bottom,
near, far
})
#[deriving(Clone, Eq)]
pub struct FrustumPoints<T> {
near_top_left: Point3<T>,
near_top_right: Point3<T>,
near_bottom_left: Point3<T>,
near_bottom_right: Point3<T>,
far_top_left: Point3<T>,
far_top_right: Point3<T>,
far_bottom_left: Point3<T>,
far_bottom_right: Point3<T>,
}
impl_dimensioned!(FrustumPoints, Point3<T>, 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<T:Clone + Float> Frustum<T> {
/// Constructs a frustum
pub fn from_planes(left: Plane3<T>, right: Plane3<T>,
bottom: Plane3<T>, top: Plane3<T>,
near: Plane3<T>, far: Plane3<T>) -> Frustum<T> {
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<T>) -> Frustum<T> {
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<T:Clone + Float> Frustum<T> {
/// 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<T> {
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(),
}
}
}

View file

@ -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<T> {
center: Point2<T>,
axis: Vec2<T>,
extents: Vec2<T>,
}
#[deriving(Clone, Eq)]
pub struct OBB3<T> {
center: Point3<T>,
axis: Vec3<T>,
extents: Vec3<T>,
}

View file

@ -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<T> {
center: Point3<T>,
radius: T,
}
impl_approx!(Sphere { center, radius })
impl<T> Sphere<T> {
#[inline]
pub fn new(center: Point3<T>, radius: T) -> Sphere<T> {
Sphere { center: center, radius: radius }
}
}

View file

@ -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;

View file

@ -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<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for $T<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &$T<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &$T<T>, epsilon: &T) -> bool {
$( self.$field.approx_eq_eps(&other.$field, epsilon) )&&+
}
}
);
($T:ident) => (
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for $T<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &$T<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &$T<T>, epsilon: &T) -> bool {
(**self).approx_eq_eps(&**other, epsilon)
}
}
)
)

View file

@ -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<T> Dimensioned<$T,[$T,..$n]> for $Self<T> {
#[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<T:Clone> $ToVec<T> for $Self<T> {
#[inline]
pub fn $to_vec(&self) -> $Vec<T> {
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<T> $AsVec<T> for $Self<T> {
/// Safely transmute to a vec.
#[inline]
pub fn $as_vec<'a>(&'a self) -> &'a $Vec<T> {
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<T> {
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<T>) -> $Vec<T>) -> $Self<T> {
use std::cast::transmute;
unsafe { transmute(f(self.$as_vec())) }
}
}
)
)
macro_rules! impl_swap_components(
($Self:ident) => (
impl<T:Clone> SwapComponents for $Self<T> {
#[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;
}
}
)
)

File diff suppressed because it is too large Load diff

View file

@ -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<T,Slice> {
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> = (T,);
pub type Tuple2<T> = (T,T);
pub type Tuple3<T> = (T,T,T);
pub type Tuple4<T> = (T,T,T,T);
pub type Tuple5<T> = (T,T,T,T,T);
pub type Tuple6<T> = (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> = [T, ..1];
pub type Fixed2<T> = [T, ..2];
pub type Fixed3<T> = [T, ..3];
pub type Fixed4<T> = [T, ..4];
pub type Fixed5<T> = [T, ..5];
pub type Fixed6<T> = [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)

View file

@ -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<T> {
normal: Vec3<T>,
distance: T,
}
impl_approx!(Plane3 { normal, distance })
impl<T:Clone + Float> Plane3<T> {
/// # 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<T> {
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<T>, distance: T) -> Plane3<T> {
Plane3 { normal: normal, distance: distance }
}
/// Construct a plane from the components of a four-dimensional vector
pub fn from_vec4(vec: Vec4<T>) -> Plane3<T> {
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>) -> 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<T>) -> Point3<T> {
fail!(~"not yet implemented")
}
/// Returns `true` if the ray intersects the plane
pub fn intersects(&self, _ray: &Ray3<T>) -> bool {
fail!(~"not yet implemented")
}
/// Returns `true` if `pos` is located behind the plane - otherwise it returns `false`
pub fn contains(&self, pos: &Point3<T>) -> bool {
self.distance(pos) < zero!(T)
}
}
impl<T:Clone + Float> Plane3<T> {
/// Constructs a plane that passes through the the three points `a`, `b` and `c`
pub fn from_3p(a: Point3<T>,
b: Point3<T>,
c: Point3<T>) -> Option<Plane3<T>> {
// 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<T>) -> Option<Ray3<T>> {
let dir = self.normal.cross(&other.normal);
if dir.approx_eq(&Vec3::zero::<T>()) {
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<T>, other_b: &Plane3<T>) -> Option<Point3<T>> {
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<T> ToStr for Plane3<T> {
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");
}
}

View file

@ -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<T, Vec, Ray>: Eq
+ Add<Vec, Self>
+ Sub<Self, Vec>
+ Mul<Vec, Self>
+ ApproxEq<T>
+ 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<T> { 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<T> {
pub fn as_point2<'a>(&'a self) -> &'a Point2<T>;
pub fn as_mut_point2<'a>(&'a mut self) -> &'a mut Point2<T>;
}
impl<T:Clone + Num> AsPoint2<T> for Vec2<T> {
#[inline]
pub fn as_point2<'a>(&'a self) -> &'a Point2<T> {
unsafe { cast::transmute(self) }
}
#[inline]
pub fn as_mut_point2<'a>(&'a mut self) -> &'a mut Point2<T> {
unsafe { cast::transmute(self) }
}
}
impl<T:Num> Point2<T> {
/// Creates a new point from three coordinates.
#[inline]
pub fn new(x: T, y: T) -> Point2<T> {
Point2 { x: x, y: y }
}
/// Converts a vector to a point.
#[inline]
pub fn from_vec2(vec: Vec2<T>) -> Point2<T> {
unsafe { cast::transmute(vec) }
}
/// The coordinate [0, 0].
#[inline]
pub fn origin() -> Point2<T> {
Point2::new(zero!(T), zero!(T))
}
}
impl<T:Clone + Num> ToVec3<T> for Point2<T> {
/// Converts the point to a three-dimensional homogeneous vector:
/// `[x, y] -> [x, y, 1]`
#[inline]
pub fn to_vec3(&self) -> Vec3<T> {
Vec3::new(self.x.clone(),
self.y.clone(),
one!(T))
}
}
impl<T:Clone + Float> Point<T, Vec2<T>, Ray2<T>> for Point2<T> {
/// Applies a displacement vector to the point.
#[inline]
pub fn translate_v(&self, offset: &Vec2<T>) -> Point2<T> {
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<T> {
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<T>) -> Point2<T> {
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<T>) -> Vec2<T> {
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>) -> T {
((*other) - (*self)).magnitude2()
}
/// Returns the scalar distance to the other point.
#[inline]
pub fn distance(&self, other: &Point2<T>) -> T {
other.distance2(self).sqrt()
}
/// Returns a normalized direction vector pointing to the other point.
#[inline]
pub fn direction(&self, other: &Point2<T>) -> Vec2<T> {
((*other) - (*self)).normalize()
}
/// Projects a normalized ray towards the other point.
#[inline]
pub fn ray_to(&self, other: &Point2<T>) -> Ray2<T> {
Ray2::new(self.clone(), self.direction(other))
}
}
impl<T:Clone + Float> Add<Vec2<T>, Point2<T>> for Point2<T> {
/// Applies a displacement vector to the point.
fn add(&self, offset: &Vec2<T>) -> Point2<T> {
self.translate_v(offset)
}
}
impl<T:Clone + Float> Sub<Point2<T>, Vec2<T>> for Point2<T> {
/// Calculates the displacement vector from the point to `other`.
fn sub(&self, other: &Point2<T>) -> Vec2<T> {
self.displacement(other)
}
}
impl<T:Clone + Float> Mul<Vec2<T>, Point2<T>> for Point2<T> {
/// Scales the distance from the point to the origin using the components
/// of a vector.
fn mul(&self, factor: &Vec2<T>) -> Point2<T> {
self.scale_v(factor)
}
}
impl<T> ToStr for Point2<T> {
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<T> { 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<T> {
pub fn as_point3<'a>(&'a self) -> &'a Point3<T>;
pub fn as_mut_point3<'a>(&'a mut self) -> &'a mut Point3<T>;
}
impl<T:Clone + Num> AsPoint3<T> for Vec3<T> {
#[inline]
pub fn as_point3<'a>(&'a self) -> &'a Point3<T> {
unsafe { cast::transmute(self) }
}
#[inline]
pub fn as_mut_point3<'a>(&'a mut self) -> &'a mut Point3<T> {
unsafe { cast::transmute(self) }
}
}
impl<T:Num> Point3<T> {
/// Creates a new point from three coordinates.
#[inline]
pub fn new(x: T, y: T, z: T) -> Point3<T> {
Point3 { x: x, y: y, z: z }
}
/// Converts a vector to a point.
#[inline]
pub fn from_vec3(vec: Vec3<T>) -> Point3<T> {
unsafe { cast::transmute(vec) }
}
/// The coordinate [0, 0, 0].
#[inline]
pub fn origin() -> Point3<T> {
Point3::new(zero!(T), zero!(T), zero!(T))
}
}
impl<T:Clone + Num> ToVec4<T> for Point3<T> {
/// Converts the point to a four-dimensional homogeneous vector:
/// `[x, y, z] -> [x, y, z, 1]`
#[inline]
pub fn to_vec4(&self) -> Vec4<T> {
Vec4::new(self.x.clone(),
self.y.clone(),
self.z.clone(),
one!(T))
}
}
impl<T:Clone + Float> Point<T, Vec3<T>, Ray3<T>> for Point3<T> {
/// Applies a displacement vector to the point.
#[inline]
pub fn translate_v(&self, offset: &Vec3<T>) -> Point3<T> {
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<T> {
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<T>) -> Point3<T> {
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<T>) -> Vec3<T> {
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>) -> T {
((*other) - (*self)).magnitude2()
}
/// Returns the scalar distance to the other point.
#[inline]
pub fn distance(&self, other: &Point3<T>) -> T {
other.distance2(self).sqrt()
}
/// Returns a normalized direction vector pointing to the other point.
#[inline]
pub fn direction(&self, other: &Point3<T>) -> Vec3<T> {
((*other) - (*self)).normalize()
}
/// Projects a normalized ray towards the other point.
#[inline]
pub fn ray_to(&self, other: &Point3<T>) -> Ray3<T> {
Ray3::new(self.clone(), self.direction(other))
}
}
impl<T:Clone + Float> Add<Vec3<T>, Point3<T>> for Point3<T> {
/// Applies a displacement vector to the point
fn add(&self, offset: &Vec3<T>) -> Point3<T> {
self.translate_v(offset)
}
}
impl<T:Clone + Float> Sub<Point3<T>, Vec3<T>> for Point3<T> {
/// Calculates the displacement required to move the point to `other`.
fn sub(&self, other: &Point3<T>) -> Vec3<T> {
self.displacement(other)
}
}
impl<T:Clone + Float> Mul<Vec3<T>, Point3<T>> for Point3<T> {
/// Scales the distance from the point to the origin using the components
/// of a vector.
fn mul(&self, factor: &Vec3<T>) -> Point3<T> {
self.scale_v(factor)
}
}
impl<T> ToStr for Point3<T> {
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]");
}
}

View file

@ -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<f32>;
pub type dquat = Quat<f64>;
// Rust-style type aliases
pub type Quatf = Quat<float>;
pub type Quatf32 = Quat<f32>;
pub type Quatf64 = Quat<f64>;
/// A quaternion in scalar/vector form
#[deriving(Clone, Eq)]
pub struct Quat<T> { s: T, v: Vec3<T> }
impl_dimensioned!(Quat, T, 4)
impl_swap_components!(Quat)
impl_approx!(Quat { s, v })
pub trait ToQuat<T> {
pub fn to_quat(&self) -> Quat<T>;
}
impl<T> Quat<T> {
/// 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<T> {
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<T>) -> Quat<T> {
Quat { s: s, v: v }
}
}
impl<T:Clone + Float> Quat<T> {
#[inline]
pub fn look_at(dir: &Vec3<T>, up: &Vec3<T>) -> Quat<T> {
Mat3::look_at(dir, up).to_quat()
}
#[inline]
pub fn from_axes(x: Vec3<T>, y: Vec3<T>, z: Vec3<T>) -> Quat<T> {
Mat3::from_axes(x, y, z).to_quat()
}
/// The multiplicative identity, ie: `q = 1 + 0i + 0j + 0i`
#[inline]
pub fn identity() -> Quat<T> {
Quat::from_sv(one!(T), Vec3::zero())
}
/// The additive identity, ie: `q = 0 + 0i + 0j + 0i`
#[inline]
pub fn zero() -> Quat<T> {
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<T> {
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<T> {
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<T>) -> Vec3<T> {
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<T>) -> Quat<T> {
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<T>) -> Quat<T> {
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<T>) -> Quat<T> {
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>) -> T {
self.s * other.s + self.v.dot(&other.v)
}
/// The conjugate of the quaternion
#[inline]
pub fn conjugate(&self) -> Quat<T> {
Quat::from_sv(self.s.clone(), -self.v.clone())
}
/// The multiplicative inverse of the quaternion
#[inline]
pub fn inverse(&self) -> Quat<T> {
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<T> {
self.mul_s(one!(T) / self.magnitude())
}
/// Normalised linear interpolation
///
/// # Return value
///
/// The intoperlated quaternion
pub fn nlerp(&self, other: &Quat<T>, amount: T) -> Quat<T> {
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<T>, amount: T) -> Quat<T> {
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<T:Clone + Num> ToMat3<T> for Quat<T> {
/// Convert the quaternion to a 3 x 3 rotation matrix
pub fn to_mat3(&self) -> Mat3<T> {
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<T:Clone + Float> Neg<Quat<T>> for Quat<T> {
#[inline]
pub fn neg(&self) -> Quat<T> {
Quat::from_sv(-self.s, -self.v)
}
}

View file

@ -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<T> {
origin: Point2<T>,
direction: Vec2<T>,
}
impl_approx!(Ray2 { origin, direction })
impl<T> Ray2<T> {
/// Creates a new ray from a position coordinate and a direction vector
#[inline]
pub fn new(origin: Point2<T>, direction: Vec2<T>) -> Ray2<T> {
Ray2 { origin: origin, direction: direction }
}
}
#[deriving(Clone, Eq)]
pub struct Ray3<T> {
origin: Point3<T>,
direction: Vec3<T>,
}
impl_approx!(Ray3 { origin, direction })
impl<T> Ray3<T> {
/// Creates a new ray from a position coordinate and a direction vector
#[inline]
pub fn new(origin: Point3<T>, direction: Vec3<T>) -> Ray3<T> {
Ray3 { origin: origin, direction: direction }
}
}

File diff suppressed because it is too large Load diff

View file

@ -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;

View file

@ -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<Elem,T> {
bounds: AABB3<T>,
octants: [Option<~Octree<Elem,T>>, ..8],
}

View file

@ -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;

View file

@ -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;

View file

@ -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<T:Clone + Float>(fovy: T, aspectRatio: T, near: T, far: T) -> Mat4<T> {
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<T:Clone + Float>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
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<T:Clone + Float>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
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<T> {
pub fn if_valid<U:Clone>(&self, f: &fn() -> U) -> Result<U, ~str>;
pub fn to_mat4(&self) -> Result<Mat4<T>, ~str>;
pub fn to_frustum(&self) -> Result<Frustum<T>, ~str>;
}
/// A symmetrical perspective projection based on a field-of-view angle
#[deriving(Clone, Eq)]
pub struct PerspectiveFOV<T> {
fovy: T, //radians
aspect: T,
near: T,
far: T,
}
impl<T:Clone + Float> PerspectiveFOV<T> {
pub fn to_perspective(&self) -> Result<Perspective<T>, ~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<T:Clone + Float> Projection<T> for PerspectiveFOV<T> {
pub fn if_valid<U:Clone>(&self, f: &fn() -> U) -> Result<U, ~str> {
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<Mat4<T>, ~str> {
do self.to_perspective().chain |proj| { proj.to_mat4() }
}
pub fn to_frustum(&self) -> Result<Frustum<T>, ~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<T> {
left: T,
right: T,
bottom: T,
top: T,
near: T,
far: T,
}
impl<T:Clone + Float> Projection<T> for Perspective<T> {
pub fn if_valid<U:Clone>(&self, f: &fn() -> U) -> Result<U, ~str> {
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<Mat4<T>, ~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<Frustum<T>, ~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<T> {
left: T,
right: T,
bottom: T,
top: T,
near: T,
far: T,
}
impl<T:Clone + Float> Projection<T> for Ortho<T> {
pub fn if_valid<U:Clone>(&self, f: &fn() -> U) -> Result<U, ~str> {
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<Mat4<T>, ~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<Frustum<T>, ~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()),
}
}
}
}

View file

@ -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::<f32>(1.0, 2.0, 0.0).to_mat3()
//! ~~~
//!
//! ~~~rust
//! AxisY::<f32>(0.3).to_quat()
//! ~~~
use std::cast;
use math::*;
use math::{Point3, Ray3};
/// A two-dimensional rotation
pub trait Rotation2<T>: Eq
+ ApproxEq<T>
+ ToMat2<T> {
pub fn rotate_point2(&self, point: Point2<T>) -> Point2<T>;
pub fn rotate_vec2(&self, vec: &Vec2<T>) -> Vec2<T>;
pub fn rotate_ray2(&self, ray: &Ray2<T>) -> Ray2<T>;
pub fn to_rotation_mat2(&self) -> RotationMat2<T>;
}
/// A three-dimensional rotation
pub trait Rotation3<T>: Eq
+ ApproxEq<T>
+ ToMat3<T>
+ ToMat4<T>
+ ToQuat<T> {
pub fn rotate_point3(&self, point: &Point3<T>) -> Point3<T>;
pub fn rotate_vec3(&self, vec: &Vec3<T>) -> Vec3<T>;
pub fn rotate_ray3(&self, ray: &Ray3<T>) -> Ray3<T>;
pub fn to_rotation_mat3(&self) -> RotationMat3<T>;
}
/// 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<T> {
priv mat: Mat2<T>
}
impl_approx!(RotationMat2 { mat })
impl<T> RotationMat2<T> {
#[inline]
pub fn as_mat2<'a>(&'a self) -> & 'a Mat2<T> {
unsafe { cast::transmute(self) }
}
}
impl<T:Clone + Float> Rotation2<T> for RotationMat2<T> {
pub fn rotate_point2(&self, point: Point2<T>) -> Point2<T> {
point.with_vec2(|vec| self.rotate_vec2(vec))
}
pub fn rotate_vec2(&self, vec: &Vec2<T>) -> Vec2<T> {
self.mat.mul_v(vec)
}
pub fn rotate_ray2(&self, _ray: &Ray2<T>) -> Ray2<T> {
fail!("Not yet implemented.")
}
#[inline]
pub fn to_rotation_mat2(&self) -> RotationMat2<T> {
RotationMat2 { mat: self.to_mat2() }
}
}
impl<T:Clone + Float> ToMat2<T> for RotationMat2<T> {
#[inline] pub fn to_mat2(&self) -> Mat2<T> { self.mat.clone() }
}
impl<T:Num> RotationMat2<T> {
#[inline]
pub fn identity() -> RotationMat2<T> {
RotationMat2 { mat: Mat2::identity() }
}
#[inline]
pub fn zero() -> RotationMat2<T> {
RotationMat2 { mat: Mat2::zero() }
}
}
impl<T:Clone + Num> Neg<RotationMat2<T>> for RotationMat2<T> {
#[inline]
pub fn neg(&self) -> RotationMat2<T> {
RotationMat2 { mat: -self.mat }
}
}
impl<T:Clone + Float> Rotation3<T> for Quat<T> {
pub fn rotate_point3(&self, point: &Point3<T>) -> Point3<T> {
point.with_vec3(|vec| self.rotate_vec3(vec))
}
pub fn rotate_vec3(&self, vec: &Vec3<T>) -> Vec3<T> {
self.mul_v(vec)
}
pub fn rotate_ray3(&self, _ray: &Ray3<T>) -> Ray3<T> {
fail!("Not yet implemented.")
}
#[inline]
pub fn to_rotation_mat3(&self) -> RotationMat3<T> {
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<T> {
priv mat: Mat3<T>
}
impl_approx!(RotationMat3 { mat })
impl<T> RotationMat3<T> {
#[inline]
pub fn as_mat3<'a>(&'a self) -> & 'a Mat3<T> {
unsafe { cast::transmute(self) }
}
}
impl<T:Clone + Float> Rotation3<T> for RotationMat3<T> {
pub fn rotate_point3(&self, point: &Point3<T>) -> Point3<T> {
point.with_vec3(|vec| self.rotate_vec3(vec))
}
pub fn rotate_vec3(&self, vec: &Vec3<T>) -> Vec3<T> {
self.mat.mul_v(vec)
}
pub fn rotate_ray3(&self, _ray: &Ray3<T>) -> Ray3<T> {
fail!("Not yet implemented.")
}
#[inline]
pub fn to_rotation_mat3(&self) -> RotationMat3<T> {
RotationMat3 { mat: self.to_mat3() }
}
}
impl<T:Clone + Float> ToQuat<T> for RotationMat3<T> {
#[inline] pub fn to_quat(&self) -> Quat<T> { self.mat.to_quat() }
}
impl<T:Clone + Float> ToMat3<T> for RotationMat3<T> {
#[inline] pub fn to_mat3(&self) -> Mat3<T> { self.mat.clone() }
}
impl<T:Clone + Float> ToMat4<T> for RotationMat3<T> {
#[inline] pub fn to_mat4(&self) -> Mat4<T> { self.mat.to_mat4() }
}
impl<T:Num> RotationMat3<T> {
#[inline]
pub fn identity() -> RotationMat3<T> {
RotationMat3 { mat: Mat3::identity() }
}
#[inline]
pub fn zero() -> RotationMat3<T> {
RotationMat3 { mat: Mat3::zero() }
}
}
impl<T:Clone + Num> Neg<RotationMat3<T>> for RotationMat3<T> {
#[inline]
pub fn neg(&self) -> RotationMat3<T> {
RotationMat3 { mat: -self.mat }
}
}
impl<T:Float> RotationMat3<T> {
pub fn look_at(dir: &Vec3<T>, up: &Vec3<T>) -> RotationMat3<T> {
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<T> { 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<T> {
pub fn to_euler(&self) -> Euler<T>;
}
impl<T:Float> Euler<T> {
#[inline]
pub fn new(pitch: T, yaw: T, roll: T) -> Euler<T> {
Euler { pitch: pitch, yaw: yaw, roll: roll }
}
}
impl<T:Clone + Float> Rotation3<T> for Euler<T> {
pub fn rotate_point3(&self, _point: &Point3<T>) -> Point3<T> {
fail!("Not yet implemented.")
}
pub fn rotate_vec3(&self, _vec: &Vec3<T>) -> Vec3<T> {
fail!("Not yet implemented.")
}
pub fn rotate_ray3(&self, _ray: &Ray3<T>) -> Ray3<T> {
fail!("Not yet implemented.")
}
#[inline]
pub fn to_rotation_mat3(&self) -> RotationMat3<T> {
RotationMat3 { mat: self.to_mat3() }
}
}
impl<T:Float> ToQuat<T> for Euler<T> {
pub fn to_quat(&self) -> Quat<T> {
// 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<T:Float> ToMat3<T> for Euler<T> {
pub fn to_mat3(&self) -> Mat3<T> {
// 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<T:Float> ToMat4<T> for Euler<T> {
pub fn to_mat4(&self) -> Mat4<T> {
// 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<T> {
axis: Vec3<T>,
angle: T,
}
impl_approx!(AxisAngle { axis, angle })
pub trait ToAxisAngle<T> {
pub fn to_axis_angle(&self) -> AxisAngle<T>;
}
impl<T:Float> AxisAngle<T> {
pub fn new(axis: Vec3<T>, angle: T) -> AxisAngle<T> {
AxisAngle { axis: axis, angle: angle }
}
}
impl<T:Float> Rotation3<T> for AxisAngle<T> {
pub fn rotate_point3(&self, point: &Point3<T>) -> Point3<T> {
point.with_vec3(|vec| self.rotate_vec3(vec))
}
pub fn rotate_vec3(&self, vec: &Vec3<T>) -> Vec3<T> {
// 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<T>) -> Ray3<T> {
fail!("Not yet implemented.")
}
#[inline]
pub fn to_rotation_mat3(&self) -> RotationMat3<T> {
RotationMat3 { mat: self.to_mat3() }
}
}
impl<T:Float> ToQuat<T> for AxisAngle<T> {
pub fn to_quat(&self) -> Quat<T> {
let half = self.angle / two!(T);
Quat::from_sv(half.cos(), self.axis.mul_s(half.sin()))
}
}
impl<T:Float> ToMat3<T> for AxisAngle<T> {
pub fn to_mat3(&self) -> Mat3<T> {
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<T:Float> ToMat4<T> for AxisAngle<T> {
pub fn to_mat4(&self) -> Mat4<T> {
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>(T);
impl_approx!(AngleX)
impl<T:Clone + Float> Rotation3<T> for AngleX<T> {
pub fn rotate_point3(&self, _point: &Point3<T>) -> Point3<T> {
fail!("Not yet implemented.")
}
pub fn rotate_vec3(&self, _vec: &Vec3<T>) -> Vec3<T> {
fail!("Not yet implemented.")
}
pub fn rotate_ray3(&self, _ray: &Ray3<T>) -> Ray3<T> {
fail!("Not yet implemented.")
}
#[inline]
pub fn to_rotation_mat3(&self) -> RotationMat3<T> {
RotationMat3 { mat: self.to_mat3() }
}
}
impl<T:Float> ToQuat<T> for AngleX<T> {
pub fn to_quat(&self) -> Quat<T> {
Quat::new(((**self) / two!(T)).cos(), (**self).sin(), zero!(T), zero!(T))
}
}
impl<T:Clone + Float> ToMat3<T> for AngleX<T> {
pub fn to_mat3(&self) -> Mat3<T> {
// 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<T:Clone + Float> ToMat4<T> for AngleX<T> {
pub fn to_mat4(&self) -> Mat4<T> {
// 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>(T);
impl_approx!(AngleY)
impl<T:Clone + Float> Rotation3<T> for AngleY<T> {
pub fn rotate_point3(&self, _point: &Point3<T>) -> Point3<T> {
fail!("Not yet implemented.")
}
pub fn rotate_vec3(&self, _vec: &Vec3<T>) -> Vec3<T> {
fail!("Not yet implemented.")
}
pub fn rotate_ray3(&self, _ray: &Ray3<T>) -> Ray3<T> {
fail!("Not yet implemented.")
}
#[inline]
pub fn to_rotation_mat3(&self) -> RotationMat3<T> {
RotationMat3 { mat: self.to_mat3() }
}
}
impl<T:Float> ToQuat<T> for AngleY<T> {
pub fn to_quat(&self) -> Quat<T> {
Quat::new(((**self) / two!(T)).cos(), zero!(T), (**self).sin(), zero!(T))
}
}
impl<T:Clone + Float> ToMat3<T> for AngleY<T> {
pub fn to_mat3(&self) -> Mat3<T> {
// 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<T:Clone + Float> ToMat4<T> for AngleY<T> {
pub fn to_mat4(&self) -> Mat4<T> {
// 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>(T);
impl_approx!(AngleZ)
impl<T:Float> Rotation2<T> for AngleZ<T> {
pub fn rotate_point2(&self, _point: Point2<T>) -> Point2<T> {
fail!("Not yet implemented.")
}
pub fn rotate_vec2(&self, _vec: &Vec2<T>) -> Vec2<T> {
fail!("Not yet implemented.")
}
pub fn rotate_ray2(&self, _ray: &Ray2<T>) -> Ray2<T> {
fail!("Not yet implemented.")
}
#[inline]
pub fn to_rotation_mat2(&self) -> RotationMat2<T> {
fail!("Not yet implemented.")
}
}
impl<T:Clone + Float> Rotation3<T> for AngleZ<T> {
pub fn rotate_point3(&self, _point: &Point3<T>) -> Point3<T> {
fail!("Not yet implemented.")
}
pub fn rotate_vec3(&self, _vec: &Vec3<T>) -> Vec3<T> {
fail!("Not yet implemented.")
}
pub fn rotate_ray3(&self, _ray: &Ray3<T>) -> Ray3<T> {
fail!("Not yet implemented.")
}
#[inline]
pub fn to_rotation_mat3(&self) -> RotationMat3<T> {
RotationMat3 { mat: self.to_mat3() }
}
}
impl<T:Float> ToQuat<T> for AngleZ<T> {
pub fn to_quat(&self) -> Quat<T> {
Quat::new(((**self) / two!(T)).cos(), zero!(T), zero!(T), (**self).sin())
}
}
impl<T:Clone + Float> ToMat3<T> for AngleZ<T> {
pub fn to_mat3(&self) -> Mat3<T> {
// 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<T:Clone + Float> ToMat4<T> for AngleZ<T> {
pub fn to_mat4(&self) -> Mat4<T> {
// 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
}

View file

@ -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<T> {}
pub struct QuatTransform<T> {
scale: T,
translation: Vec3<T>,
rotation: Quat<T>,
}
impl<T> Transform<T> for QuatTransform<T> {}