parent
75af609121
commit
0ce28fbe10
5 changed files with 480 additions and 367 deletions
11
src/array.rs
11
src/array.rs
|
@ -90,14 +90,3 @@ pub trait Array2<Column: Array1<Element>+'static, Row: Array1<Element>, Element:
|
|||
fn map<F>(&mut self, op: F) -> Self
|
||||
where F: FnMut(&Column) -> Column;
|
||||
}
|
||||
|
||||
/// Homogeneous arrays of elements that can be converted to and from `[T, ..N]`
|
||||
/// arrays.
|
||||
pub trait FixedArray<V> {
|
||||
fn into_fixed(self) -> V;
|
||||
fn as_fixed<'a>(&'a self) -> &'a V;
|
||||
fn as_mut_fixed<'a>(&'a mut self) -> &'a mut V;
|
||||
fn from_fixed(v: V) -> Self;
|
||||
fn from_fixed_ref<'a>(v: &'a V) -> &'a Self;
|
||||
fn from_fixed_mut<'a>(v: &'a mut V) -> &'a mut Self;
|
||||
}
|
||||
|
|
306
src/matrix.rs
306
src/matrix.rs
|
@ -26,7 +26,7 @@ use rust_num::traits::cast;
|
|||
|
||||
use angle::{Rad, sin, cos, sin_cos};
|
||||
use approx::ApproxEq;
|
||||
use array::{Array1, Array2, FixedArray};
|
||||
use array::{Array1, Array2};
|
||||
use num::{BaseFloat, BaseNum};
|
||||
use point::{Point, Point3};
|
||||
use quaternion::Quaternion;
|
||||
|
@ -557,65 +557,6 @@ impl<S: BaseFloat> One for Matrix4<S> {
|
|||
#[inline] fn one() -> Matrix4<S> { Matrix4::identity() }
|
||||
}
|
||||
|
||||
impl<S> FixedArray<[[S; 2]; 2]> for Matrix2<S> {
|
||||
#[inline]
|
||||
fn into_fixed(self) -> [[S; 2]; 2] {
|
||||
match self {
|
||||
Matrix2 { x, y } => [
|
||||
x.into_fixed(),
|
||||
y.into_fixed(),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_fixed<'a>(&'a self) -> &'a [[S; 2]; 2] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [[S; 2]; 2] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed(_v: [[S; 2]; 2]) -> Matrix2<S> {
|
||||
// match v {
|
||||
// [x, y] => Matrix2 {
|
||||
// x: FixedArray::from_fixed(x),
|
||||
// y: FixedArray::from_fixed(y),
|
||||
// },
|
||||
// }
|
||||
panic!("Unimplemented, pending a fix for rust-lang/rust#16418");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_ref<'a>(v: &'a [[S; 2]; 2]) -> &'a Matrix2<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_mut<'a>(v: &'a mut [[S; 2]; 2]) -> &'a mut Matrix2<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Index<usize> for Matrix2<S> {
|
||||
type Output = Vector2<S>;
|
||||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: usize) -> &'a Vector2<S> {
|
||||
FixedArray::from_fixed_ref(&self.as_fixed()[i])
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> IndexMut<usize> for Matrix2<S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut Vector2<S> {
|
||||
FixedArray::from_fixed_mut(&mut self.as_mut_fixed()[i])
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Copy + 'static> Array2<Vector2<S>, Vector2<S>, S> for Matrix2<S> {
|
||||
#[inline]
|
||||
fn row(&self, r: usize) -> Vector2<S> {
|
||||
|
@ -637,67 +578,6 @@ impl<S: Copy + 'static> Array2<Vector2<S>, Vector2<S>, S> for Matrix2<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> FixedArray<[[S; 3]; 3]> for Matrix3<S> {
|
||||
#[inline]
|
||||
fn into_fixed(self) -> [[S; 3]; 3] {
|
||||
match self {
|
||||
Matrix3 { x, y, z } => [
|
||||
x.into_fixed(),
|
||||
y.into_fixed(),
|
||||
z.into_fixed(),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_fixed<'a>(&'a self) -> &'a [[S; 3]; 3] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [[S; 3]; 3] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed(_v: [[S; 3]; 3]) -> Matrix3<S> {
|
||||
// match v {
|
||||
// [x, y, z] => Matrix3 {
|
||||
// x: FixedArray::from_fixed(x),
|
||||
// y: FixedArray::from_fixed(y),
|
||||
// z: FixedArray::from_fixed(z),
|
||||
// },
|
||||
// }
|
||||
panic!("Unimplemented, pending a fix for rust-lang/rust#16418")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_ref<'a>(v: &'a [[S; 3]; 3]) -> &'a Matrix3<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_mut<'a>(v: &'a mut [[S; 3]; 3]) -> &'a mut Matrix3<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Index<usize> for Matrix3<S> {
|
||||
type Output = Vector3<S>;
|
||||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: usize) -> &'a Vector3<S> {
|
||||
FixedArray::from_fixed_ref(&self.as_fixed()[i])
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> IndexMut<usize> for Matrix3<S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut Vector3<S> {
|
||||
FixedArray::from_fixed_mut(&mut self.as_mut_fixed()[i])
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Copy + 'static> Array2<Vector3<S>, Vector3<S>, S> for Matrix3<S> {
|
||||
#[inline]
|
||||
fn row(&self, r: usize) -> Vector3<S> {
|
||||
|
@ -722,69 +602,6 @@ impl<S: Copy + 'static> Array2<Vector3<S>, Vector3<S>, S> for Matrix3<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> FixedArray<[[S; 4]; 4]> for Matrix4<S> {
|
||||
#[inline]
|
||||
fn into_fixed(self) -> [[S; 4]; 4] {
|
||||
match self {
|
||||
Matrix4 { x, y, z, w } => [
|
||||
x.into_fixed(),
|
||||
y.into_fixed(),
|
||||
z.into_fixed(),
|
||||
w.into_fixed(),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_fixed<'a>(&'a self) -> &'a [[S; 4]; 4] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [[S; 4]; 4] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed(_v: [[S; 4]; 4]) -> Matrix4<S> {
|
||||
// match v {
|
||||
// [x, y, z, w] => Matrix4 {
|
||||
// x: FixedArray::from_fixed(x),
|
||||
// y: FixedArray::from_fixed(y),
|
||||
// z: FixedArray::from_fixed(z),
|
||||
// w: FixedArray::from_fixed(w),
|
||||
// },
|
||||
// }
|
||||
panic!("Unimplemented, pending a fix for rust-lang/rust#16418")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_ref<'a>(v: &'a [[S; 4]; 4]) -> &'a Matrix4<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_mut<'a>(v: &'a mut [[S; 4]; 4]) -> &'a mut Matrix4<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Index<usize> for Matrix4<S> {
|
||||
type Output = Vector4<S>;
|
||||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: usize) -> &'a Vector4<S> {
|
||||
FixedArray::from_fixed_ref(&self.as_fixed()[i])
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> IndexMut<usize> for Matrix4<S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut Vector4<S> {
|
||||
FixedArray::from_fixed_mut(&mut self.as_mut_fixed()[i])
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Copy + 'static> Array2<Vector4<S>, Vector4<S>, S> for Matrix4<S> {
|
||||
#[inline]
|
||||
fn row(&self, r: usize) -> Vector4<S> {
|
||||
|
@ -1324,7 +1141,126 @@ impl<S: BaseFloat> ApproxEq<S> for Matrix4<S> {
|
|||
}
|
||||
}
|
||||
|
||||
// Conversion traits
|
||||
macro_rules! index_operators {
|
||||
($MatrixN:ident <$S:ident>, $VectorN: ident, $n:expr) => {
|
||||
impl<$S> Index<usize> for $MatrixN<$S> {
|
||||
type Output = $VectorN<$S>;
|
||||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: usize) -> &'a $VectorN<$S> {
|
||||
let v: &[[$S; $n]; $n] = self.as_ref();
|
||||
From::from(&v[i])
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> IndexMut<usize> for $MatrixN<$S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut $VectorN<$S> {
|
||||
let v: &mut [[$S; $n]; $n] = self.as_mut();
|
||||
From::from(&mut v[i])
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
index_operators!(Matrix2<S>, Vector2, 2);
|
||||
index_operators!(Matrix3<S>, Vector3, 3);
|
||||
index_operators!(Matrix4<S>, Vector4, 4);
|
||||
|
||||
macro_rules! fixed_array_conversions {
|
||||
($MatrixN:ident <$S:ident> { $($field:ident : $index:expr),+ }, $n:expr) => {
|
||||
impl<$S> Into<[[$S; $n]; $n]> for $MatrixN<$S> {
|
||||
#[inline]
|
||||
fn into(self) -> [[$S; $n]; $n] {
|
||||
match self { $MatrixN { $($field),+ } => [$($field.into()),+] }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> AsRef<[[$S; $n]; $n]> for $MatrixN<$S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[[$S; $n]; $n] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> AsMut<[[$S; $n]; $n]> for $MatrixN<$S> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [[$S; $n]; $n] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S: Copy> From<[[$S; $n]; $n]> for $MatrixN<$S> {
|
||||
#[inline]
|
||||
fn from(m: [[$S; $n]; $n]) -> $MatrixN<$S> {
|
||||
// We need to use a copy here because we can't pattern match on arrays yet
|
||||
$MatrixN { $($field: From::from(m[$index])),+ }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S> From<&'a [[$S; $n]; $n]> for &'a $MatrixN<$S> {
|
||||
#[inline]
|
||||
fn from(m: &'a [[$S; $n]; $n]) -> &'a $MatrixN<$S> {
|
||||
unsafe { mem::transmute(m) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S> From<&'a mut [[$S; $n]; $n]> for &'a mut $MatrixN<$S> {
|
||||
#[inline]
|
||||
fn from(m: &'a mut [[$S; $n]; $n]) -> &'a mut $MatrixN<$S> {
|
||||
unsafe { mem::transmute(m) }
|
||||
}
|
||||
}
|
||||
|
||||
// impl<$S> Into<[$S; ($n * $n)]> for $MatrixN<$S> {
|
||||
// #[inline]
|
||||
// fn into(self) -> [[$S; $n]; $n] {
|
||||
// // TODO: Not sure how to implement this...
|
||||
// unimplemented!()
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<$S> AsRef<[$S; ($n * $n)]> for $MatrixN<$S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[$S; ($n * $n)] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> AsMut<[$S; ($n * $n)]> for $MatrixN<$S> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [$S; ($n * $n)] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
// impl<$S> From<[$S; ($n * $n)]> for $MatrixN<$S> {
|
||||
// #[inline]
|
||||
// fn from(m: [$S; ($n * $n)]) -> $MatrixN<$S> {
|
||||
// // TODO: Not sure how to implement this...
|
||||
// unimplemented!()
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<'a, $S> From<&'a [$S; ($n * $n)]> for &'a $MatrixN<$S> {
|
||||
#[inline]
|
||||
fn from(m: &'a [$S; ($n * $n)]) -> &'a $MatrixN<$S> {
|
||||
unsafe { mem::transmute(m) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S> From<&'a mut [$S; ($n * $n)]> for &'a mut $MatrixN<$S> {
|
||||
#[inline]
|
||||
fn from(m: &'a mut [$S; ($n * $n)]) -> &'a mut $MatrixN<$S> {
|
||||
unsafe { mem::transmute(m) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixed_array_conversions!(Matrix2<S> { x:0, y:1 }, 2);
|
||||
fixed_array_conversions!(Matrix3<S> { x:0, y:1, z:2 }, 3);
|
||||
fixed_array_conversions!(Matrix4<S> { x:0, y:1, z:2, w:3 }, 4);
|
||||
|
||||
impl<S: BaseFloat> From<Matrix2<S>> for Matrix3<S> {
|
||||
/// Clone the elements of a 2-dimensional matrix into the top-left corner
|
||||
|
|
222
src/point.rs
222
src/point.rs
|
@ -24,7 +24,7 @@ use std::ops::*;
|
|||
use rust_num::{one, zero};
|
||||
|
||||
use approx::ApproxEq;
|
||||
use array::{Array1, FixedArray};
|
||||
use array::Array1;
|
||||
use bound::*;
|
||||
use matrix::{Matrix, Matrix4};
|
||||
use num::{BaseNum, BaseFloat};
|
||||
|
@ -113,54 +113,6 @@ pub trait Point<S: BaseNum, V: Vector<S>>: Array1<S> + Clone {
|
|||
fn max(&self, p: &Self) -> Self;
|
||||
}
|
||||
|
||||
impl<S> FixedArray<[S; 2]> for Point2<S> {
|
||||
#[inline]
|
||||
fn into_fixed(self) -> [S; 2] {
|
||||
match self { Point2 { x, y } => [x, y] }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_fixed<'a>(&'a self) -> &'a [S; 2] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [S; 2] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed(_v: [S; 2]) -> Point2<S> {
|
||||
// match v { [x, y] => Point2 { x: x, y: y } }
|
||||
panic!("Unimplemented, pending a fix for rust-lang/rust#16418");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_ref<'a>(v: &'a [S; 2]) -> &'a Point2<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_mut<'a>(v: &'a mut [S; 2]) -> &'a mut Point2<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Index<usize> for Point2<S> {
|
||||
type Output = S;
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: usize) -> &'a S {
|
||||
&self.as_fixed()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> IndexMut<usize> for Point2<S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut S {
|
||||
&mut self.as_mut_fixed()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Array1<S> for Point2<S> {
|
||||
#[inline]
|
||||
fn map<F>(&mut self, mut op: F) -> Point2<S> where F: FnMut(S) -> S {
|
||||
|
@ -268,55 +220,6 @@ impl<S: BaseFloat> ApproxEq<S> for Point2<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> FixedArray<[S; 3]> for Point3<S> {
|
||||
#[inline]
|
||||
fn into_fixed(self) -> [S; 3] {
|
||||
match self { Point3 { x, y, z } => [x, y, z] }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_fixed<'a>(&'a self) -> &'a [S; 3] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [S; 3] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed(_v: [S; 3]) -> Point3<S> {
|
||||
// match v { [x, y, z] => Point3 { x: x, y: y, z: z } }
|
||||
panic!("Unimplemented, pending a fix for rust-lang/rust#16418")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_ref<'a>(v: &'a [S; 3]) -> &'a Point3<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_mut<'a>(v: &'a mut [S; 3]) -> &'a mut Point3<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Index<usize> for Point3<S> {
|
||||
type Output = S;
|
||||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: usize) -> &'a S {
|
||||
&self.as_fixed()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> IndexMut<usize> for Point3<S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut S {
|
||||
&mut self.as_mut_fixed()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Array1<S> for Point3<S> {
|
||||
#[inline]
|
||||
fn map<F>(&mut self, mut op: F) -> Point3<S> where F: FnMut(S) -> S {
|
||||
|
@ -439,6 +342,129 @@ impl<S: BaseFloat> ApproxEq<S> for Point3<S> {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! fixed_array_conversions {
|
||||
($PointN:ident <$S:ident> { $($field:ident : $index:expr),+ }, $n:expr) => {
|
||||
impl<$S> Into<[$S; $n]> for $PointN<$S> {
|
||||
#[inline]
|
||||
fn into(self) -> [$S; $n] {
|
||||
match self { $PointN { $($field),+ } => [$($field),+] }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> AsRef<[$S; $n]> for $PointN<$S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[$S; $n] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> AsMut<[$S; $n]> for $PointN<$S> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [$S; $n] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S: Clone> From<[$S; $n]> for $PointN<$S> {
|
||||
#[inline]
|
||||
fn from(v: [$S; $n]) -> $PointN<$S> {
|
||||
// We need to use a clone here because we can't pattern match on arrays yet
|
||||
$PointN { $($field: v[$index].clone()),+ }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S> From<&'a [$S; $n]> for &'a $PointN<$S> {
|
||||
#[inline]
|
||||
fn from(v: &'a [$S; $n]) -> &'a $PointN<$S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S> From<&'a mut [$S; $n]> for &'a mut $PointN<$S> {
|
||||
#[inline]
|
||||
fn from(v: &'a mut [$S; $n]) -> &'a mut $PointN<$S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixed_array_conversions!(Point2<S> { x:0, y:1 }, 2);
|
||||
fixed_array_conversions!(Point3<S> { x:0, y:1, z:2 }, 3);
|
||||
|
||||
macro_rules! tuple_conversions {
|
||||
($PointN:ident <$S:ident> { $($field:ident),+ }, $Tuple:ty) => {
|
||||
impl<$S> Into<$Tuple> for $PointN<$S> {
|
||||
#[inline]
|
||||
fn into(self) -> $Tuple {
|
||||
match self { $PointN { $($field),+ } => ($($field),+) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> AsRef<$Tuple> for $PointN<$S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &$Tuple {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> AsMut<$Tuple> for $PointN<$S> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut $Tuple {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> From<$Tuple> for $PointN<$S> {
|
||||
#[inline]
|
||||
fn from(v: $Tuple) -> $PointN<$S> {
|
||||
// We need to use a clone here because we can't pattern match on arrays yet
|
||||
match v { ($($field),+) => $PointN { $($field: $field),+ } }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S> From<&'a $Tuple> for &'a $PointN<$S> {
|
||||
#[inline]
|
||||
fn from(v: &'a $Tuple) -> &'a $PointN<$S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S> From<&'a mut $Tuple> for &'a mut $PointN<$S> {
|
||||
#[inline]
|
||||
fn from(v: &'a mut $Tuple) -> &'a mut $PointN<$S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tuple_conversions!(Point2<S> { x, y }, (S, S));
|
||||
tuple_conversions!(Point3<S> { x, y, z }, (S, S, S));
|
||||
|
||||
macro_rules! index_operators {
|
||||
($PointN:ident <$S:ident>, $n:expr) => {
|
||||
impl<$S> Index<usize> for $PointN<$S> {
|
||||
type Output = $S;
|
||||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: usize) -> &'a $S {
|
||||
let v: &[$S; $n] = self.as_ref(); &v[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> IndexMut<usize> for $PointN<$S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut $S {
|
||||
let v: &mut [$S; $n] = self.as_mut(); &mut v[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index_operators!(Point2<S>, 2);
|
||||
index_operators!(Point3<S>, 3);
|
||||
|
||||
impl<S: BaseNum> fmt::Debug for Point2<S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "[{:?}, {:?}]", self.x, self.y)
|
||||
|
|
|
@ -35,7 +35,10 @@ use vector::{Vector3, Vector, EuclideanVector};
|
|||
/// A [quaternion](https://en.wikipedia.org/wiki/Quaternion) in scalar/vector
|
||||
/// form.
|
||||
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
|
||||
pub struct Quaternion<S> { pub s: S, pub v: Vector3<S> }
|
||||
pub struct Quaternion<S> {
|
||||
pub s: S,
|
||||
pub v: Vector3<S>,
|
||||
}
|
||||
|
||||
impl<S: Copy + BaseFloat> Array1<S> for Quaternion<S> {
|
||||
#[inline]
|
||||
|
@ -48,24 +51,6 @@ impl<S: Copy + BaseFloat> Array1<S> for Quaternion<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Index<usize> for Quaternion<S> {
|
||||
type Output = S;
|
||||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: usize) -> &'a S {
|
||||
let slice: &[S; 4] = unsafe { mem::transmute(self) };
|
||||
&slice[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> IndexMut<usize> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut S {
|
||||
let slice: &'a mut [S; 4] = unsafe { mem::transmute(self) };
|
||||
&mut slice[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Quaternion<S> {
|
||||
/// Construct a new quaternion from one scalar component and three
|
||||
/// imaginary components
|
||||
|
@ -434,6 +419,106 @@ impl<S: BaseFloat> Rotation3<S> for Quaternion<S> where S: 'static {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Into<[S; 4]> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn into(self) -> [S; 4] {
|
||||
match self.into() { (w, xi, yj, zk) => [w, xi, yj, zk] }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> AsRef<[S; 4]> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[S; 4] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> AsMut<[S; 4]> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [S; 4] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> From<[S; 4]> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn from(v: [S; 4]) -> Quaternion<S> {
|
||||
Quaternion::new(v[0], v[1], v[2], v[3])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: BaseFloat> From<&'a [S; 4]> for &'a Quaternion<S> {
|
||||
#[inline]
|
||||
fn from(v: &'a [S; 4]) -> &'a Quaternion<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: BaseFloat> From<&'a mut [S; 4]> for &'a mut Quaternion<S> {
|
||||
#[inline]
|
||||
fn from(v: &'a mut [S; 4]) -> &'a mut Quaternion<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Into<(S, S, S, S)> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn into(self) -> (S, S, S, S) {
|
||||
match self { Quaternion { s, v: Vector3 { x, y, z } } => (s, x, y, z) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> AsRef<(S, S, S, S)> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &(S, S, S, S) {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> AsMut<(S, S, S, S)> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut (S, S, S, S) {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> From<(S, S, S, S)> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn from(v: (S, S, S, S)) -> Quaternion<S> {
|
||||
match v { (w, xi, yj, zk) => Quaternion::new(w, xi, yj, zk) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: BaseFloat> From<&'a (S, S, S, S)> for &'a Quaternion<S> {
|
||||
#[inline]
|
||||
fn from(v: &'a (S, S, S, S)) -> &'a Quaternion<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: BaseFloat> From<&'a mut (S, S, S, S)> for &'a mut Quaternion<S> {
|
||||
#[inline]
|
||||
fn from(v: &'a mut (S, S, S, S)) -> &'a mut Quaternion<S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Index<usize> for Quaternion<S> {
|
||||
type Output = S;
|
||||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: usize) -> &'a S {
|
||||
let v: &[S; 4] = self.as_ref(); &v[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> IndexMut<usize> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut S {
|
||||
let v: &mut [S; 4] = self.as_mut(); &mut v[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat + Rand> Rand for Quaternion<S> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> Quaternion<S> {
|
||||
|
|
185
src/vector.rs
185
src/vector.rs
|
@ -106,7 +106,7 @@ use rust_num::{NumCast, Zero, One, zero, one};
|
|||
|
||||
use angle::{Rad, atan2, acos};
|
||||
use approx::ApproxEq;
|
||||
use array::{Array1, FixedArray};
|
||||
use array::Array1;
|
||||
use num::{BaseNum, BaseFloat};
|
||||
|
||||
/// A trait that specifies a range of numeric operations for vectors. Not all
|
||||
|
@ -188,8 +188,8 @@ pub trait Vector<S: BaseNum>: Array1<S> + Zero + One {
|
|||
#[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(
|
||||
($Self_:ident <$S:ident> { $($field:ident),+ }, $n:expr, $constructor:ident) => (
|
||||
macro_rules! vec {
|
||||
($Self_:ident <$S:ident> { $($field:ident),+ }, $n:expr, $constructor:ident) => {
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct $Self_<S> { $(pub $field: S),+ }
|
||||
|
||||
|
@ -236,55 +236,6 @@ macro_rules! vec(
|
|||
}
|
||||
}
|
||||
|
||||
impl<$S> FixedArray<[$S; $n]> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn into_fixed(self) -> [$S; $n] {
|
||||
match self { $Self_ { $($field),+ } => [$($field),+] }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_fixed<'a>(&'a self) -> &'a [$S; $n] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [$S; $n] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed(_v: [$S; $n]) -> $Self_<$S> {
|
||||
// match v { [$($field),+] => $Self { $($field: $field),+ } }
|
||||
panic!("Unimplemented, pending a fix for rust-lang/rust#16418");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_ref<'a>(v: &'a [$S; $n]) -> &'a $Self_<$S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_fixed_mut<'a>(v: &'a mut [$S; $n]) -> &'a mut $Self_<$S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S: Copy> Index<usize> for $Self_<$S> {
|
||||
type Output = S;
|
||||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: usize) -> &'a $S {
|
||||
&self.as_fixed()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S: Copy> IndexMut<usize> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut $S {
|
||||
&mut self.as_mut_fixed()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S: Copy> Array1<$S> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn map<F>(&mut self, mut op: F) -> $Self_<$S> where F: FnMut($S) -> $S {
|
||||
|
@ -379,8 +330,8 @@ macro_rules! vec(
|
|||
$Self_ { $($field: rng.gen()),+ }
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! fold {
|
||||
(&$method:ident, { $x:expr, $y:expr }) => { $x.$method(&$y) };
|
||||
|
@ -395,6 +346,132 @@ vec!(Vector2<S> { x, y }, 2, vec2);
|
|||
vec!(Vector3<S> { x, y, z }, 3, vec3);
|
||||
vec!(Vector4<S> { x, y, z, w }, 4, vec4);
|
||||
|
||||
macro_rules! fixed_array_conversions {
|
||||
($Self_:ident <$S:ident> { $($field:ident : $index:expr),+ }, $n:expr) => {
|
||||
|
||||
impl<$S> Into<[$S; $n]> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn into(self) -> [$S; $n] {
|
||||
match self { $Self_ { $($field),+ } => [$($field),+] }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> AsRef<[$S; $n]> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[$S; $n] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> AsMut<[$S; $n]> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [$S; $n] {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S: Clone> From<[$S; $n]> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn from(v: [$S; $n]) -> $Self_<$S> {
|
||||
// We need to use a clone here because we can't pattern match on arrays yet
|
||||
$Self_ { $($field: v[$index].clone()),+ }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S> From<&'a [$S; $n]> for &'a $Self_<$S> {
|
||||
#[inline]
|
||||
fn from(v: &'a [$S; $n]) -> &'a $Self_<$S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S> From<&'a mut [$S; $n]> for &'a mut $Self_<$S> {
|
||||
#[inline]
|
||||
fn from(v: &'a mut [$S; $n]) -> &'a mut $Self_<$S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixed_array_conversions!(Vector2<S> { x:0, y:1 }, 2);
|
||||
fixed_array_conversions!(Vector3<S> { x:0, y:1, z:2 }, 3);
|
||||
fixed_array_conversions!(Vector4<S> { x:0, y:1, z:2, w:3 }, 4);
|
||||
|
||||
macro_rules! tuple_conversions {
|
||||
($Self_:ident <$S:ident> { $($field:ident),+ }, $Tuple:ty) => {
|
||||
impl<$S> Into<$Tuple> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn into(self) -> $Tuple {
|
||||
match self { $Self_ { $($field),+ } => ($($field),+) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> AsRef<$Tuple> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &$Tuple {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> AsMut<$Tuple> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut $Tuple {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> From<$Tuple> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn from(v: $Tuple) -> $Self_<$S> {
|
||||
match v { ($($field),+) => $Self_ { $($field: $field),+ } }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S> From<&'a $Tuple> for &'a $Self_<$S> {
|
||||
#[inline]
|
||||
fn from(v: &'a $Tuple) -> &'a $Self_<$S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $S> From<&'a mut $Tuple> for &'a mut $Self_<$S> {
|
||||
#[inline]
|
||||
fn from(v: &'a mut $Tuple) -> &'a mut $Self_<$S> {
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tuple_conversions!(Vector2<S> { x, y }, (S, S));
|
||||
tuple_conversions!(Vector3<S> { x, y, z }, (S, S, S));
|
||||
tuple_conversions!(Vector4<S> { x, y, z, w }, (S, S, S, S));
|
||||
|
||||
macro_rules! index_operators {
|
||||
($Self_:ident <$S:ident>, $n:expr) => {
|
||||
impl<$S> Index<usize> for $Self_<$S> {
|
||||
type Output = $S;
|
||||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: usize) -> &'a $S {
|
||||
let v: &[$S; $n] = self.as_ref(); &v[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> IndexMut<usize> for $Self_<$S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut $S {
|
||||
let v: &mut [$S; $n] = self.as_mut(); &mut v[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index_operators!(Vector2<S>, 2);
|
||||
index_operators!(Vector3<S>, 3);
|
||||
index_operators!(Vector4<S>, 4);
|
||||
|
||||
/// Operations specific to numeric two-dimensional vectors.
|
||||
impl<S: BaseNum> Vector2<S> {
|
||||
/// A unit vector in the `x` direction.
|
||||
|
|
Loading…
Reference in a new issue