Merge pull request #77 from bjz/simplify-array
Simplify type signatures and make function implementations more strait-forward
This commit is contained in:
commit
df072ca97c
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|);
|
||||
}
|
||||
|
||||
macro_rules! array(
|
||||
(impl<$S:ident> $Self:ty -> [$T:ty, ..$n:expr] $_n:ident) => (
|
||||
impl<$S: Clone> Array<$T, [$T,..$n]> for $Self {
|
||||
/// Replace an element in the array.
|
||||
#[inline]
|
||||
fn i<'a>(&'a self, i: uint) -> &'a $T {
|
||||
&'a self.as_slice()[i]
|
||||
fn replace_i(&mut self, i: uint, src: Element) -> Element {
|
||||
mem::replace(self.mut_i(i), src)
|
||||
}
|
||||
}
|
||||
|
||||
/// 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;
|
||||
|
||||
/// Get a mutable pointer to the first element of the array.
|
||||
fn mut_ptr<'a>(&'a mut self) -> &'a mut Element;
|
||||
|
||||
/// Get a shared reference to a column of this array.
|
||||
fn c<'a>(&'a self, c: uint) -> &'a Column;
|
||||
|
||||
/// Get a mutable reference to a column of this array.
|
||||
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut Column;
|
||||
|
||||
/// Swap two columns of this array.
|
||||
#[inline]
|
||||
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut $T {
|
||||
&'a mut self.as_mut_slice()[i]
|
||||
fn swap_c(&mut self, a: uint, b: uint) {
|
||||
unsafe { ptr::swap(self.mut_c(a), self.mut_c(b)) };
|
||||
}
|
||||
|
||||
/// Replace a column in the array.
|
||||
#[inline]
|
||||
fn as_slice<'a>(&'a self) -> &'a [$T,..$n] {
|
||||
unsafe { ::std::mem::transmute(self) }
|
||||
fn replace_c(&mut self, c: uint, src: Column) -> Column {
|
||||
mem::replace(self.mut_c(c), src)
|
||||
}
|
||||
|
||||
/// Get a row from this array by-value.
|
||||
fn r(&self, r: uint) -> Row;
|
||||
|
||||
/// Swap two rows of this array.
|
||||
fn swap_r(&mut self, a: uint, b: uint);
|
||||
|
||||
/// Return a shared reference to the element at column `c` and row `r`.
|
||||
#[inline]
|
||||
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [$T,..$n] {
|
||||
unsafe { ::std::mem::transmute(self) }
|
||||
}
|
||||
fn cr(&self, c: uint, r: uint) -> Element { self.c(c).i(r) }
|
||||
|
||||
/// Return a mutable reference to the element at column `c` and row `r`.
|
||||
#[inline]
|
||||
fn from_repr(slice: [$T,..$n]) -> $Self {
|
||||
unsafe { ::std::mem::transmute(slice) }
|
||||
fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut Element {
|
||||
self.mut_c(c).mut_i(r)
|
||||
}
|
||||
|
||||
/// Swap the values at index `a` and `b`
|
||||
#[inline]
|
||||
fn build(builder: |i: uint| -> $T) -> $Self {
|
||||
Array::from_repr(gen_builder!($_n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn iter<'a>(&'a self) -> ::std::slice::Items<'a, $T> {
|
||||
self.as_slice().iter()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mut_iter<'a>(&'a mut self) -> ::std::slice::MutItems<'a, $T> {
|
||||
self.as_mut_slice().mut_iter()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold(&self, f: |&$T, &$T| -> $T) -> $T {
|
||||
gen_fold!($_n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn each_mut(&mut self, f: |i: uint, x: &mut $T|) {
|
||||
gen_each_mut!($_n)
|
||||
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)) };
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
#[inline]
|
||||
pub fn build<T: Clone, Slice, A: Array<T, Slice>>(builder: |i: uint| -> T) -> A {
|
||||
Array::build(builder)
|
||||
}
|
||||
|
||||
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>
|
||||
pub trait Matrix<S: BaseFloat, V: Clone + Vector<S>>: Array2<V, V, S>
|
||||
+ 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()) }
|
||||
|
||||
+ 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;
|
||||
|
||||
|
@ -60,9 +50,7 @@ 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) )
|
||||
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>>
|
||||
pub trait Rotation2<S>: Rotation<S, Vector2<S>, Point2<S>>
|
||||
+ ToMatrix2<S>
|
||||
+ ToBasis2<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>>
|
||||
pub trait Rotation3<S: BaseNum>: Rotation<S, Vector3<S>, Point3<S>>
|
||||
+ ToMatrix3<S>
|
||||
+ ToBasis3<S>
|
||||
+ ToQuaternion<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() }
|
||||
|
|
|
@ -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>
|
||||
pub trait Vector<S: BaseNum>: Array1<S>
|
||||
+ Neg<Self>
|
||||
+ Zero + One
|
||||
{
|
||||
+ 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