Remove old code
Yayy!
This commit is contained in:
parent
f968784b9b
commit
0e0107837d
23 changed files with 0 additions and 6458 deletions
|
@ -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 {}
|
||||
}
|
|
@ -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;
|
|
@ -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,
|
||||
}
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>,
|
||||
}
|
|
@ -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 }
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
1677
src-old/math/mat.rs
1677
src-old/math/mat.rs
File diff suppressed because it is too large
Load diff
|
@ -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)
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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]");
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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 }
|
||||
}
|
||||
}
|
2161
src-old/math/vec.rs
2161
src-old/math/vec.rs
File diff suppressed because it is too large
Load diff
|
@ -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;
|
|
@ -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],
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
|
@ -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()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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> {}
|
Loading…
Reference in a new issue