Simplify type signatures and make function implementations more strait-forward
This results in more code duplication, but the resulting type signatures are much simpler and the implementations are far easier to understand. It should be easier for llvm to optimise things too, seeing as closures are not used.
This commit is contained in:
parent
07006afeac
commit
3559ab2e35
14 changed files with 1057 additions and 562 deletions
|
@ -22,19 +22,11 @@
|
|||
|
||||
use point::{Point, Point2, Point3};
|
||||
use vector::{Vector, Vector2, Vector3};
|
||||
use array::build;
|
||||
use num::BaseNum;
|
||||
use std::fmt;
|
||||
use std::num::{zero, one};
|
||||
use std::iter::Iterator;
|
||||
|
||||
pub trait Aabb
|
||||
<
|
||||
S: BaseNum,
|
||||
V: Vector<S, Slice>,
|
||||
P: Point<S, V, Slice>,
|
||||
Slice
|
||||
> {
|
||||
pub trait Aabb<S: BaseNum, V: Vector<S>, P: Point<S, V>> {
|
||||
/// Create a new AABB using two points as opposing corners.
|
||||
fn new(p1: P, p2: P) -> Self;
|
||||
|
||||
|
@ -45,28 +37,29 @@ pub trait Aabb
|
|||
fn max<'a>(&'a self) -> &'a P;
|
||||
|
||||
/// Return the dimensions of this AABB.
|
||||
#[inline] fn dim(&self) -> V { self.max().sub_p(self.min()) }
|
||||
#[inline]
|
||||
fn dim(&self) -> V { self.max().sub_p(self.min()) }
|
||||
|
||||
/// Return the volume this AABB encloses.
|
||||
#[inline] fn volume(&self) -> S { self.dim().comp_mul() }
|
||||
#[inline]
|
||||
fn volume(&self) -> S { self.dim().comp_mul() }
|
||||
|
||||
/// Return the center point of this AABB.
|
||||
#[inline] fn center(&self) -> P {
|
||||
#[inline]
|
||||
fn center(&self) -> P {
|
||||
let two = one::<S>() + one::<S>();
|
||||
self.min().add_v(&self.dim().div_s(two))
|
||||
}
|
||||
|
||||
/// Tests whether a point is cointained in the box, inclusive for min corner
|
||||
/// and exclusive for the max corner.
|
||||
#[inline] fn contains(&self, p: &P) -> bool {
|
||||
p.sub_p(self.min()).iter().all(|x| *x >= zero::<S>()) &&
|
||||
self.max().sub_p(p).iter().all(|x| *x > zero::<S>())
|
||||
}
|
||||
#[inline]
|
||||
fn contains(&self, p: &P) -> bool;
|
||||
|
||||
/// Returns a new AABB that is grown to include the given point.
|
||||
fn grow(&self, p: &P) -> Self {
|
||||
let min : P = build(|i| self.min().i(i).partial_min(*p.i(i)));
|
||||
let max : P = build(|i| self.max().i(i).partial_max(*p.i(i)));
|
||||
let min = self.min().min(p);
|
||||
let max = self.max().max(p);
|
||||
Aabb::new(min, max)
|
||||
}
|
||||
|
||||
|
@ -108,10 +101,23 @@ impl<S: BaseNum> Aabb2<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Aabb<S, Vector2<S>, Point2<S>, [S, ..2]> for Aabb2<S> {
|
||||
impl<S: BaseNum> Aabb<S, Vector2<S>, Point2<S>> for Aabb2<S> {
|
||||
#[inline]
|
||||
fn new(p1: Point2<S>, p2: Point2<S>) -> Aabb2<S> { Aabb2::new(p1, p2) }
|
||||
#[inline] fn min<'a>(&'a self) -> &'a Point2<S> { &self.min }
|
||||
#[inline] fn max<'a>(&'a self) -> &'a Point2<S> { &self.max }
|
||||
|
||||
#[inline]
|
||||
fn min<'a>(&'a self) -> &'a Point2<S> { &self.min }
|
||||
|
||||
#[inline]
|
||||
fn max<'a>(&'a self) -> &'a Point2<S> { &self.max }
|
||||
|
||||
#[inline]
|
||||
fn contains(&self, p: &Point2<S>) -> bool {
|
||||
let v_min = p.sub_p(self.min());
|
||||
let v_max = self.max().sub_p(p);
|
||||
v_min.x >= zero() && v_min.y >= zero() &&
|
||||
v_max.x > zero() && v_max.y > zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> fmt::Show for Aabb2<S> {
|
||||
|
@ -142,10 +148,23 @@ impl<S: BaseNum> Aabb3<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Aabb<S, Vector3<S>, Point3<S>, [S, ..3]> for Aabb3<S> {
|
||||
impl<S: BaseNum> Aabb<S, Vector3<S>, Point3<S>> for Aabb3<S> {
|
||||
#[inline]
|
||||
fn new(p1: Point3<S>, p2: Point3<S>) -> Aabb3<S> { Aabb3::new(p1, p2) }
|
||||
#[inline] fn min<'a>(&'a self) -> &'a Point3<S> { &self.min }
|
||||
#[inline] fn max<'a>(&'a self) -> &'a Point3<S> { &self.max }
|
||||
|
||||
#[inline]
|
||||
fn min<'a>(&'a self) -> &'a Point3<S> { &self.min }
|
||||
|
||||
#[inline]
|
||||
fn max<'a>(&'a self) -> &'a Point3<S> { &self.max }
|
||||
|
||||
#[inline]
|
||||
fn contains(&self, p: &Point3<S>) -> bool {
|
||||
let v_min = p.sub_p(self.min());
|
||||
let v_max = self.max().sub_p(p);
|
||||
v_min.x >= zero() && v_min.y >= zero() && v_min.z >= zero() &&
|
||||
v_max.x > zero() && v_max.y > zero() && v_max.z > zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> fmt::Show for Aabb3<S> {
|
||||
|
|
|
@ -15,12 +15,6 @@
|
|||
|
||||
use std::num;
|
||||
|
||||
use array::Array;
|
||||
use matrix::{Matrix2, Matrix3, Matrix4};
|
||||
use point::{Point2, Point3};
|
||||
use quaternion::Quaternion;
|
||||
use vector::{Vector2, Vector3, Vector4};
|
||||
|
||||
pub trait ApproxEq<T: Float> {
|
||||
fn approx_epsilon(_hack: Option<Self>) -> T {
|
||||
num::cast(1.0e-5).unwrap()
|
||||
|
@ -35,7 +29,7 @@ pub trait ApproxEq<T: Float> {
|
|||
}
|
||||
|
||||
|
||||
macro_rules! approx_simple(
|
||||
macro_rules! approx_float(
|
||||
($S:ident) => (
|
||||
impl ApproxEq<$S> for $S {
|
||||
#[inline]
|
||||
|
@ -46,31 +40,5 @@ macro_rules! approx_simple(
|
|||
)
|
||||
)
|
||||
|
||||
approx_simple!(f32)
|
||||
approx_simple!(f64)
|
||||
|
||||
|
||||
macro_rules! approx_array(
|
||||
(impl<$S:ident> $Self:ty) => (
|
||||
impl<$S: Float + Clone + ApproxEq<$S>> ApproxEq<$S> for $Self {
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &$Self, epsilon: &$S) -> bool {
|
||||
self.iter().zip(other.iter())
|
||||
.all(|(a, b)| a.approx_eq_eps(b, epsilon))
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
approx_array!(impl<S> Matrix2<S>)
|
||||
approx_array!(impl<S> Matrix3<S>)
|
||||
approx_array!(impl<S> Matrix4<S>)
|
||||
|
||||
approx_array!(impl<S> Quaternion<S>)
|
||||
|
||||
approx_array!(impl<S> Vector2<S>)
|
||||
approx_array!(impl<S> Vector3<S>)
|
||||
approx_array!(impl<S> Vector4<S>)
|
||||
|
||||
approx_array!(impl<S> Point2<S>)
|
||||
approx_array!(impl<S> Point3<S>)
|
||||
approx_float!(f32)
|
||||
approx_float!(f64)
|
||||
|
|
|
@ -13,138 +13,84 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#![macro_escape]
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use std::slice::{Items, MutItems};
|
||||
/// An array containing elements of type `Element`
|
||||
pub trait Array1<Element: Copy> {
|
||||
/// Get the pointer to the first element of the array.
|
||||
fn ptr<'a>(&'a self) -> &'a Element;
|
||||
|
||||
/// Get a mutable pointer to the first element of the array.
|
||||
fn mut_ptr<'a>(&'a mut self) -> &'a mut Element;
|
||||
|
||||
/// An array containing elements of type `T` represented with `Repr`
|
||||
///
|
||||
/// This trait abstracts over [T, ..N], and is manually implemented for arrays
|
||||
/// of length 2, 3, and 4.
|
||||
pub trait Array<T: Clone, Repr> {
|
||||
/// Get a shared reference to the `i`th value.
|
||||
fn i<'a>(&'a self, i: uint) -> &'a T;
|
||||
fn i(&self, i: uint) -> Element;
|
||||
|
||||
/// Get a mutable reference to the `i`th value.
|
||||
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut T;
|
||||
|
||||
/// Get a shared reference to this array's data as `Repr`.
|
||||
fn as_slice<'a>(&'a self) -> &'a Repr;
|
||||
|
||||
/// Get a mutable reference to this array's data as `Repr`.
|
||||
fn as_mut_slice<'a>(&'a mut self) -> &'a mut Repr;
|
||||
|
||||
/// Construct a new Array from its representation.
|
||||
fn from_repr(repr: Repr) -> Self;
|
||||
|
||||
/// Create a new `Array` using a closure to generate the elements. The
|
||||
/// closure is passed the index of the element it should produce.
|
||||
fn build(builder: |i: uint| -> T) -> Self;
|
||||
|
||||
/// Iterate over the elements of this `Array`, yielding shared references
|
||||
/// to items.
|
||||
fn iter<'a>(&'a self) -> Items<'a, T>;
|
||||
|
||||
/// Iterate over the elements of this `Array`, yielding mutable references
|
||||
/// to items.
|
||||
fn mut_iter<'a>(&'a mut self) -> MutItems<'a, T>;
|
||||
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut Element;
|
||||
|
||||
#[inline]
|
||||
/// Swap the elements at indices `a` and `b` in-place.
|
||||
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;
|
||||
fn swap_i(&mut self, a: uint, b: uint) {
|
||||
// Yeah, ok borrow checker – I know what I'm doing here
|
||||
unsafe { ptr::swap(self.mut_i(a), self.mut_i(b)) };
|
||||
}
|
||||
|
||||
/// Fold over this array, creating the same type as the type of the
|
||||
/// elements. Use `.iter().fold(...)` for a more flexible fold. The first
|
||||
/// element passed to the fold is the accumulator. It starts as the first
|
||||
/// value in the array.
|
||||
fn fold(&self, f: |&T, &T| -> T) -> T;
|
||||
|
||||
/// Iterate over this array, yielding mutable references to items. The
|
||||
/// closure is passed the index of the element the reference is pointing
|
||||
/// at.
|
||||
fn each_mut(&mut self, f: |i: uint, x: &mut T|);
|
||||
/// Replace an element in the array.
|
||||
#[inline]
|
||||
fn replace_i(&mut self, i: uint, src: Element) -> Element {
|
||||
mem::replace(self.mut_i(i), src)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! array(
|
||||
(impl<$S:ident> $Self:ty -> [$T:ty, ..$n:expr] $_n:ident) => (
|
||||
impl<$S: Clone> Array<$T, [$T,..$n]> for $Self {
|
||||
#[inline]
|
||||
fn i<'a>(&'a self, i: uint) -> &'a $T {
|
||||
&'a self.as_slice()[i]
|
||||
}
|
||||
/// A column-major array
|
||||
pub trait Array2<Column: Array1<Element>, Row: Array1<Element>, Element: Copy> {
|
||||
/// Get the pointer to the first element of the array.
|
||||
fn ptr<'a>(&'a self) -> &'a Element;
|
||||
|
||||
#[inline]
|
||||
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut $T {
|
||||
&'a mut self.as_mut_slice()[i]
|
||||
}
|
||||
/// Get a mutable pointer to the first element of the array.
|
||||
fn mut_ptr<'a>(&'a mut self) -> &'a mut Element;
|
||||
|
||||
#[inline]
|
||||
fn as_slice<'a>(&'a self) -> &'a [$T,..$n] {
|
||||
unsafe { ::std::mem::transmute(self) }
|
||||
}
|
||||
/// Get a shared reference to a column of this array.
|
||||
fn c<'a>(&'a self, c: uint) -> &'a Column;
|
||||
|
||||
#[inline]
|
||||
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [$T,..$n] {
|
||||
unsafe { ::std::mem::transmute(self) }
|
||||
}
|
||||
/// Get a mutable reference to a column of this array.
|
||||
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Column;
|
||||
|
||||
#[inline]
|
||||
fn from_repr(slice: [$T,..$n]) -> $Self {
|
||||
unsafe { ::std::mem::transmute(slice) }
|
||||
}
|
||||
/// Swap two columns of this array.
|
||||
#[inline]
|
||||
fn swap_c(&mut self, a: uint, b: uint) {
|
||||
unsafe { ptr::swap(self.mut_c(a), self.mut_c(b)) };
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn build(builder: |i: uint| -> $T) -> $Self {
|
||||
Array::from_repr(gen_builder!($_n))
|
||||
}
|
||||
/// Replace a column in the array.
|
||||
#[inline]
|
||||
fn replace_c(&mut self, c: uint, src: Column) -> Column {
|
||||
mem::replace(self.mut_c(c), src)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn iter<'a>(&'a self) -> ::std::slice::Items<'a, $T> {
|
||||
self.as_slice().iter()
|
||||
}
|
||||
/// Get a row from this array by-value.
|
||||
fn r(&self, r: uint) -> Row;
|
||||
|
||||
#[inline]
|
||||
fn mut_iter<'a>(&'a mut self) -> ::std::slice::MutItems<'a, $T> {
|
||||
self.as_mut_slice().mut_iter()
|
||||
}
|
||||
/// Swap two rows of this array.
|
||||
fn swap_r(&mut self, a: uint, b: uint);
|
||||
|
||||
#[inline]
|
||||
fn fold(&self, f: |&$T, &$T| -> $T) -> $T {
|
||||
gen_fold!($_n)
|
||||
}
|
||||
/// Return a shared reference to the element at column `c` and row `r`.
|
||||
#[inline]
|
||||
fn cr(&self, c: uint, r: uint) -> Element { self.c(c).i(r) }
|
||||
|
||||
#[inline]
|
||||
fn each_mut(&mut self, f: |i: uint, x: &mut $T|) {
|
||||
gen_each_mut!($_n)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
/// Return a mutable reference to the element at column `c` and row `r`.
|
||||
#[inline]
|
||||
fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut Element {
|
||||
self.mut_c(c).mut_i(r)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn build<T: Clone, Slice, A: Array<T, Slice>>(builder: |i: uint| -> T) -> A {
|
||||
Array::build(builder)
|
||||
/// Swap the values at index `a` and `b`
|
||||
#[inline]
|
||||
fn swap_cr(&mut self, a: (uint, uint), b: (uint, uint)) {
|
||||
let (ac, ar) = a;
|
||||
let (bc, br) = b;
|
||||
unsafe { ptr::swap(self.mut_cr(ac, ar), self.mut_cr(bc, br)) };
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! gen_builder(
|
||||
(_2) => ({ [builder(0), builder(1)] });
|
||||
(_3) => ({ [builder(0), builder(1), builder(2)] });
|
||||
(_4) => ({ [builder(0), builder(1), builder(2), builder(3)] });
|
||||
)
|
||||
|
||||
macro_rules! gen_fold(
|
||||
(_2) => ({ f(self.i(0), self.i(1)) });
|
||||
(_3) => ({ let tmp = f(self.i(0), self.i(1)); f(&tmp, self.i(2)) });
|
||||
(_4) => ({ let tmp1 = f(self.i(0), self.i(1)); let tmp2 = f(&tmp1, self.i(2)); f(&tmp2, self.i(3)) });
|
||||
)
|
||||
|
||||
macro_rules! gen_each_mut(
|
||||
(_2) => ({ f(0, self.mut_i(0)); f(1, self.mut_i(1)); });
|
||||
(_3) => ({ f(0, self.mut_i(0)); f(1, self.mut_i(1)); f(2, self.mut_i(2)); });
|
||||
(_4) => ({ f(0, self.mut_i(0)); f(1, self.mut_i(1)); f(2, self.mut_i(2)); f(3, self.mut_i(3)); });
|
||||
)
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
|
||||
//! View frustum for visibility determination
|
||||
|
||||
use matrix::{Matrix, Matrix4};
|
||||
use array::Array2;
|
||||
use matrix::Matrix4;
|
||||
use num::BaseFloat;
|
||||
use plane::Plane;
|
||||
use point::Point3;
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
//! `look_at`, `from_angle`, `from_euler`, and `from_axis_angle` methods.
|
||||
//! These are provided for convenience.
|
||||
|
||||
pub use array::Array;
|
||||
|
||||
mod array;
|
||||
|
||||
pub mod matrix;
|
||||
|
@ -63,5 +61,3 @@ pub mod sphere;
|
|||
|
||||
pub mod approx;
|
||||
pub mod num;
|
||||
pub mod ptr;
|
||||
|
||||
|
|
|
@ -24,20 +24,12 @@ use intersect::Intersect;
|
|||
|
||||
/// A generic directed line segment from `origin` to `dest`.
|
||||
#[deriving(Clone, Eq)]
|
||||
pub struct Line<P>
|
||||
{
|
||||
pub struct Line<P> {
|
||||
pub origin: P,
|
||||
pub dest: P,
|
||||
}
|
||||
|
||||
impl
|
||||
<
|
||||
S: BaseNum,
|
||||
Slice,
|
||||
V: Vector<S,Slice>,
|
||||
P: Point<S,V,Slice>
|
||||
> Line<P>
|
||||
{
|
||||
impl<S: BaseNum, V: Vector<S>, P: Point<S, V>> Line<P> {
|
||||
pub fn new(origin: P, dest: P) -> Line<P> {
|
||||
Line { origin:origin, dest:dest }
|
||||
}
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
//! Column major, square matrix types and traits.
|
||||
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::num::{Zero, zero, One, one, cast};
|
||||
|
||||
use angle::{Rad, sin, cos, sin_cos};
|
||||
use approx::ApproxEq;
|
||||
use array::{Array, build};
|
||||
use array::{Array1, Array2};
|
||||
use num::{BaseFloat, BaseNum};
|
||||
use point::{Point, Point3};
|
||||
use quaternion::{Quaternion, ToQuaternion};
|
||||
|
@ -267,107 +268,47 @@ Matrix4<S> {
|
|||
}
|
||||
}
|
||||
|
||||
array!(impl<S> Matrix2<S> -> [Vector2<S>, ..2] _2)
|
||||
array!(impl<S> Matrix3<S> -> [Vector3<S>, ..3] _3)
|
||||
array!(impl<S> Matrix4<S> -> [Vector4<S>, ..4] _4)
|
||||
|
||||
pub trait Matrix
|
||||
<
|
||||
S: BaseFloat, Slice,
|
||||
V: Clone + Vector<S, VSlice> + Array<S, VSlice>, VSlice
|
||||
>
|
||||
: Array<V, Slice>
|
||||
+ Neg<Self>
|
||||
+ Zero + One
|
||||
+ ApproxEq<S>
|
||||
{
|
||||
/// Get a shared reference to a column of this matrix.
|
||||
#[inline]
|
||||
fn c<'a>(&'a self, c: uint) -> &'a V { self.i(c) }
|
||||
|
||||
/// Get a mutable reference to a column of this matrix.
|
||||
#[inline]
|
||||
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut V { self.mut_i(c) }
|
||||
|
||||
/// Swap two columns of this matrix.
|
||||
#[inline]
|
||||
fn swap_c(&mut self, a: uint, b: uint) {
|
||||
let tmp = self.c(a).clone();
|
||||
*self.mut_c(a) = self.c(b).clone();
|
||||
*self.mut_c(b) = tmp;
|
||||
}
|
||||
|
||||
/// Get a row from this matrix.
|
||||
///
|
||||
/// Since matrixes in cgmath are stored column-major, this cannot return a
|
||||
/// reference. It creates a new copy of the row instead.
|
||||
#[inline]
|
||||
fn r(&self, r: uint) -> V {
|
||||
build(|i| self.i(i).i(r).clone())
|
||||
}
|
||||
|
||||
/// Swap two rows of this matrix.
|
||||
#[inline]
|
||||
fn swap_r(&mut self, a: uint, b: uint) {
|
||||
self.each_mut(|_, c| c.swap(a, b))
|
||||
}
|
||||
|
||||
/// Return a shared reference to the element at column `c` and row `r`.
|
||||
#[inline]
|
||||
fn cr<'a>(&'a self, c: uint, r: uint) -> &'a S { self.i(c).i(r) }
|
||||
|
||||
/// Return a mutable reference to the element at column `c` and row `r`.
|
||||
#[inline]
|
||||
fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut S {
|
||||
self.mut_i(c).mut_i(r)
|
||||
}
|
||||
|
||||
/// Swap the values at index `a` and `b`
|
||||
#[inline]
|
||||
fn swap_cr(&mut self, a: (uint, uint), b: (uint, uint)) {
|
||||
let (ca, ra) = a;
|
||||
let (cb, rb) = b;
|
||||
let tmp = self.cr(ca, ra).clone();
|
||||
*self.mut_cr(ca, ra) = self.cr(cb, rb).clone();
|
||||
*self.mut_cr(cb, rb) = tmp;
|
||||
}
|
||||
|
||||
/// Negate this matrix in-place (multiply by scalar -1).
|
||||
#[inline] fn neg_self(&mut self) { self.each_mut(|_, x| *x = x.neg()) }
|
||||
|
||||
pub trait Matrix<S: BaseFloat, V: Clone + Vector<S>>: Array2<V, V, S>
|
||||
+ Neg<Self>
|
||||
+ Zero + One
|
||||
+ ApproxEq<S> {
|
||||
/// Multiply this matrix by a scalar, returning the new matrix.
|
||||
#[inline] fn mul_s(&self, s: S) -> Self { build(|i| self.c(i).mul_s(s.clone())) }
|
||||
fn mul_s(&self, s: S) -> Self;
|
||||
/// Divide this matrix by a scalar, returning the new matrix.
|
||||
#[inline] fn div_s(&self, s: S) -> Self { build(|i| self.c(i).div_s(s.clone())) }
|
||||
fn div_s(&self, s: S) -> Self;
|
||||
/// Take the remainder of this matrix by a scalar, returning the new
|
||||
/// matrix.
|
||||
#[inline] fn rem_s(&self, s: S) -> Self { build(|i| self.c(i).rem_s(s.clone())) }
|
||||
fn rem_s(&self, s: S) -> Self;
|
||||
|
||||
/// Add this matrix with another matrix, returning the new metrix.
|
||||
#[inline] fn add_m(&self, other: &Self) -> Self { build(|i| self.i(i).add_v(other.i(i))) }
|
||||
fn add_m(&self, m: &Self) -> Self;
|
||||
/// Subtract another matrix from this matrix, returning the new matrix.
|
||||
#[inline] fn sub_m(&self, other: &Self) -> Self { build(|i| self.i(i).sub_v(other.i(i))) }
|
||||
fn sub_m(&self, m: &Self) -> Self;
|
||||
|
||||
/// Multiplay a vector by this matrix, returning a new vector.
|
||||
#[inline] fn mul_v(&self, v: &V) -> V { build(|i| self.r(i).dot(v)) }
|
||||
fn mul_v(&self, v: &V) -> V;
|
||||
|
||||
/// Multiply this matrix by another matrix, returning the new matrix.
|
||||
fn mul_m(&self, other: &Self) -> Self;
|
||||
fn mul_m(&self, m: &Self) -> Self;
|
||||
|
||||
/// Negate this matrix in-place (multiply by scalar -1).
|
||||
fn neg_self(&mut self);
|
||||
|
||||
/// Multiply this matrix by a scalar, in-place.
|
||||
#[inline] fn mul_self_s(&mut self, s: S) { self.each_mut(|_, c| *c = c.mul_s(s.clone())) }
|
||||
fn mul_self_s(&mut self, s: S);
|
||||
/// Divide this matrix by a scalar, in-place.
|
||||
#[inline] fn div_self_s(&mut self, s: S) { self.each_mut(|_, c| *c = c.div_s(s.clone())) }
|
||||
fn div_self_s(&mut self, s: S);
|
||||
/// Take the remainder of this matrix, in-place.
|
||||
#[inline] fn rem_self_s(&mut self, s: S) { self.each_mut(|_, c| *c = c.rem_s(s.clone())) }
|
||||
fn rem_self_s(&mut self, s: S);
|
||||
|
||||
/// Add this matrix with another matrix, in-place.
|
||||
#[inline] fn add_self_m(&mut self, other: &Self) { self.each_mut(|i, c| *c = c.add_v(other.c(i))) }
|
||||
fn add_self_m(&mut self, m: &Self);
|
||||
/// Subtract another matrix from this matrix, in-place.
|
||||
#[inline] fn sub_self_m(&mut self, other: &Self) { self.each_mut(|i, c| *c = c.sub_v(other.c(i))) }
|
||||
fn sub_self_m(&mut self, m: &Self);
|
||||
|
||||
/// Multiply this matrix by another matrix, in-place.
|
||||
#[inline] fn mul_self_m(&mut self, other: &Self) { *self = self.mul_m(other); }
|
||||
#[inline]
|
||||
fn mul_self_m(&mut self, m: &Self) { *self = self.mul_m(m); }
|
||||
|
||||
/// Transpose this matrix, returning a new matrix.
|
||||
fn transpose(&self) -> Self;
|
||||
|
@ -377,8 +318,7 @@ pub trait Matrix
|
|||
fn determinant(&self) -> S;
|
||||
|
||||
/// Return a vector containing the diagonal of this matrix.
|
||||
#[inline]
|
||||
fn diagonal(&self) -> V { build(|i| self.cr(i, i).clone()) }
|
||||
fn diagonal(&self) -> V;
|
||||
|
||||
/// Return the trace of this matrix. That is, the sum of the diagonal.
|
||||
#[inline]
|
||||
|
@ -397,16 +337,12 @@ pub trait Matrix
|
|||
|
||||
/// Test if this matrix is invertible.
|
||||
#[inline]
|
||||
fn is_invertible(&self) -> bool {
|
||||
!self.determinant().approx_eq(&zero())
|
||||
}
|
||||
fn is_invertible(&self) -> bool { !self.determinant().approx_eq(&zero()) }
|
||||
|
||||
/// Test if this matrix is the identity matrix. That is, it is diagonal
|
||||
/// and every element in the diagonal is one.
|
||||
#[inline]
|
||||
fn is_identity(&self) -> bool {
|
||||
self.approx_eq(&one())
|
||||
}
|
||||
fn is_identity(&self) -> bool { self.approx_eq(&one()) }
|
||||
|
||||
/// Test if this is a diagonal matrix. That is, every element outside of
|
||||
/// the diagonal is 0.
|
||||
|
@ -425,9 +361,9 @@ impl<S: BaseFloat> Sub<Matrix2<S>, Matrix2<S>> for Matrix2<S> { #[inline] fn sub
|
|||
impl<S: BaseFloat> Sub<Matrix3<S>, Matrix3<S>> for Matrix3<S> { #[inline] fn sub(&self, other: &Matrix3<S>) -> Matrix3<S> { self.sub_m(other) } }
|
||||
impl<S: BaseFloat> Sub<Matrix4<S>, Matrix4<S>> for Matrix4<S> { #[inline] fn sub(&self, other: &Matrix4<S>) -> Matrix4<S> { self.sub_m(other) } }
|
||||
|
||||
impl<S: BaseFloat> Neg<Matrix2<S>> for Matrix2<S> { #[inline] fn neg(&self) -> Matrix2<S> { build(|i| self.i(i).neg()) } }
|
||||
impl<S: BaseFloat> Neg<Matrix3<S>> for Matrix3<S> { #[inline] fn neg(&self) -> Matrix3<S> { build(|i| self.i(i).neg()) } }
|
||||
impl<S: BaseFloat> Neg<Matrix4<S>> for Matrix4<S> { #[inline] fn neg(&self) -> Matrix4<S> { build(|i| self.i(i).neg()) } }
|
||||
impl<S: BaseFloat> Neg<Matrix2<S>> for Matrix2<S> { #[inline] fn neg(&self) -> Matrix2<S> { Matrix2::from_cols(self.c(0).neg(), self.c(1).neg()) } }
|
||||
impl<S: BaseFloat> Neg<Matrix3<S>> for Matrix3<S> { #[inline] fn neg(&self) -> Matrix3<S> { Matrix3::from_cols(self.c(0).neg(), self.c(1).neg(), self.c(2).neg()) } }
|
||||
impl<S: BaseFloat> Neg<Matrix4<S>> for Matrix4<S> { #[inline] fn neg(&self) -> Matrix4<S> { Matrix4::from_cols(self.c(0).neg(), self.c(1).neg(), self.c(2).neg(), self.c(3).neg()) } }
|
||||
|
||||
impl<S: BaseFloat> Zero for Matrix2<S> { #[inline] fn zero() -> Matrix2<S> { Matrix2::zero() } #[inline] fn is_zero(&self) -> bool { *self == zero() } }
|
||||
impl<S: BaseFloat> Zero for Matrix3<S> { #[inline] fn zero() -> Matrix3<S> { Matrix3::zero() } #[inline] fn is_zero(&self) -> bool { *self == zero() } }
|
||||
|
@ -441,15 +377,186 @@ impl<S: BaseFloat> One for Matrix2<S> { #[inline] fn one() -> Matrix2<S> { Matri
|
|||
impl<S: BaseFloat> One for Matrix3<S> { #[inline] fn one() -> Matrix3<S> { Matrix3::identity() } }
|
||||
impl<S: BaseFloat> One for Matrix4<S> { #[inline] fn one() -> Matrix4<S> { Matrix4::identity() } }
|
||||
|
||||
impl<S: BaseFloat>
|
||||
Matrix<S, [Vector2<S>, ..2], Vector2<S>, [S, ..2]>
|
||||
for Matrix2<S>
|
||||
{
|
||||
impl<S: Copy> Array2<Vector2<S>, Vector2<S>, S> for Matrix2<S> {
|
||||
#[inline]
|
||||
fn ptr<'a>(&'a self) -> &'a S { &self.x.x }
|
||||
|
||||
#[inline]
|
||||
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x.x }
|
||||
|
||||
#[inline]
|
||||
fn c<'a>(&'a self, c: uint) -> &'a Vector2<S> {
|
||||
let slice: &'a [Vector2<S>, ..2] = unsafe { mem::transmute(self) };
|
||||
&'a slice[c]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vector2<S> {
|
||||
let slice: &'a mut [Vector2<S>, ..2] = unsafe { mem::transmute(self) };
|
||||
&'a mut slice[c]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn r(&self, r: uint) -> Vector2<S> {
|
||||
Vector2::new(self.cr(0, r),
|
||||
self.cr(1, r))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn swap_r(&mut self, a: uint, b: uint) {
|
||||
self.mut_c(0).swap_i(a, b);
|
||||
self.mut_c(1).swap_i(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Copy> Array2<Vector3<S>, Vector3<S>, S> for Matrix3<S> {
|
||||
#[inline]
|
||||
fn ptr<'a>(&'a self) -> &'a S { &self.x.x }
|
||||
|
||||
#[inline]
|
||||
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x.x }
|
||||
|
||||
#[inline]
|
||||
fn c<'a>(&'a self, c: uint) -> &'a Vector3<S> {
|
||||
let slice: &'a [Vector3<S>, ..3] = unsafe { mem::transmute(self) };
|
||||
&'a slice[c]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vector3<S> {
|
||||
let slice: &'a mut [Vector3<S>, ..3] = unsafe { mem::transmute(self) };
|
||||
&'a mut slice[c]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn r(&self, r: uint) -> Vector3<S> {
|
||||
Vector3::new(self.cr(0, r),
|
||||
self.cr(1, r),
|
||||
self.cr(2, r))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn swap_r(&mut self, a: uint, b: uint) {
|
||||
self.mut_c(0).swap_i(a, b);
|
||||
self.mut_c(1).swap_i(a, b);
|
||||
self.mut_c(2).swap_i(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Copy> Array2<Vector4<S>, Vector4<S>, S> for Matrix4<S> {
|
||||
#[inline]
|
||||
fn ptr<'a>(&'a self) -> &'a S { &self.x.x }
|
||||
|
||||
#[inline]
|
||||
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x.x }
|
||||
|
||||
#[inline]
|
||||
fn c<'a>(&'a self, c: uint) -> &'a Vector4<S> {
|
||||
let slice: &'a [Vector4<S>, ..4] = unsafe { mem::transmute(self) };
|
||||
&'a slice[c]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Vector4<S> {
|
||||
let slice: &'a mut [Vector4<S>, ..4] = unsafe { mem::transmute(self) };
|
||||
&'a mut slice[c]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn r(&self, r: uint) -> Vector4<S> {
|
||||
Vector4::new(self.cr(0, r),
|
||||
self.cr(1, r),
|
||||
self.cr(2, r),
|
||||
self.cr(3, r))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn swap_r(&mut self, a: uint, b: uint) {
|
||||
self.mut_c(0).swap_i(a, b);
|
||||
self.mut_c(1).swap_i(a, b);
|
||||
self.mut_c(2).swap_i(a, b);
|
||||
self.mut_c(3).swap_i(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Matrix<S, Vector2<S>> for Matrix2<S> {
|
||||
#[inline]
|
||||
fn mul_s(&self, s: S) -> Matrix2<S> {
|
||||
Matrix2::from_cols(self.c(0).mul_s(s),
|
||||
self.c(1).mul_s(s))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_s(&self, s: S) -> Matrix2<S> {
|
||||
Matrix2::from_cols(self.c(0).div_s(s),
|
||||
self.c(1).div_s(s))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rem_s(&self, s: S) -> Matrix2<S> {
|
||||
Matrix2::from_cols(self.c(0).rem_s(s),
|
||||
self.c(1).rem_s(s))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_m(&self, m: &Matrix2<S>) -> Matrix2<S> {
|
||||
Matrix2::from_cols(self.c(0).add_v(m.c(0)),
|
||||
self.c(1).add_v(m.c(1)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_m(&self, m: &Matrix2<S>) -> Matrix2<S> {
|
||||
Matrix2::from_cols(self.c(0).sub_v(m.c(0)),
|
||||
self.c(1).sub_v(m.c(1)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mul_v(&self, v: &Vector2<S>) -> Vector2<S> {
|
||||
Vector2::new(self.r(0).dot(v),
|
||||
self.r(1).dot(v))
|
||||
}
|
||||
|
||||
fn mul_m(&self, other: &Matrix2<S>) -> Matrix2<S> {
|
||||
Matrix2::new(self.r(0).dot(other.c(0)), self.r(1).dot(other.c(0)),
|
||||
self.r(0).dot(other.c(1)), self.r(1).dot(other.c(1)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn neg_self(&mut self) {
|
||||
self.mut_c(0).neg_self();
|
||||
self.mut_c(1).neg_self();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mul_self_s(&mut self, s: S) {
|
||||
self.mut_c(0).mul_self_s(s);
|
||||
self.mut_c(1).mul_self_s(s);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_self_s(&mut self, s: S) {
|
||||
self.mut_c(0).div_self_s(s);
|
||||
self.mut_c(1).div_self_s(s);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rem_self_s(&mut self, s: S) {
|
||||
self.mut_c(0).rem_self_s(s);
|
||||
self.mut_c(1).rem_self_s(s);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_self_m(&mut self, m: &Matrix2<S>) {
|
||||
self.mut_c(0).add_self_v(m.c(0));
|
||||
self.mut_c(1).add_self_v(m.c(1));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_self_m(&mut self, m: &Matrix2<S>) {
|
||||
self.mut_c(0).sub_self_v(m.c(0));
|
||||
self.mut_c(1).sub_self_v(m.c(1));
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Matrix2<S> {
|
||||
Matrix2::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(),
|
||||
self.cr(0, 1).clone(), self.cr(1, 1).clone())
|
||||
|
@ -462,7 +569,13 @@ for Matrix2<S>
|
|||
|
||||
#[inline]
|
||||
fn determinant(&self) -> S {
|
||||
*self.cr(0, 0) * *self.cr(1, 1) - *self.cr(1, 0) * *self.cr(0, 1)
|
||||
self.cr(0, 0) * self.cr(1, 1) - self.cr(1, 0) * self.cr(0, 1)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn diagonal(&self) -> Vector2<S> {
|
||||
Vector2::new(self.cr(0, 0),
|
||||
self.cr(1, 1))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -471,8 +584,8 @@ for Matrix2<S>
|
|||
if det.approx_eq(&zero()) {
|
||||
None
|
||||
} else {
|
||||
Some(Matrix2::new( *self.cr(1, 1) / det, -*self.cr(0, 1) / det,
|
||||
-*self.cr(1, 0) / det, *self.cr(0, 0) / det))
|
||||
Some(Matrix2::new( self.cr(1, 1) / det, -self.cr(0, 1) / det,
|
||||
-self.cr(1, 0) / det, self.cr(0, 0) / det))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -485,21 +598,102 @@ for Matrix2<S>
|
|||
|
||||
#[inline]
|
||||
fn is_symmetric(&self) -> bool {
|
||||
self.cr(0, 1).approx_eq(self.cr(1, 0)) &&
|
||||
self.cr(1, 0).approx_eq(self.cr(0, 1))
|
||||
self.cr(0, 1).approx_eq(&self.cr(1, 0)) &&
|
||||
self.cr(1, 0).approx_eq(&self.cr(0, 1))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat>
|
||||
Matrix<S, [Vector3<S>, ..3], Vector3<S>, [S, ..3]>
|
||||
for Matrix3<S>
|
||||
{
|
||||
impl<S: BaseFloat> Matrix<S, Vector3<S>> for Matrix3<S> {
|
||||
#[inline]
|
||||
fn mul_s(&self, s: S) -> Matrix3<S> {
|
||||
Matrix3::from_cols(self.c(0).mul_s(s),
|
||||
self.c(1).mul_s(s),
|
||||
self.c(2).mul_s(s))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_s(&self, s: S) -> Matrix3<S> {
|
||||
Matrix3::from_cols(self.c(0).div_s(s),
|
||||
self.c(1).div_s(s),
|
||||
self.c(2).div_s(s))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rem_s(&self, s: S) -> Matrix3<S> {
|
||||
Matrix3::from_cols(self.c(0).rem_s(s),
|
||||
self.c(1).rem_s(s),
|
||||
self.c(2).rem_s(s))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_m(&self, m: &Matrix3<S>) -> Matrix3<S> {
|
||||
Matrix3::from_cols(self.c(0).add_v(m.c(0)),
|
||||
self.c(1).add_v(m.c(1)),
|
||||
self.c(2).add_v(m.c(2)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_m(&self, m: &Matrix3<S>) -> Matrix3<S> {
|
||||
Matrix3::from_cols(self.c(0).sub_v(m.c(0)),
|
||||
self.c(1).sub_v(m.c(1)),
|
||||
self.c(2).sub_v(m.c(2)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mul_v(&self, v: &Vector3<S>) -> Vector3<S> {
|
||||
Vector3::new(self.r(0).dot(v),
|
||||
self.r(1).dot(v),
|
||||
self.r(2).dot(v))
|
||||
}
|
||||
|
||||
fn mul_m(&self, other: &Matrix3<S>) -> Matrix3<S> {
|
||||
Matrix3::new(self.r(0).dot(other.c(0)),self.r(1).dot(other.c(0)),self.r(2).dot(other.c(0)),
|
||||
self.r(0).dot(other.c(1)),self.r(1).dot(other.c(1)),self.r(2).dot(other.c(1)),
|
||||
self.r(0).dot(other.c(2)),self.r(1).dot(other.c(2)),self.r(2).dot(other.c(2)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn neg_self(&mut self) {
|
||||
self.mut_c(0).neg_self();
|
||||
self.mut_c(1).neg_self();
|
||||
self.mut_c(2).neg_self();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mul_self_s(&mut self, s: S) {
|
||||
self.mut_c(0).mul_self_s(s);
|
||||
self.mut_c(1).mul_self_s(s);
|
||||
self.mut_c(2).mul_self_s(s);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_self_s(&mut self, s: S) {
|
||||
self.mut_c(0).div_self_s(s);
|
||||
self.mut_c(1).div_self_s(s);
|
||||
self.mut_c(2).div_self_s(s);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rem_self_s(&mut self, s: S) {
|
||||
self.mut_c(0).rem_self_s(s);
|
||||
self.mut_c(1).rem_self_s(s);
|
||||
self.mut_c(2).rem_self_s(s);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_self_m(&mut self, m: &Matrix3<S>) {
|
||||
self.mut_c(0).add_self_v(m.c(0));
|
||||
self.mut_c(1).add_self_v(m.c(1));
|
||||
self.mut_c(2).add_self_v(m.c(2));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_self_m(&mut self, m: &Matrix3<S>) {
|
||||
self.mut_c(0).sub_self_v(m.c(0));
|
||||
self.mut_c(1).sub_self_v(m.c(1));
|
||||
self.mut_c(2).sub_self_v(m.c(2));
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Matrix3<S> {
|
||||
Matrix3::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(),
|
||||
self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(),
|
||||
|
@ -514,9 +708,16 @@ for Matrix3<S>
|
|||
}
|
||||
|
||||
fn determinant(&self) -> S {
|
||||
*self.cr(0, 0) * (*self.cr(1, 1) * *self.cr(2, 2) - *self.cr(2, 1) * *self.cr(1, 2)) -
|
||||
*self.cr(1, 0) * (*self.cr(0, 1) * *self.cr(2, 2) - *self.cr(2, 1) * *self.cr(0, 2)) +
|
||||
*self.cr(2, 0) * (*self.cr(0, 1) * *self.cr(1, 2) - *self.cr(1, 1) * *self.cr(0, 2))
|
||||
self.cr(0, 0) * (self.cr(1, 1) * self.cr(2, 2) - self.cr(2, 1) * self.cr(1, 2)) -
|
||||
self.cr(1, 0) * (self.cr(0, 1) * self.cr(2, 2) - self.cr(2, 1) * self.cr(0, 2)) +
|
||||
self.cr(2, 0) * (self.cr(0, 1) * self.cr(1, 2) - self.cr(1, 1) * self.cr(0, 2))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn diagonal(&self) -> Vector3<S> {
|
||||
Vector3::new(self.cr(0, 0),
|
||||
self.cr(1, 1),
|
||||
self.cr(2, 2))
|
||||
}
|
||||
|
||||
fn invert(&self) -> Option<Matrix3<S>> {
|
||||
|
@ -540,14 +741,14 @@ for Matrix3<S>
|
|||
}
|
||||
|
||||
fn is_symmetric(&self) -> bool {
|
||||
self.cr(0, 1).approx_eq(self.cr(1, 0)) &&
|
||||
self.cr(0, 2).approx_eq(self.cr(2, 0)) &&
|
||||
self.cr(0, 1).approx_eq(&self.cr(1, 0)) &&
|
||||
self.cr(0, 2).approx_eq(&self.cr(2, 0)) &&
|
||||
|
||||
self.cr(1, 0).approx_eq(self.cr(0, 1)) &&
|
||||
self.cr(1, 2).approx_eq(self.cr(2, 1)) &&
|
||||
self.cr(1, 0).approx_eq(&self.cr(0, 1)) &&
|
||||
self.cr(1, 2).approx_eq(&self.cr(2, 1)) &&
|
||||
|
||||
self.cr(2, 0).approx_eq(self.cr(0, 2)) &&
|
||||
self.cr(2, 1).approx_eq(self.cr(1, 2))
|
||||
self.cr(2, 0).approx_eq(&self.cr(0, 2)) &&
|
||||
self.cr(2, 1).approx_eq(&self.cr(1, 2))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -557,16 +758,61 @@ for Matrix3<S>
|
|||
// around ~4 times.
|
||||
macro_rules! dot_matrix4(
|
||||
($A:expr, $B:expr, $I:expr, $J:expr) => (
|
||||
(*$A.cr(0, $I)) * (*$B.cr($J, 0)) +
|
||||
(*$A.cr(1, $I)) * (*$B.cr($J, 1)) +
|
||||
(*$A.cr(2, $I)) * (*$B.cr($J, 2)) +
|
||||
(*$A.cr(3, $I)) * (*$B.cr($J, 3))
|
||||
($A.cr(0, $I)) * ($B.cr($J, 0)) +
|
||||
($A.cr(1, $I)) * ($B.cr($J, 1)) +
|
||||
($A.cr(2, $I)) * ($B.cr($J, 2)) +
|
||||
($A.cr(3, $I)) * ($B.cr($J, 3))
|
||||
))
|
||||
|
||||
impl<S: BaseFloat>
|
||||
Matrix<S, [Vector4<S>, ..4], Vector4<S>, [S, ..4]>
|
||||
for Matrix4<S>
|
||||
{
|
||||
impl<S: BaseFloat> Matrix<S, Vector4<S>> for Matrix4<S> {
|
||||
#[inline]
|
||||
fn mul_s(&self, s: S) -> Matrix4<S> {
|
||||
Matrix4::from_cols(self.c(0).mul_s(s),
|
||||
self.c(1).mul_s(s),
|
||||
self.c(2).mul_s(s),
|
||||
self.c(3).mul_s(s))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_s(&self, s: S) -> Matrix4<S> {
|
||||
Matrix4::from_cols(self.c(0).div_s(s),
|
||||
self.c(1).div_s(s),
|
||||
self.c(2).div_s(s),
|
||||
self.c(3).div_s(s))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rem_s(&self, s: S) -> Matrix4<S> {
|
||||
Matrix4::from_cols(self.c(0).rem_s(s),
|
||||
self.c(1).rem_s(s),
|
||||
self.c(2).rem_s(s),
|
||||
self.c(3).rem_s(s))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_m(&self, m: &Matrix4<S>) -> Matrix4<S> {
|
||||
Matrix4::from_cols(self.c(0).add_v(m.c(0)),
|
||||
self.c(1).add_v(m.c(1)),
|
||||
self.c(2).add_v(m.c(2)),
|
||||
self.c(3).add_v(m.c(3)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_m(&self, m: &Matrix4<S>) -> Matrix4<S> {
|
||||
Matrix4::from_cols(self.c(0).sub_v(m.c(0)),
|
||||
self.c(1).sub_v(m.c(1)),
|
||||
self.c(2).sub_v(m.c(2)),
|
||||
self.c(3).sub_v(m.c(3)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mul_v(&self, v: &Vector4<S>) -> Vector4<S> {
|
||||
Vector4::new(self.r(0).dot(v),
|
||||
self.r(1).dot(v),
|
||||
self.r(2).dot(v),
|
||||
self.r(3).dot(v))
|
||||
}
|
||||
|
||||
fn mul_m(&self, other: &Matrix4<S>) -> Matrix4<S> {
|
||||
Matrix4::new(dot_matrix4!(self, other, 0, 0), dot_matrix4!(self, other, 1, 0), dot_matrix4!(self, other, 2, 0), dot_matrix4!(self, other, 3, 0),
|
||||
dot_matrix4!(self, other, 0, 1), dot_matrix4!(self, other, 1, 1), dot_matrix4!(self, other, 2, 1), dot_matrix4!(self, other, 3, 1),
|
||||
|
@ -574,6 +820,54 @@ for Matrix4<S>
|
|||
dot_matrix4!(self, other, 0, 3), dot_matrix4!(self, other, 1, 3), dot_matrix4!(self, other, 2, 3), dot_matrix4!(self, other, 3, 3))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn neg_self(&mut self) {
|
||||
self.mut_c(0).neg_self();
|
||||
self.mut_c(1).neg_self();
|
||||
self.mut_c(2).neg_self();
|
||||
self.mut_c(3).neg_self();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mul_self_s(&mut self, s: S) {
|
||||
self.mut_c(0).mul_self_s(s);
|
||||
self.mut_c(1).mul_self_s(s);
|
||||
self.mut_c(2).mul_self_s(s);
|
||||
self.mut_c(3).mul_self_s(s);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_self_s(&mut self, s: S) {
|
||||
self.mut_c(0).div_self_s(s);
|
||||
self.mut_c(1).div_self_s(s);
|
||||
self.mut_c(2).div_self_s(s);
|
||||
self.mut_c(3).div_self_s(s);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rem_self_s(&mut self, s: S) {
|
||||
self.mut_c(0).rem_self_s(s);
|
||||
self.mut_c(1).rem_self_s(s);
|
||||
self.mut_c(2).rem_self_s(s);
|
||||
self.mut_c(3).rem_self_s(s);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_self_m(&mut self, m: &Matrix4<S>) {
|
||||
self.mut_c(0).add_self_v(m.c(0));
|
||||
self.mut_c(1).add_self_v(m.c(1));
|
||||
self.mut_c(2).add_self_v(m.c(2));
|
||||
self.mut_c(3).add_self_v(m.c(3));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_self_m(&mut self, m: &Matrix4<S>) {
|
||||
self.mut_c(0).sub_self_v(m.c(0));
|
||||
self.mut_c(1).sub_self_v(m.c(1));
|
||||
self.mut_c(2).sub_self_v(m.c(2));
|
||||
self.mut_c(3).sub_self_v(m.c(3));
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Matrix4<S> {
|
||||
Matrix4::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(), self.cr(3, 0).clone(),
|
||||
self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(), self.cr(3, 1).clone(),
|
||||
|
@ -604,10 +898,18 @@ for Matrix4<S>
|
|||
self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(2, 2).clone(),
|
||||
self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone());
|
||||
|
||||
*self.cr(0, 0) * m0.determinant() -
|
||||
*self.cr(1, 0) * m1.determinant() +
|
||||
*self.cr(2, 0) * m2.determinant() -
|
||||
*self.cr(3, 0) * m3.determinant()
|
||||
self.cr(0, 0) * m0.determinant() -
|
||||
self.cr(1, 0) * m1.determinant() +
|
||||
self.cr(2, 0) * m2.determinant() -
|
||||
self.cr(3, 0) * m3.determinant()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn diagonal(&self) -> Vector4<S> {
|
||||
Vector4::new(self.cr(0, 0),
|
||||
self.cr(1, 1),
|
||||
self.cr(2, 2),
|
||||
self.cr(3, 3))
|
||||
}
|
||||
|
||||
fn invert(&self) -> Option<Matrix4<S>> {
|
||||
|
@ -673,21 +975,48 @@ for Matrix4<S>
|
|||
}
|
||||
|
||||
fn is_symmetric(&self) -> bool {
|
||||
self.cr(0, 1).approx_eq(self.cr(1, 0)) &&
|
||||
self.cr(0, 2).approx_eq(self.cr(2, 0)) &&
|
||||
self.cr(0, 3).approx_eq(self.cr(3, 0)) &&
|
||||
self.cr(0, 1).approx_eq(&self.cr(1, 0)) &&
|
||||
self.cr(0, 2).approx_eq(&self.cr(2, 0)) &&
|
||||
self.cr(0, 3).approx_eq(&self.cr(3, 0)) &&
|
||||
|
||||
self.cr(1, 0).approx_eq(self.cr(0, 1)) &&
|
||||
self.cr(1, 2).approx_eq(self.cr(2, 1)) &&
|
||||
self.cr(1, 3).approx_eq(self.cr(3, 1)) &&
|
||||
self.cr(1, 0).approx_eq(&self.cr(0, 1)) &&
|
||||
self.cr(1, 2).approx_eq(&self.cr(2, 1)) &&
|
||||
self.cr(1, 3).approx_eq(&self.cr(3, 1)) &&
|
||||
|
||||
self.cr(2, 0).approx_eq(self.cr(0, 2)) &&
|
||||
self.cr(2, 1).approx_eq(self.cr(1, 2)) &&
|
||||
self.cr(2, 3).approx_eq(self.cr(3, 2)) &&
|
||||
self.cr(2, 0).approx_eq(&self.cr(0, 2)) &&
|
||||
self.cr(2, 1).approx_eq(&self.cr(1, 2)) &&
|
||||
self.cr(2, 3).approx_eq(&self.cr(3, 2)) &&
|
||||
|
||||
self.cr(3, 0).approx_eq(self.cr(0, 3)) &&
|
||||
self.cr(3, 1).approx_eq(self.cr(1, 3)) &&
|
||||
self.cr(3, 2).approx_eq(self.cr(2, 3))
|
||||
self.cr(3, 0).approx_eq(&self.cr(0, 3)) &&
|
||||
self.cr(3, 1).approx_eq(&self.cr(1, 3)) &&
|
||||
self.cr(3, 2).approx_eq(&self.cr(2, 3))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> ApproxEq<S> for Matrix2<S> {
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &Matrix2<S>, epsilon: &S) -> bool {
|
||||
self.c(0).approx_eq_eps(other.c(0), epsilon) &&
|
||||
self.c(1).approx_eq_eps(other.c(1), epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> ApproxEq<S> for Matrix3<S> {
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &Matrix3<S>, epsilon: &S) -> bool {
|
||||
self.c(0).approx_eq_eps(other.c(0), epsilon) &&
|
||||
self.c(1).approx_eq_eps(other.c(1), epsilon) &&
|
||||
self.c(2).approx_eq_eps(other.c(2), epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> ApproxEq<S> for Matrix4<S> {
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &Matrix4<S>, epsilon: &S) -> bool {
|
||||
self.c(0).approx_eq_eps(other.c(0), epsilon) &&
|
||||
self.c(1).approx_eq_eps(other.c(1), epsilon) &&
|
||||
self.c(2).approx_eq_eps(other.c(2), epsilon) &&
|
||||
self.c(3).approx_eq_eps(other.c(3), epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -711,8 +1040,7 @@ pub trait ToMatrix4<S: BaseNum> {
|
|||
fn to_matrix4(&self) -> Matrix4<S>;
|
||||
}
|
||||
|
||||
impl<S: BaseFloat>
|
||||
ToMatrix3<S> for Matrix2<S> {
|
||||
impl<S: BaseFloat> ToMatrix3<S> for Matrix2<S> {
|
||||
/// Clone the elements of a 2-dimensional matrix into the top-left corner
|
||||
/// of a 3-dimensional identity matrix.
|
||||
fn to_matrix3(&self) -> Matrix3<S> {
|
||||
|
@ -722,8 +1050,7 @@ ToMatrix3<S> for Matrix2<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat>
|
||||
ToMatrix4<S> for Matrix2<S> {
|
||||
impl<S: BaseFloat> ToMatrix4<S> for Matrix2<S> {
|
||||
/// Clone the elements of a 2-dimensional matrix into the top-left corner
|
||||
/// of a 4-dimensional identity matrix.
|
||||
fn to_matrix4(&self) -> Matrix4<S> {
|
||||
|
@ -734,8 +1061,7 @@ ToMatrix4<S> for Matrix2<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat>
|
||||
ToMatrix4<S> for Matrix3<S> {
|
||||
impl<S: BaseFloat> ToMatrix4<S> for Matrix3<S> {
|
||||
/// Clone the elements of a 3-dimensional matrix into the top-left corner
|
||||
/// of a 4-dimensional identity matrix.
|
||||
fn to_matrix4(&self) -> Matrix4<S> {
|
||||
|
@ -746,8 +1072,7 @@ ToMatrix4<S> for Matrix3<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat>
|
||||
ToQuaternion<S> for Matrix3<S> {
|
||||
impl<S: BaseFloat> ToQuaternion<S> for Matrix3<S> {
|
||||
/// Convert the matrix to a quaternion
|
||||
fn to_quaternion(&self) -> Quaternion<S> {
|
||||
// http://www.cs.ucr.edu/~vbz/resources/quatut.pdf
|
||||
|
@ -758,43 +1083,43 @@ ToQuaternion<S> for Matrix3<S> {
|
|||
let s = (one::<S>() + trace).sqrt();
|
||||
let w = half * s;
|
||||
let s = half / s;
|
||||
let x = (*self.cr(1, 2) - *self.cr(2, 1)) * s;
|
||||
let y = (*self.cr(2, 0) - *self.cr(0, 2)) * s;
|
||||
let z = (*self.cr(0, 1) - *self.cr(1, 0)) * s;
|
||||
let x = (self.cr(1, 2) - self.cr(2, 1)) * s;
|
||||
let y = (self.cr(2, 0) - self.cr(0, 2)) * s;
|
||||
let z = (self.cr(0, 1) - self.cr(1, 0)) * s;
|
||||
Quaternion::new(w, x, y, z)
|
||||
}
|
||||
() if (*self.cr(0, 0) > *self.cr(1, 1)) && (*self.cr(0, 0) > *self.cr(2, 2)) => {
|
||||
let s = (half + (*self.cr(0, 0) - *self.cr(1, 1) - *self.cr(2, 2))).sqrt();
|
||||
() if (self.cr(0, 0) > self.cr(1, 1)) && (self.cr(0, 0) > self.cr(2, 2)) => {
|
||||
let s = (half + (self.cr(0, 0) - self.cr(1, 1) - self.cr(2, 2))).sqrt();
|
||||
let w = half * s;
|
||||
let s = half / s;
|
||||
let x = (*self.cr(0, 1) - *self.cr(1, 0)) * s;
|
||||
let y = (*self.cr(2, 0) - *self.cr(0, 2)) * s;
|
||||
let z = (*self.cr(1, 2) - *self.cr(2, 1)) * s;
|
||||
let x = (self.cr(0, 1) - self.cr(1, 0)) * s;
|
||||
let y = (self.cr(2, 0) - self.cr(0, 2)) * s;
|
||||
let z = (self.cr(1, 2) - self.cr(2, 1)) * s;
|
||||
Quaternion::new(w, x, y, z)
|
||||
}
|
||||
() if *self.cr(1, 1) > *self.cr(2, 2) => {
|
||||
let s = (half + (*self.cr(1, 1) - *self.cr(0, 0) - *self.cr(2, 2))).sqrt();
|
||||
() if self.cr(1, 1) > self.cr(2, 2) => {
|
||||
let s = (half + (self.cr(1, 1) - self.cr(0, 0) - self.cr(2, 2))).sqrt();
|
||||
let w = half * s;
|
||||
let s = half / s;
|
||||
let x = (*self.cr(0, 1) - *self.cr(1, 0)) * s;
|
||||
let y = (*self.cr(1, 2) - *self.cr(2, 1)) * s;
|
||||
let z = (*self.cr(2, 0) - *self.cr(0, 2)) * s;
|
||||
let x = (self.cr(0, 1) - self.cr(1, 0)) * s;
|
||||
let y = (self.cr(1, 2) - self.cr(2, 1)) * s;
|
||||
let z = (self.cr(2, 0) - self.cr(0, 2)) * s;
|
||||
Quaternion::new(w, x, y, z)
|
||||
}
|
||||
() => {
|
||||
let s = (half + (*self.cr(2, 2) - *self.cr(0, 0) - *self.cr(1, 1))).sqrt();
|
||||
let s = (half + (self.cr(2, 2) - self.cr(0, 0) - self.cr(1, 1))).sqrt();
|
||||
let w = half * s;
|
||||
let s = half / s;
|
||||
let x = (*self.cr(2, 0) - *self.cr(0, 2)) * s;
|
||||
let y = (*self.cr(1, 2) - *self.cr(2, 1)) * s;
|
||||
let z = (*self.cr(0, 1) - *self.cr(1, 0)) * s;
|
||||
let x = (self.cr(2, 0) - self.cr(0, 2)) * s;
|
||||
let y = (self.cr(1, 2) - self.cr(2, 1)) * s;
|
||||
let z = (self.cr(0, 1) - self.cr(1, 0)) * s;
|
||||
Quaternion::new(w, x, y, z)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> fmt::Show for Matrix2<S> {
|
||||
impl<S: BaseNum> fmt::Show for Matrix2<S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "[[{}, {}], [{}, {}]]",
|
||||
self.cr(0, 0), self.cr(0, 1),
|
||||
|
@ -802,7 +1127,7 @@ impl<S: BaseFloat> fmt::Show for Matrix2<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> fmt::Show for Matrix3<S> {
|
||||
impl<S: BaseNum> fmt::Show for Matrix3<S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "[[{}, {}, {}], [{}, {}, {}], [{}, {}, {}]]",
|
||||
self.cr(0, 0), self.cr(0, 1), self.cr(0, 2),
|
||||
|
@ -811,7 +1136,7 @@ impl<S: BaseFloat> fmt::Show for Matrix3<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> fmt::Show for Matrix4<S> {
|
||||
impl<S: BaseNum> fmt::Show for Matrix4<S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "[[{}, {}, {}, {}], [{}, {}, {}, {}], [{}, {}, {}, {}], [{}, {}, {}, {}]]",
|
||||
self.cr(0, 0), self.cr(0, 1), self.cr(0, 2), self.cr(0, 3),
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
//! not have a fixed position.
|
||||
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::num::{one, zero};
|
||||
|
||||
use array::*;
|
||||
use num::BaseNum;
|
||||
use approx::ApproxEq;
|
||||
use array::Array1;
|
||||
use num::{BaseNum, BaseFloat};
|
||||
use vector::*;
|
||||
|
||||
/// A point in 2-dimensional space.
|
||||
|
@ -61,56 +63,294 @@ impl<S: BaseNum> Point3<S> {
|
|||
}
|
||||
|
||||
/// Specifies the numeric operations for point types.
|
||||
pub trait Point
|
||||
<
|
||||
S: BaseNum,
|
||||
V: Vector<S, Slice>,
|
||||
Slice
|
||||
>
|
||||
: Array<S, Slice>
|
||||
{
|
||||
pub trait Point<S: BaseNum, V: Vector<S>>: Array1<S> + Clone {
|
||||
/// Create a point at the origin.
|
||||
#[inline] fn origin() -> Self{ build(|_i| zero::<S>()) }
|
||||
fn origin() -> Self;
|
||||
|
||||
/// Create a point from a vector.
|
||||
#[inline] fn from_vec(v: &V) -> Self { build(|i| v.i(i).clone()) }
|
||||
fn from_vec(v: &V) -> Self;
|
||||
/// Convert a point to a vector.
|
||||
#[inline] fn to_vec(&self) -> V { build(|i| self.i(i).clone()) }
|
||||
fn to_vec(&self) -> V;
|
||||
|
||||
/// Multiply each component by a scalar, returning the new point.
|
||||
#[inline] fn mul_s(&self, s: S) -> Self { build(|i| self.i(i).mul(&s)) }
|
||||
fn mul_s(&self, s: S) -> Self;
|
||||
/// Divide each component by a scalar, returning the new point.
|
||||
#[inline] fn div_s(&self, s: S) -> Self { build(|i| self.i(i).div(&s)) }
|
||||
fn div_s(&self, s: S) -> Self;
|
||||
/// Subtract a scalar from each component, returning the new point.
|
||||
#[inline] fn rem_s(&self, s: S) -> Self { build(|i| self.i(i).rem(&s)) }
|
||||
fn rem_s(&self, s: S) -> Self;
|
||||
|
||||
/// Add a vector to this point, returning the new point.
|
||||
#[inline] fn add_v(&self, other: &V) -> Self { build(|i| self.i(i).add(other.i(i))) }
|
||||
fn add_v(&self, v: &V) -> Self;
|
||||
/// Subtract another point from this one, returning a new vector.
|
||||
#[inline] fn sub_p(&self, other: &Self) -> V { build(|i| self.i(i).sub(other.i(i))) }
|
||||
fn sub_p(&self, p: &Self) -> V;
|
||||
|
||||
/// Multiply each component by a scalar, in-place.
|
||||
#[inline] fn mul_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.mul(&s)) }
|
||||
fn mul_self_s(&mut self, s: S);
|
||||
/// Divide each component by a scalar, in-place.
|
||||
#[inline] fn div_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.div(&s)) }
|
||||
fn div_self_s(&mut self, s: S);
|
||||
/// Take the remainder of each component by a scalar, in-place.
|
||||
#[inline] fn rem_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.rem(&s)) }
|
||||
fn rem_self_s(&mut self, s: S);
|
||||
|
||||
/// Add a vector to this point, in-place.
|
||||
#[inline] fn add_self_v(&mut self, other: &V) { self.each_mut(|i, x| *x = x.add(other.i(i))) }
|
||||
fn add_self_v(&mut self, v: &V);
|
||||
|
||||
/// This is a weird one, but its useful for plane calculations.
|
||||
fn dot(&self, v: &V) -> S;
|
||||
|
||||
fn min(&self, p: &Self) -> Self;
|
||||
|
||||
fn max(&self, p: &Self) -> Self;
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Array1<S> for Point2<S> {
|
||||
#[inline]
|
||||
fn dot(&self, v: &V) -> S {
|
||||
build::<S, Slice, V>(|i| self.i(i).mul(v.i(i))).comp_add()
|
||||
fn ptr<'a>(&'a self) -> &'a S { &self.x }
|
||||
|
||||
#[inline]
|
||||
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x }
|
||||
|
||||
#[inline]
|
||||
fn i(&self, i: uint) -> S {
|
||||
let slice: &[S, ..2] = unsafe { mem::transmute(self) };
|
||||
slice[i]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut S {
|
||||
let slice: &'a mut [S, ..2] = unsafe { mem::transmute(self) };
|
||||
&'a mut slice[i]
|
||||
}
|
||||
}
|
||||
|
||||
array!(impl<S> Point2<S> -> [S, ..2] _2)
|
||||
array!(impl<S> Point3<S> -> [S, ..3] _3)
|
||||
impl<S: BaseNum> Point<S, Vector2<S>> for Point2<S> {
|
||||
#[inline]
|
||||
fn origin() -> Point2<S> {
|
||||
Point2::new(zero(), zero())
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Point<S, Vector2<S>, [S, ..2]> for Point2<S> {}
|
||||
impl<S: BaseNum> Point<S, Vector3<S>, [S, ..3]> for Point3<S> {}
|
||||
#[inline]
|
||||
fn from_vec(v: &Vector2<S>) -> Point2<S> {
|
||||
Point2::new(v.x, v.y)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_vec(&self) -> Vector2<S> {
|
||||
Vector2::new(self.x,
|
||||
self.y)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mul_s(&self, s: S) -> Point2<S> {
|
||||
Point2::new(self.x * s,
|
||||
self.y * s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_s(&self, s: S) -> Point2<S> {
|
||||
Point2::new(self.x / s,
|
||||
self.y / s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rem_s(&self, s: S) -> Point2<S> {
|
||||
Point2::new(self.x % s,
|
||||
self.y % s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_v(&self, v: &Vector2<S>) -> Point2<S> {
|
||||
Point2::new(self.x + v.x,
|
||||
self.y + v.y)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_p(&self, p: &Point2<S>) -> Vector2<S> {
|
||||
Vector2::new(self.x - p.x,
|
||||
self.y - p.y)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mul_self_s(&mut self, s: S) {
|
||||
self.x = self.x * s;
|
||||
self.y = self.y * s;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_self_s(&mut self, s: S) {
|
||||
self.x = self.x / s;
|
||||
self.y = self.y / s;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rem_self_s(&mut self, s: S) {
|
||||
self.x = self.x % s;
|
||||
self.y = self.y % s;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_self_v(&mut self, v: &Vector2<S>) {
|
||||
self.x = self.x + v.x;
|
||||
self.y = self.y + v.y;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn dot(&self, v: &Vector2<S>) -> S {
|
||||
self.x * v.x +
|
||||
self.y * v.y
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min(&self, p: &Point2<S>) -> Point2<S> {
|
||||
Point2::new(self.x.partial_min(p.x),
|
||||
self.y.partial_min(p.y))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max(&self, p: &Point2<S>) -> Point2<S> {
|
||||
Point2::new(self.x.partial_max(p.x),
|
||||
self.y.partial_max(p.y))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> ApproxEq<S> for Point2<S> {
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &Point2<S>, epsilon: &S) -> bool {
|
||||
self.x.approx_eq_eps(&other.x, epsilon) &&
|
||||
self.y.approx_eq_eps(&other.y, epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Array1<S> for Point3<S> {
|
||||
#[inline]
|
||||
fn ptr<'a>(&'a self) -> &'a S { &self.x }
|
||||
|
||||
#[inline]
|
||||
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x }
|
||||
|
||||
#[inline]
|
||||
fn i(&self, i: uint) -> S {
|
||||
let slice: &[S, ..3] = unsafe { mem::transmute(self) };
|
||||
slice[i]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut S {
|
||||
let slice: &'a mut [S, ..3] = unsafe { mem::transmute(self) };
|
||||
&'a mut slice[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Point<S, Vector3<S>> for Point3<S> {
|
||||
#[inline]
|
||||
fn origin() -> Point3<S> {
|
||||
Point3::new(zero(), zero(), zero())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_vec(v: &Vector3<S>) -> Point3<S> {
|
||||
Point3::new(v.x, v.y, v.z)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_vec(&self) -> Vector3<S> {
|
||||
Vector3::new(self.x,
|
||||
self.y,
|
||||
self.z)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mul_s(&self, s: S) -> Point3<S> {
|
||||
Point3::new(self.x * s,
|
||||
self.y * s,
|
||||
self.z * s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_s(&self, s: S) -> Point3<S> {
|
||||
Point3::new(self.x / s,
|
||||
self.y / s,
|
||||
self.z / s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rem_s(&self, s: S) -> Point3<S> {
|
||||
Point3::new(self.x % s,
|
||||
self.y % s,
|
||||
self.z % s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_v(&self, v: &Vector3<S>) -> Point3<S> {
|
||||
Point3::new(self.x + v.x,
|
||||
self.y + v.y,
|
||||
self.z + v.z)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_p(&self, p: &Point3<S>) -> Vector3<S> {
|
||||
Vector3::new(self.x - p.x,
|
||||
self.y - p.y,
|
||||
self.z - p.z)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mul_self_s(&mut self, s: S) {
|
||||
self.x = self.x * s;
|
||||
self.y = self.y * s;
|
||||
self.z = self.z * s;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_self_s(&mut self, s: S) {
|
||||
self.x = self.x / s;
|
||||
self.y = self.y / s;
|
||||
self.z = self.z / s;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rem_self_s(&mut self, s: S) {
|
||||
self.x = self.x % s;
|
||||
self.y = self.y % s;
|
||||
self.z = self.z % s;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_self_v(&mut self, v: &Vector3<S>) {
|
||||
self.x = self.x + v.x;
|
||||
self.y = self.y + v.y;
|
||||
self.z = self.z + v.z;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn dot(&self, v: &Vector3<S>) -> S {
|
||||
self.x * v.x +
|
||||
self.y * v.y +
|
||||
self.z * v.z
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min(&self, p: &Point3<S>) -> Point3<S> {
|
||||
Point3::new(self.x.partial_min(p.x),
|
||||
self.y.partial_min(p.y),
|
||||
self.z.partial_min(p.z))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max(&self, p: &Point3<S>) -> Point3<S> {
|
||||
Point3::new(self.x.partial_max(p.x),
|
||||
self.y.partial_max(p.y),
|
||||
self.z.partial_max(p.z))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> ApproxEq<S> for Point3<S> {
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &Point3<S>, epsilon: &S) -> bool {
|
||||
self.x.approx_eq_eps(&other.x, epsilon) &&
|
||||
self.y.approx_eq_eps(&other.y, epsilon) &&
|
||||
self.z.approx_eq_eps(&other.z, epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> fmt::Show for Point2<S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use array::Array;
|
||||
use matrix::{Matrix2, Matrix3, Matrix4};
|
||||
use point::{Point2, Point3};
|
||||
use vector::{Vector2, Vector3, Vector4};
|
||||
|
||||
pub trait Ptr<T> {
|
||||
fn ptr<'a>(&'a self) -> &'a T;
|
||||
}
|
||||
|
||||
impl<S: Clone> Ptr<S> for Vector2<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } }
|
||||
impl<S: Clone> Ptr<S> for Vector3<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } }
|
||||
impl<S: Clone> Ptr<S> for Vector4<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } }
|
||||
|
||||
impl<S: Clone> Ptr<S> for Point2<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } }
|
||||
impl<S: Clone> Ptr<S> for Point3<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0) } }
|
||||
|
||||
impl<S: Clone> Ptr<S> for Matrix2<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } }
|
||||
impl<S: Clone> Ptr<S> for Matrix3<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } }
|
||||
impl<S: Clone> Ptr<S> for Matrix4<S> { #[inline] fn ptr<'a>(&'a self) -> &'a S { self.i(0).i(0) } }
|
||||
|
||||
impl<'a, T, P: Ptr<T>> Ptr<T> for &'a [P] {
|
||||
#[inline] fn ptr<'a>(&'a self) -> &'a T { self[0].ptr() }
|
||||
}
|
|
@ -14,13 +14,15 @@
|
|||
// limitations under the License.
|
||||
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::num::{zero, one, cast};
|
||||
|
||||
use angle::{Angle, Rad, acos, sin, sin_cos};
|
||||
use array::{Array, build};
|
||||
use approx::ApproxEq;
|
||||
use array::Array1;
|
||||
use matrix::{Matrix3, ToMatrix3, ToMatrix4, Matrix4};
|
||||
use num::BaseFloat;
|
||||
use point::{Point3};
|
||||
use point::Point3;
|
||||
use rotation::{Rotation, Rotation3, Basis3, ToBasis3};
|
||||
use vector::{Vector3, Vector, EuclideanVector};
|
||||
|
||||
|
@ -29,14 +31,32 @@ use vector::{Vector3, Vector, EuclideanVector};
|
|||
#[deriving(Clone, Eq)]
|
||||
pub struct Quaternion<S> { pub s: S, pub v: Vector3<S> }
|
||||
|
||||
array!(impl<S> Quaternion<S> -> [S, ..4] _4)
|
||||
|
||||
/// Represents types which can be expressed as a quaternion.
|
||||
pub trait ToQuaternion<S: BaseFloat> {
|
||||
/// Convert this value to a quaternion.
|
||||
fn to_quaternion(&self) -> Quaternion<S>;
|
||||
}
|
||||
|
||||
impl<S: Copy> Array1<S> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn ptr<'a>(&'a self) -> &'a S { &self.s }
|
||||
|
||||
#[inline]
|
||||
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.s }
|
||||
|
||||
#[inline]
|
||||
fn i(&self, i: uint) -> S {
|
||||
let slice: &[S, ..4] = unsafe { mem::transmute(self) };
|
||||
slice[i]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut S {
|
||||
let slice: &'a mut [S, ..4] = unsafe { mem::transmute(self) };
|
||||
&'a mut slice[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Quaternion<S> {
|
||||
/// Construct a new quaternion from one scalar component and three
|
||||
/// imaginary components
|
||||
|
@ -85,13 +105,13 @@ impl<S: BaseFloat> Quaternion<S> {
|
|||
/// The sum of this quaternion and `other`
|
||||
#[inline]
|
||||
pub fn add_q(&self, other: &Quaternion<S>) -> Quaternion<S> {
|
||||
build(|i| self.i(i).add(other.i(i)))
|
||||
Quaternion::from_sv(self.s + other.s, self.v + other.v)
|
||||
}
|
||||
|
||||
/// The difference between this quaternion and `other`
|
||||
#[inline]
|
||||
pub fn sub_q(&self, other: &Quaternion<S>) -> Quaternion<S> {
|
||||
build(|i| self.i(i).add(other.i(i)))
|
||||
Quaternion::from_sv(self.s - other.s, self.v - other.v)
|
||||
}
|
||||
|
||||
/// The result of multipliplying the quaternion by `other`
|
||||
|
@ -105,37 +125,42 @@ impl<S: BaseFloat> Quaternion<S> {
|
|||
/// Multiply this quaternion by a scalar, in-place.
|
||||
#[inline]
|
||||
pub fn mul_self_s(&mut self, s: S) {
|
||||
self.each_mut(|_, x| *x = x.mul(&s))
|
||||
self.s = self.s * s;
|
||||
self.v.mul_self_s(s);
|
||||
}
|
||||
|
||||
/// Divide this quaternion by a scalar, in-place.
|
||||
#[inline]
|
||||
pub fn div_self_s(&mut self, s: S) {
|
||||
self.each_mut(|_, x| *x = x.div(&s))
|
||||
self.s = self.s / s;
|
||||
self.v.div_self_s(s);
|
||||
}
|
||||
|
||||
/// Add this quaternion by another, in-place.
|
||||
#[inline]
|
||||
pub fn add_self_q(&mut self, other: &Quaternion<S>) {
|
||||
self.each_mut(|i, x| *x = x.add(other.i(i)));
|
||||
pub fn add_self_q(&mut self, q: &Quaternion<S>) {
|
||||
self.s = self.s + q.s;
|
||||
self.v.add_self_v(&q.v);
|
||||
}
|
||||
|
||||
/// Subtract another quaternion from this one, in-place.
|
||||
#[inline]
|
||||
pub fn sub_self_q(&mut self, other: &Quaternion<S>) {
|
||||
self.each_mut(|i, x| *x = x.sub(other.i(i)));
|
||||
pub fn sub_self_q(&mut self, q: &Quaternion<S>) {
|
||||
self.s = self.s - q.s;
|
||||
self.v.sub_self_v(&q.v);
|
||||
}
|
||||
|
||||
/// Multiply this quaternion by another, in-place.
|
||||
#[inline]
|
||||
pub fn mul_self_q(&mut self, other: &Quaternion<S>) {
|
||||
*self = self.mul_q(other);
|
||||
pub fn mul_self_q(&mut self, q: &Quaternion<S>) {
|
||||
self.s = self.s * q.s;
|
||||
self.v.mul_self_v(&q.v);
|
||||
}
|
||||
|
||||
/// The dot product of the quaternion and `other`.
|
||||
/// The dot product of the quaternion and `q`.
|
||||
#[inline]
|
||||
pub fn dot(&self, other: &Quaternion<S>) -> S {
|
||||
self.s * other.s + self.v.dot(&other.v)
|
||||
pub fn dot(&self, q: &Quaternion<S>) -> S {
|
||||
self.s * q.s + self.v.dot(&q.v)
|
||||
}
|
||||
|
||||
/// The conjugate of the quaternion.
|
||||
|
@ -176,6 +201,14 @@ impl<S: BaseFloat> Quaternion<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> ApproxEq<S> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &Quaternion<S>, epsilon: &S) -> bool {
|
||||
self.s.approx_eq_eps(&other.s, epsilon) &&
|
||||
self.v.approx_eq_eps(&other.v, epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Quaternion<S> {
|
||||
/// Spherical Linear Intoperlation
|
||||
///
|
||||
|
@ -305,7 +338,7 @@ impl<S: BaseFloat> ToQuaternion<S> for Quaternion<S> {
|
|||
fn to_quaternion(&self) -> Quaternion<S> { self.clone() }
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Rotation<S, [S, ..3], Vector3<S>, Point3<S>> for Quaternion<S> {
|
||||
impl<S: BaseFloat> Rotation<S, Vector3<S>, Point3<S>> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn identity() -> Quaternion<S> { Quaternion::identity() }
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ pub struct Ray<P,V> {
|
|||
pub direction: V,
|
||||
}
|
||||
|
||||
impl<S: BaseNum, Slice, V: Vector<S, Slice>, P: Point<S, V, Slice>> Ray<P, V> {
|
||||
impl<S: BaseNum, V: Vector<S>, P: Point<S, V>> Ray<P, V> {
|
||||
pub fn new(origin: P, direction: V) -> Ray<P,V> {
|
||||
Ray { origin: origin, direction: direction }
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
use angle::{Rad, acos};
|
||||
use approx::ApproxEq;
|
||||
use array::Array;
|
||||
use matrix::Matrix;
|
||||
use matrix::{Matrix2, ToMatrix2};
|
||||
use matrix::{Matrix3, ToMatrix3};
|
||||
|
@ -27,16 +26,7 @@ use vector::{Vector, Vector2, Vector3};
|
|||
|
||||
/// A trait for a generic rotation. A rotation is a transformation that
|
||||
/// creates a circular motion, and preserves at least one point in the space.
|
||||
pub trait Rotation
|
||||
<
|
||||
S: BaseNum,
|
||||
Slice,
|
||||
V: Vector<S,Slice>,
|
||||
P: Point<S,V,Slice>
|
||||
>
|
||||
: Eq
|
||||
+ ApproxEq<S>
|
||||
{
|
||||
pub trait Rotation<S: BaseNum, V: Vector<S>, P: Point<S, V>>: Eq + ApproxEq<S> {
|
||||
/// Create the identity transform (causes no transformation).
|
||||
fn identity() -> Self;
|
||||
|
||||
|
@ -59,10 +49,8 @@ pub trait Rotation
|
|||
|
||||
/// Rotate a ray using this rotation.
|
||||
#[inline]
|
||||
fn rotate_ray(&self, ray: &Ray<P,V>) -> Ray<P,V> {
|
||||
Ray::new( //FIXME: use clone derived from Array
|
||||
Array::build(|i| ray.origin.i(i).clone()),
|
||||
self.rotate_vector(&ray.direction) )
|
||||
fn rotate_ray(&self, ray: &Ray<P, V>) -> Ray<P,V> {
|
||||
Ray::new(ray.origin.clone(), self.rotate_vector(&ray.direction))
|
||||
}
|
||||
|
||||
/// Create a new rotation which combines both this rotation, and another.
|
||||
|
@ -86,29 +74,19 @@ pub trait Rotation
|
|||
}
|
||||
|
||||
/// A two-dimensional rotation.
|
||||
pub trait Rotation2
|
||||
<
|
||||
S
|
||||
>
|
||||
: Rotation<S, [S, ..2], Vector2<S>, Point2<S>>
|
||||
+ ToMatrix2<S>
|
||||
+ ToBasis2<S>
|
||||
{
|
||||
pub trait Rotation2<S>: Rotation<S, Vector2<S>, Point2<S>>
|
||||
+ ToMatrix2<S>
|
||||
+ ToBasis2<S> {
|
||||
/// Create a rotation by a given angle. Thus is a redundant case of both
|
||||
/// from_axis_angle() and from_euler() for 2D space.
|
||||
fn from_angle(theta: Rad<S>) -> Self;
|
||||
}
|
||||
|
||||
/// A three-dimensional rotation.
|
||||
pub trait Rotation3
|
||||
<
|
||||
S: BaseNum
|
||||
>
|
||||
: Rotation<S, [S, ..3], Vector3<S>, Point3<S>>
|
||||
+ ToMatrix3<S>
|
||||
+ ToBasis3<S>
|
||||
+ ToQuaternion<S>
|
||||
{
|
||||
pub trait Rotation3<S: BaseNum>: Rotation<S, Vector3<S>, Point3<S>>
|
||||
+ ToMatrix3<S>
|
||||
+ ToBasis3<S>
|
||||
+ ToQuaternion<S>{
|
||||
/// Create a rotation using an angle around a given axis.
|
||||
fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Self;
|
||||
|
||||
|
@ -174,7 +152,7 @@ impl<S: BaseFloat> ToMatrix2<S> for Basis2<S> {
|
|||
fn to_matrix2(&self) -> Matrix2<S> { self.mat.clone() }
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Rotation<S, [S, ..2], Vector2<S>, Point2<S>> for Basis2<S> {
|
||||
impl<S: BaseFloat> Rotation<S, Vector2<S>, Point2<S>> for Basis2<S> {
|
||||
#[inline]
|
||||
fn identity() -> Basis2<S> { Basis2{ mat: Matrix2::identity() } }
|
||||
|
||||
|
@ -263,7 +241,7 @@ impl<S: BaseFloat> ToQuaternion<S> for Basis3<S> {
|
|||
fn to_quaternion(&self) -> Quaternion<S> { self.mat.to_quaternion() }
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Rotation<S, [S, ..3], Vector3<S>, Point3<S>> for Basis3<S> {
|
||||
impl<S: BaseFloat> Rotation<S, Vector3<S>, Point3<S>> for Basis3<S> {
|
||||
#[inline]
|
||||
fn identity() -> Basis3<S> { Basis3{ mat: Matrix3::identity() } }
|
||||
|
||||
|
|
|
@ -29,14 +29,7 @@ use vector::{Vector, Vector3};
|
|||
/// A trait representing an [affine
|
||||
/// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that
|
||||
/// can be applied to points or vectors. An affine transformation is one which
|
||||
pub trait Transform
|
||||
<
|
||||
S: BaseNum,
|
||||
Slice,
|
||||
V: Vector<S,Slice>,
|
||||
P: Point<S,V,Slice>
|
||||
>
|
||||
{
|
||||
pub trait Transform<S: BaseNum, V: Vector<S>, P: Point<S,V>> {
|
||||
/// Create an identity transformation. That is, a transformation which
|
||||
/// does nothing.
|
||||
fn identity() -> Self;
|
||||
|
@ -92,15 +85,7 @@ pub struct Decomposed<S,V,R> {
|
|||
pub disp: V,
|
||||
}
|
||||
|
||||
impl
|
||||
<
|
||||
S: BaseFloat,
|
||||
Slice,
|
||||
V: Vector<S, Slice>,
|
||||
P: Point<S, V, Slice>,
|
||||
R: Rotation<S, Slice, V, P>
|
||||
>
|
||||
Transform<S, Slice, V, P> for Decomposed<S,V,R> {
|
||||
impl<S: BaseFloat, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>> Transform<S, V, P> for Decomposed<S,V,R> {
|
||||
#[inline]
|
||||
fn identity() -> Decomposed<S,V,R> {
|
||||
Decomposed {
|
||||
|
@ -157,10 +142,7 @@ Transform<S, Slice, V, P> for Decomposed<S,V,R> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait Transform3<S>
|
||||
: Transform<S, [S, ..3], Vector3<S>, Point3<S>>
|
||||
+ ToMatrix4<S>
|
||||
{}
|
||||
pub trait Transform3<S>: Transform<S, Vector3<S>, Point3<S>>+ ToMatrix4<S> {}
|
||||
|
||||
impl<S: BaseFloat, R: Rotation3<S>> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> {
|
||||
fn to_matrix4(&self) -> Matrix4<S> {
|
||||
|
@ -185,7 +167,7 @@ pub struct AffineMatrix3<S> {
|
|||
pub mat: Matrix4<S>,
|
||||
}
|
||||
|
||||
impl<S : BaseFloat> Transform<S, [S, ..3], Vector3<S>, Point3<S>> for AffineMatrix3<S> {
|
||||
impl<S : BaseFloat> Transform<S, Vector3<S>, Point3<S>> for AffineMatrix3<S> {
|
||||
#[inline]
|
||||
fn identity() -> AffineMatrix3<S> {
|
||||
AffineMatrix3 { mat: Matrix4::identity() }
|
||||
|
@ -226,7 +208,7 @@ impl<S: BaseFloat> Transform3<S> for AffineMatrix3<S> {}
|
|||
|
||||
/// A transformation in three dimensions consisting of a rotation,
|
||||
/// displacement vector and scale amount.
|
||||
pub struct Transform3D<S>( Decomposed<S,Vector3<S>,Quaternion<S>> );
|
||||
pub struct Transform3D<S>(Decomposed<S,Vector3<S>,Quaternion<S>>);
|
||||
|
||||
impl<S: BaseFloat> Transform3D<S> {
|
||||
#[inline]
|
||||
|
|
|
@ -14,90 +14,85 @@
|
|||
// limitations under the License.
|
||||
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::num::{Zero, zero, One, one};
|
||||
|
||||
use angle::{Rad, atan2, acos};
|
||||
use approx::ApproxEq;
|
||||
use array::{Array, build};
|
||||
use num::{BaseNum, BaseFloat, PartialOrd};
|
||||
use array::Array1;
|
||||
use num::{BaseNum, BaseFloat};
|
||||
|
||||
/// A trait that specifies a range of numeric operations for vectors. Not all
|
||||
/// of these make sense from a linear algebra point of view, but are included
|
||||
/// for pragmatic reasons.
|
||||
pub trait Vector
|
||||
<
|
||||
S: BaseNum,
|
||||
Slice
|
||||
>
|
||||
: Array<S, Slice>
|
||||
+ Neg<Self>
|
||||
+ Zero + One
|
||||
{
|
||||
pub trait Vector<S: BaseNum>: Array1<S>
|
||||
+ Neg<Self>
|
||||
+ Zero
|
||||
+ One {
|
||||
/// Add a scalar to this vector, returning a new vector.
|
||||
#[inline] fn add_s(&self, s: S) -> Self { build(|i| self.i(i).add(&s)) }
|
||||
fn add_s(&self, s: S) -> Self;
|
||||
/// Subtract a scalar from this vector, returning a new vector.
|
||||
#[inline] fn sub_s(&self, s: S) -> Self { build(|i| self.i(i).sub(&s)) }
|
||||
fn sub_s(&self, s: S) -> Self;
|
||||
/// Multiply this vector by a scalar, returning a new vector.
|
||||
#[inline] fn mul_s(&self, s: S) -> Self { build(|i| self.i(i).mul(&s)) }
|
||||
fn mul_s(&self, s: S) -> Self;
|
||||
/// Divide this vector by a scalar, returning a new vector.
|
||||
#[inline] fn div_s(&self, s: S) -> Self { build(|i| self.i(i).div(&s)) }
|
||||
fn div_s(&self, s: S) -> Self;
|
||||
/// Take the remainder of this vector by a scalar, returning a new vector.
|
||||
#[inline] fn rem_s(&self, s: S) -> Self { build(|i| self.i(i).rem(&s)) }
|
||||
fn rem_s(&self, s: S) -> Self;
|
||||
|
||||
/// Add this vector to another, returning a new vector.
|
||||
#[inline] fn add_v(&self, other: &Self) -> Self { build(|i| self.i(i).add(other.i(i))) }
|
||||
fn add_v(&self, v: &Self) -> Self;
|
||||
/// Subtract another vector from this one, returning a new vector.
|
||||
#[inline] fn sub_v(&self, other: &Self) -> Self { build(|i| self.i(i).sub(other.i(i))) }
|
||||
fn sub_v(&self, v: &Self) -> Self;
|
||||
/// Multiply this vector by another, returning a new vector.
|
||||
#[inline] fn mul_v(&self, other: &Self) -> Self { build(|i| self.i(i).mul(other.i(i))) }
|
||||
fn mul_v(&self, v: &Self) -> Self;
|
||||
/// Divide this vector by another, returning a new vector.
|
||||
#[inline] fn div_v(&self, other: &Self) -> Self { build(|i| self.i(i).div(other.i(i))) }
|
||||
fn div_v(&self, v: &Self) -> Self;
|
||||
/// Take the remainder of this vector by another, returning a new scalar.
|
||||
#[inline] fn rem_v(&self, other: &Self) -> Self { build(|i| self.i(i).rem(other.i(i))) }
|
||||
fn rem_v(&self, v: &Self) -> Self;
|
||||
|
||||
/// Negate this vector in-place.
|
||||
#[inline] fn neg_self(&mut self) { self.each_mut(|_, x| *x = x.neg()) }
|
||||
fn neg_self(&mut self);
|
||||
|
||||
/// Add a scalar to this vector in-place.
|
||||
#[inline] fn add_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.add(&s)) }
|
||||
fn add_self_s(&mut self, s: S);
|
||||
/// Subtract a scalar from this vector, in-place.
|
||||
#[inline] fn sub_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.sub(&s)) }
|
||||
fn sub_self_s(&mut self, s: S);
|
||||
/// Multiply this vector by a scalar, in-place.
|
||||
#[inline] fn mul_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.mul(&s)) }
|
||||
fn mul_self_s(&mut self, s: S);
|
||||
/// Divide this vector by a scalar, in-place.
|
||||
#[inline] fn div_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.div(&s)) }
|
||||
fn div_self_s(&mut self, s: S);
|
||||
/// Take the remainder of this vector by a scalar, in-place.
|
||||
#[inline] fn rem_self_s(&mut self, s: S) { self.each_mut(|_, x| *x = x.rem(&s)) }
|
||||
fn rem_self_s(&mut self, s: S);
|
||||
|
||||
/// Add another vector to this one, in-place.
|
||||
#[inline] fn add_self_v(&mut self, other: &Self) { self.each_mut(|i, x| *x = x.add(other.i(i))) }
|
||||
fn add_self_v(&mut self, v: &Self);
|
||||
/// Subtract another vector from this one, in-place.
|
||||
#[inline] fn sub_self_v(&mut self, other: &Self) { self.each_mut(|i, x| *x = x.sub(other.i(i))) }
|
||||
fn sub_self_v(&mut self, v: &Self);
|
||||
/// Multiply this matrix by another, in-place.
|
||||
#[inline] fn mul_self_v(&mut self, other: &Self) { self.each_mut(|i, x| *x = x.mul(other.i(i))) }
|
||||
fn mul_self_v(&mut self, v: &Self);
|
||||
/// Divide this matrix by anothor, in-place.
|
||||
#[inline] fn div_self_v(&mut self, other: &Self) { self.each_mut(|i, x| *x = x.div(other.i(i))) }
|
||||
fn div_self_v(&mut self, v: &Self);
|
||||
/// Take the remainder of this vector by another, in-place.
|
||||
#[inline] fn rem_self_v(&mut self, other: &Self) { self.each_mut(|i, x| *x = x.rem(other.i(i))) }
|
||||
fn rem_self_v(&mut self, v: &Self);
|
||||
|
||||
/// The sum of each component of the vector.
|
||||
#[inline] fn comp_add(&self) -> S { self.fold(|a, b| a.add(b)) }
|
||||
|
||||
fn comp_add(&self) -> S;
|
||||
/// The product of each component of the vector.
|
||||
#[inline] fn comp_mul(&self) -> S { self.fold(|a, b| a.mul(b)) }
|
||||
fn comp_mul(&self) -> S;
|
||||
|
||||
/// Vector dot product.
|
||||
#[inline] fn dot(&self, other: &Self) -> S { self.mul_v(other).comp_add() }
|
||||
#[inline]
|
||||
fn dot(&self, v: &Self) -> S { self.mul_v(v).comp_add() }
|
||||
|
||||
/// The minimum component of the vector.
|
||||
#[inline] fn comp_min(&self) -> S { self.fold(|a, b| a.partial_min(*b)) }
|
||||
|
||||
fn comp_min(&self) -> S;
|
||||
/// The maximum component of the vector.
|
||||
#[inline] fn comp_max(&self) -> S { self.fold(|a, b| a.partial_max(*b)) }
|
||||
fn comp_max(&self) -> S;
|
||||
}
|
||||
|
||||
/// Dot product of two vectors.
|
||||
#[inline] pub fn dot<S: BaseNum, Slice, V: Vector<S, Slice>>(a: V, b: V) -> S { a.dot(&b) }
|
||||
#[inline] pub fn dot<S: BaseNum, V: Vector<S>>(a: V, b: V) -> S { a.dot(&b) }
|
||||
|
||||
// Utility macro for generating associated functions for the vectors
|
||||
macro_rules! vec(
|
||||
|
@ -105,19 +100,23 @@ macro_rules! vec(
|
|||
#[deriving(Eq, TotalEq, Clone, Hash)]
|
||||
pub struct $Self<S> { $(pub $field: S),+ }
|
||||
|
||||
impl<$S: BaseNum> $Self<$S> {
|
||||
impl<$S> $Self<$S> {
|
||||
/// Construct a new vector, using the provided values.
|
||||
#[inline]
|
||||
pub fn new($($field: $S),+) -> $Self<$S> {
|
||||
$Self { $($field: $field),+ }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S: Clone> $Self<$S> {
|
||||
/// Construct a vector from a single value, replicating it.
|
||||
#[inline]
|
||||
pub fn from_value(value: $S) -> $Self<$S> {
|
||||
$Self { $($field: value.clone()),+ }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S: BaseNum> $Self<$S> {
|
||||
/// The additive identity of the vector.
|
||||
#[inline]
|
||||
pub fn zero() -> $Self<$S> { $Self::from_value(zero()) }
|
||||
|
@ -127,12 +126,65 @@ macro_rules! vec(
|
|||
pub fn ident() -> $Self<$S> { $Self::from_value(one()) }
|
||||
}
|
||||
|
||||
impl<S: Copy> Array1<S> for $Self<S> {
|
||||
#[inline]
|
||||
fn ptr<'a>(&'a self) -> &'a S { &self.x }
|
||||
|
||||
#[inline]
|
||||
fn mut_ptr<'a>(&'a mut self) -> &'a mut S { &mut self.x }
|
||||
|
||||
#[inline]
|
||||
fn i(&self, i: uint) -> S {
|
||||
let slice: &[S, ..$n] = unsafe { mem::transmute(self) };
|
||||
slice[i]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut S {
|
||||
let slice: &'a mut [S, ..$n] = unsafe { mem::transmute(self) };
|
||||
&'a mut slice[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Vector<S> for $Self<S> {
|
||||
#[inline] fn add_s(&self, s: S) -> $Self<S> { $Self::new($(self.$field + s),+) }
|
||||
#[inline] fn sub_s(&self, s: S) -> $Self<S> { $Self::new($(self.$field - s),+) }
|
||||
#[inline] fn mul_s(&self, s: S) -> $Self<S> { $Self::new($(self.$field * s),+) }
|
||||
#[inline] fn div_s(&self, s: S) -> $Self<S> { $Self::new($(self.$field / s),+) }
|
||||
#[inline] fn rem_s(&self, s: S) -> $Self<S> { $Self::new($(self.$field % s),+) }
|
||||
|
||||
#[inline] fn add_v(&self, v: &$Self<S>) -> $Self<S> { $Self::new($(self.$field + v.$field),+) }
|
||||
#[inline] fn sub_v(&self, v: &$Self<S>) -> $Self<S> { $Self::new($(self.$field - v.$field),+) }
|
||||
#[inline] fn mul_v(&self, v: &$Self<S>) -> $Self<S> { $Self::new($(self.$field * v.$field),+) }
|
||||
#[inline] fn div_v(&self, v: &$Self<S>) -> $Self<S> { $Self::new($(self.$field / v.$field),+) }
|
||||
#[inline] fn rem_v(&self, v: &$Self<S>) -> $Self<S> { $Self::new($(self.$field % v.$field),+) }
|
||||
|
||||
#[inline] fn neg_self(&mut self) { $(self.$field = -self.$field;)+ }
|
||||
|
||||
#[inline] fn add_self_s(&mut self, s: S) { $(self.$field = self.$field + s;)+ }
|
||||
#[inline] fn sub_self_s(&mut self, s: S) { $(self.$field = self.$field - s;)+ }
|
||||
#[inline] fn mul_self_s(&mut self, s: S) { $(self.$field = self.$field * s;)+ }
|
||||
#[inline] fn div_self_s(&mut self, s: S) { $(self.$field = self.$field / s;)+ }
|
||||
#[inline] fn rem_self_s(&mut self, s: S) { $(self.$field = self.$field % s;)+ }
|
||||
|
||||
#[inline] fn add_self_v(&mut self, v: &$Self<S>) { $(self.$field = self.$field + v.$field;)+ }
|
||||
#[inline] fn sub_self_v(&mut self, v: &$Self<S>) { $(self.$field = self.$field - v.$field;)+ }
|
||||
#[inline] fn mul_self_v(&mut self, v: &$Self<S>) { $(self.$field = self.$field * v.$field;)+ }
|
||||
#[inline] fn div_self_v(&mut self, v: &$Self<S>) { $(self.$field = self.$field / v.$field;)+ }
|
||||
#[inline] fn rem_self_v(&mut self, v: &$Self<S>) { $(self.$field = self.$field % v.$field;)+ }
|
||||
|
||||
#[inline] fn comp_add(&self) -> S { fold!(&add, { $(self.$field),+ }) }
|
||||
#[inline] fn comp_mul(&self) -> S { fold!(&mul, { $(self.$field),+ }) }
|
||||
#[inline] fn comp_min(&self) -> S { fold!(partial_min, { $(self.$field),+ }) }
|
||||
#[inline] fn comp_max(&self) -> S { fold!(partial_max, { $(self.$field),+ }) }
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Add<$Self<S>, $Self<S>> for $Self<S> {
|
||||
#[inline] fn add(&self, other: &$Self<S>) -> $Self<S> { self.add_v(other) }
|
||||
#[inline] fn add(&self, v: &$Self<S>) -> $Self<S> { self.add_v(v) }
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Sub<$Self<S>, $Self<S>> for $Self<S> {
|
||||
#[inline] fn sub(&self, other: &$Self<S>) -> $Self<S> { self.sub_v(other) }
|
||||
#[inline] fn sub(&self, v: &$Self<S>) -> $Self<S> { self.sub_v(v) }
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Zero for $Self<S> {
|
||||
|
@ -141,29 +193,39 @@ macro_rules! vec(
|
|||
}
|
||||
|
||||
impl<S: BaseNum> Neg<$Self<S>> for $Self<S> {
|
||||
#[inline] fn neg(&self) -> $Self<S> { build(|i| self.i(i).neg()) }
|
||||
#[inline] fn neg(&self) -> $Self<S> { $Self::new($(-self.$field),+) }
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Mul<$Self<S>, $Self<S>> for $Self<S> {
|
||||
#[inline] fn mul(&self, other: &$Self<S>) -> $Self<S> { self.mul_v(other) }
|
||||
#[inline] fn mul(&self, v: &$Self<S>) -> $Self<S> { self.mul_v(v) }
|
||||
}
|
||||
|
||||
impl<S: BaseNum> One for $Self<S> {
|
||||
#[inline] fn one() -> $Self<S> { $Self::from_value(one()) }
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Vector<S, [S, ..$n]> for $Self<S> {}
|
||||
impl<S: BaseFloat> ApproxEq<S> for $Self<S> {
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &$Self<S>, epsilon: &S) -> bool {
|
||||
$(self.$field.approx_eq_eps(&other.$field, epsilon))&&+
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! fold {
|
||||
(&$method:ident, { $x:expr, $y:expr }) => { $x.$method(&$y) };
|
||||
(&$method:ident, { $x:expr, $y:expr, $z:expr }) => { $x.$method(&$y).$method(&$z) };
|
||||
(&$method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => { $x.$method(&$y).$method(&$z).$method(&$w) };
|
||||
($method:ident, { $x:expr, $y:expr }) => { $x.$method($y) };
|
||||
($method:ident, { $x:expr, $y:expr, $z:expr }) => { $x.$method($y).$method($z) };
|
||||
($method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => { $x.$method($y).$method($z).$method($w) };
|
||||
}
|
||||
|
||||
vec!(Vector2<S> { x, y }, 2)
|
||||
vec!(Vector3<S> { x, y, z }, 3)
|
||||
vec!(Vector4<S> { x, y, z, w }, 4)
|
||||
|
||||
array!(impl<S> Vector2<S> -> [S, ..2] _2)
|
||||
array!(impl<S> Vector3<S> -> [S, ..3] _3)
|
||||
array!(impl<S> Vector4<S> -> [S, ..4] _4)
|
||||
|
||||
/// Operations specific to numeric two-dimensional vectors.
|
||||
impl<S: BaseNum> Vector2<S> {
|
||||
/// A unit vector in the `x` direction.
|
||||
|
@ -243,14 +305,8 @@ impl<S: BaseNum> Vector4<S> {
|
|||
|
||||
/// Specifies geometric operations for vectors. This is only implemented for
|
||||
/// 2-dimensional and 3-dimensional vectors.
|
||||
pub trait EuclideanVector
|
||||
<
|
||||
S: BaseFloat,
|
||||
Slice
|
||||
>
|
||||
: Vector<S, Slice>
|
||||
+ ApproxEq<S>
|
||||
{
|
||||
pub trait EuclideanVector<S: BaseFloat>: Vector<S>
|
||||
+ ApproxEq<S> {
|
||||
/// Returns `true` if the vector is perpendicular (at right angles) to the
|
||||
/// other vector.
|
||||
fn is_perpendicular(&self, other: &Self) -> bool {
|
||||
|
@ -316,43 +372,40 @@ pub trait EuclideanVector
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat>
|
||||
EuclideanVector<S, [S, ..2]> for Vector2<S> {
|
||||
impl<S: BaseFloat> EuclideanVector<S> for Vector2<S> {
|
||||
#[inline]
|
||||
fn angle(&self, other: &Vector2<S>) -> Rad<S> {
|
||||
atan2(self.perp_dot(other), self.dot(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat>
|
||||
EuclideanVector<S, [S, ..3]> for Vector3<S> {
|
||||
impl<S: BaseFloat> EuclideanVector<S> for Vector3<S> {
|
||||
#[inline]
|
||||
fn angle(&self, other: &Vector3<S>) -> Rad<S> {
|
||||
atan2(self.cross(other).length(), self.dot(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat>
|
||||
EuclideanVector<S, [S, ..4]> for Vector4<S> {
|
||||
impl<S: BaseFloat> EuclideanVector<S> for Vector4<S> {
|
||||
#[inline]
|
||||
fn angle(&self, other: &Vector4<S>) -> Rad<S> {
|
||||
acos(self.dot(other) / (self.length() * other.length()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: fmt::Show> fmt::Show for Vector2<S> {
|
||||
impl<S: BaseNum> fmt::Show for Vector2<S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "[{}, {}]", self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: fmt::Show> fmt::Show for Vector3<S> {
|
||||
impl<S: BaseNum> fmt::Show for Vector3<S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "[{}, {}, {}]", self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: fmt::Show> fmt::Show for Vector4<S> {
|
||||
impl<S: BaseNum> fmt::Show for Vector4<S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue