Reduce code duplication
We can now have multiple definitions in macros!
This commit is contained in:
parent
ac991aaec0
commit
c2054e4993
1 changed files with 92 additions and 114 deletions
|
@ -20,99 +20,6 @@ use angle::{Rad, atan2, acos};
|
||||||
use approx::ApproxEq;
|
use approx::ApproxEq;
|
||||||
use array::{Array, build};
|
use array::{Array, build};
|
||||||
|
|
||||||
/// A 2-dimensional vector.
|
|
||||||
#[deriving(Eq, Clone)]
|
|
||||||
pub struct Vec2<S> { x: S, y: S }
|
|
||||||
|
|
||||||
/// A 3-dimensional vector.
|
|
||||||
#[deriving(Eq, Clone)]
|
|
||||||
pub struct Vec3<S> { x: S, y: S, z: S }
|
|
||||||
|
|
||||||
/// A 4-dimensional vector.
|
|
||||||
#[deriving(Eq, Clone)]
|
|
||||||
pub struct Vec4<S> { x: S, y: S, z: S, w: S }
|
|
||||||
|
|
||||||
// Conversion traits //FIXME: not used anywhere?
|
|
||||||
pub trait ToVec2<S: Primitive> { fn to_vec2(&self) -> Vec2<S>; }
|
|
||||||
pub trait ToVec3<S: Primitive> { fn to_vec3(&self) -> Vec3<S>; }
|
|
||||||
pub trait ToVec4<S: Primitive> { fn to_vec4(&self) -> Vec4<S>; }
|
|
||||||
|
|
||||||
// Utility macro for generating associated functions for the vectors
|
|
||||||
macro_rules! vec(
|
|
||||||
(impl $Self:ident <$S:ident> { $($field:ident),+ }) => (
|
|
||||||
impl<$S: Primitive> $Self<$S> {
|
|
||||||
#[inline]
|
|
||||||
pub fn new($($field: $S),+) -> $Self<$S> {
|
|
||||||
$Self { $($field: $field),+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct a vector from a single value.
|
|
||||||
#[inline]
|
|
||||||
pub fn from_value(value: $S) -> $Self<$S> {
|
|
||||||
$Self { $($field: value.clone()),+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The additive identity of the vector.
|
|
||||||
#[inline]
|
|
||||||
pub fn zero() -> $Self<$S> { $Self::from_value(zero()) }
|
|
||||||
|
|
||||||
/// The multiplicative identity of the vector.
|
|
||||||
#[inline]
|
|
||||||
pub fn ident() -> $Self<$S> { $Self::from_value(one()) }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
vec!(impl Vec2<S> { x, y })
|
|
||||||
vec!(impl Vec3<S> { x, y, z })
|
|
||||||
vec!(impl Vec4<S> { x, y, z, w })
|
|
||||||
|
|
||||||
impl<S: Primitive> Vec2<S> {
|
|
||||||
#[inline] pub fn unit_x() -> Vec2<S> { Vec2::new(one(), zero()) }
|
|
||||||
#[inline] pub fn unit_y() -> Vec2<S> { Vec2::new(zero(), one()) }
|
|
||||||
}
|
|
||||||
impl<S: Primitive + Clone> Vec2<S> {
|
|
||||||
#[inline]
|
|
||||||
pub fn extend(&self, z: S)-> Vec3<S> {
|
|
||||||
Vec3::new(self.x.clone(), self.y.clone(), z)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Primitive> Vec3<S> {
|
|
||||||
#[inline] pub fn unit_x() -> Vec3<S> { Vec3::new(one(), zero(), zero()) }
|
|
||||||
#[inline] pub fn unit_y() -> Vec3<S> { Vec3::new(zero(), one(), zero()) }
|
|
||||||
#[inline] pub fn unit_z() -> Vec3<S> { Vec3::new(zero(), zero(), one()) }
|
|
||||||
}
|
|
||||||
impl<S: Primitive + Clone> Vec3<S> {
|
|
||||||
#[inline]
|
|
||||||
pub fn extend(&self, w: S)-> Vec4<S> {
|
|
||||||
Vec4::new(self.x.clone(), self.y.clone(), self.z.clone(), w)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn truncate(&self)-> Vec2<S> {
|
|
||||||
Vec2::new(self.x.clone(), self.y.clone()) //ignore Z
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Primitive> Vec4<S> {
|
|
||||||
#[inline] pub fn unit_x() -> Vec4<S> { Vec4::new(one(), zero(), zero(), zero()) }
|
|
||||||
#[inline] pub fn unit_y() -> Vec4<S> { Vec4::new(zero(), one(), zero(), zero()) }
|
|
||||||
#[inline] pub fn unit_z() -> Vec4<S> { Vec4::new(zero(), zero(), one(), zero()) }
|
|
||||||
#[inline] pub fn unit_w() -> Vec4<S> { Vec4::new(zero(), zero(), zero(), one()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Primitive + Clone> Vec4<S> {
|
|
||||||
#[inline]
|
|
||||||
pub fn truncate(&self)-> Vec3<S> {
|
|
||||||
Vec3::new(self.x.clone(), self.y.clone(), self.z.clone()) //ignore W
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
array!(impl<S> Vec2<S> -> [S, ..2] _2)
|
|
||||||
array!(impl<S> Vec3<S> -> [S, ..3] _3)
|
|
||||||
array!(impl<S> Vec4<S> -> [S, ..4] _4)
|
|
||||||
|
|
||||||
/// A trait that specifies a range of numeric operations for vectors. Not all
|
/// 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
|
/// of these make sense from a linear algebra point of view, but are included
|
||||||
/// for pragmatic reasons.
|
/// for pragmatic reasons.
|
||||||
|
@ -169,45 +76,93 @@ pub trait Vector
|
||||||
|
|
||||||
#[inline] pub fn dot<S: Primitive, Slice, V: Vector<S, Slice>>(a: V, b: V) -> S { a.dot(&b) }
|
#[inline] pub fn dot<S: Primitive, Slice, V: Vector<S, Slice>>(a: V, b: V) -> S { a.dot(&b) }
|
||||||
|
|
||||||
impl<S: Primitive> Add<Vec2<S>, Vec2<S>> for Vec2<S> { #[inline] fn add(&self, other: &Vec2<S>) -> Vec2<S> { self.add_v(other) } }
|
// Utility macro for generating associated functions for the vectors
|
||||||
impl<S: Primitive> Add<Vec3<S>, Vec3<S>> for Vec3<S> { #[inline] fn add(&self, other: &Vec3<S>) -> Vec3<S> { self.add_v(other) } }
|
macro_rules! vec(
|
||||||
impl<S: Primitive> Add<Vec4<S>, Vec4<S>> for Vec4<S> { #[inline] fn add(&self, other: &Vec4<S>) -> Vec4<S> { self.add_v(other) } }
|
($Self:ident <$S:ident> { $($field:ident),+ }, $n:expr) => (
|
||||||
|
#[deriving(Eq, Clone)]
|
||||||
|
pub struct $Self<S> { $($field: S),+ }
|
||||||
|
|
||||||
impl<S: Primitive> Sub<Vec2<S>, Vec2<S>> for Vec2<S> { #[inline] fn sub(&self, other: &Vec2<S>) -> Vec2<S> { self.sub_v(other) } }
|
impl<$S: Primitive> $Self<$S> {
|
||||||
impl<S: Primitive> Sub<Vec3<S>, Vec3<S>> for Vec3<S> { #[inline] fn sub(&self, other: &Vec3<S>) -> Vec3<S> { self.sub_v(other) } }
|
#[inline]
|
||||||
impl<S: Primitive> Sub<Vec4<S>, Vec4<S>> for Vec4<S> { #[inline] fn sub(&self, other: &Vec4<S>) -> Vec4<S> { self.sub_v(other) } }
|
pub fn new($($field: $S),+) -> $Self<$S> {
|
||||||
|
$Self { $($field: $field),+ }
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: Primitive> Zero for Vec2<S> { #[inline] fn zero() -> Vec2<S> { Vec2::from_value(zero()) } #[inline] fn is_zero(&self) -> bool { *self == zero() } }
|
/// Construct a vector from a single value.
|
||||||
impl<S: Primitive> Zero for Vec3<S> { #[inline] fn zero() -> Vec3<S> { Vec3::from_value(zero()) } #[inline] fn is_zero(&self) -> bool { *self == zero() } }
|
#[inline]
|
||||||
impl<S: Primitive> Zero for Vec4<S> { #[inline] fn zero() -> Vec4<S> { Vec4::from_value(zero()) } #[inline] fn is_zero(&self) -> bool { *self == zero() } }
|
pub fn from_value(value: $S) -> $Self<$S> {
|
||||||
|
$Self { $($field: value.clone()),+ }
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: Primitive> Neg<Vec2<S>> for Vec2<S> { #[inline] fn neg(&self) -> Vec2<S> { build(|i| self.i(i).neg()) } }
|
/// The additive identity of the vector.
|
||||||
impl<S: Primitive> Neg<Vec3<S>> for Vec3<S> { #[inline] fn neg(&self) -> Vec3<S> { build(|i| self.i(i).neg()) } }
|
#[inline]
|
||||||
impl<S: Primitive> Neg<Vec4<S>> for Vec4<S> { #[inline] fn neg(&self) -> Vec4<S> { build(|i| self.i(i).neg()) } }
|
pub fn zero() -> $Self<$S> { $Self::from_value(zero()) }
|
||||||
|
|
||||||
impl<S: Primitive> Mul<Vec2<S>, Vec2<S>> for Vec2<S> { #[inline] fn mul(&self, other: &Vec2<S>) -> Vec2<S> { self.mul_v(other) } }
|
/// The multiplicative identity of the vector.
|
||||||
impl<S: Primitive> Mul<Vec3<S>, Vec3<S>> for Vec3<S> { #[inline] fn mul(&self, other: &Vec3<S>) -> Vec3<S> { self.mul_v(other) } }
|
#[inline]
|
||||||
impl<S: Primitive> Mul<Vec4<S>, Vec4<S>> for Vec4<S> { #[inline] fn mul(&self, other: &Vec4<S>) -> Vec4<S> { self.mul_v(other) } }
|
pub fn ident() -> $Self<$S> { $Self::from_value(one()) }
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: Primitive> One for Vec2<S> { #[inline] fn one() -> Vec2<S> { Vec2::from_value(one()) } }
|
impl<S: Primitive> Add<$Self<S>, $Self<S>> for $Self<S> {
|
||||||
impl<S: Primitive> One for Vec3<S> { #[inline] fn one() -> Vec3<S> { Vec3::from_value(one()) } }
|
#[inline] fn add(&self, other: &$Self<S>) -> $Self<S> { self.add_v(other) }
|
||||||
impl<S: Primitive> One for Vec4<S> { #[inline] fn one() -> Vec4<S> { Vec4::from_value(one()) } }
|
}
|
||||||
|
|
||||||
impl<S: Primitive> Vector<S, [S, ..2]> for Vec2<S> {}
|
impl<S: Primitive> Sub<$Self<S>, $Self<S>> for $Self<S> {
|
||||||
impl<S: Primitive> Vector<S, [S, ..3]> for Vec3<S> {}
|
#[inline] fn sub(&self, other: &$Self<S>) -> $Self<S> { self.sub_v(other) }
|
||||||
impl<S: Primitive> Vector<S, [S, ..4]> for Vec4<S> {}
|
}
|
||||||
|
|
||||||
|
impl<S: Primitive> Zero for $Self<S> {
|
||||||
|
#[inline] fn zero() -> $Self<S> { $Self::from_value(zero()) }
|
||||||
|
#[inline] fn is_zero(&self) -> bool { *self == zero() }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Primitive> Neg<$Self<S>> for $Self<S> {
|
||||||
|
#[inline] fn neg(&self) -> $Self<S> { build(|i| self.i(i).neg()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Primitive> Mul<$Self<S>, $Self<S>> for $Self<S> {
|
||||||
|
#[inline] fn mul(&self, other: &$Self<S>) -> $Self<S> { self.mul_v(other) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Primitive> One for $Self<S> {
|
||||||
|
#[inline] fn one() -> $Self<S> { $Self::from_value(one()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Primitive> Vector<S, [S, ..$n]> for $Self<S> {}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
vec!(Vec2<S> { x, y }, 2)
|
||||||
|
vec!(Vec3<S> { x, y, z }, 3)
|
||||||
|
vec!(Vec4<S> { x, y, z, w }, 4)
|
||||||
|
|
||||||
|
array!(impl<S> Vec2<S> -> [S, ..2] _2)
|
||||||
|
array!(impl<S> Vec3<S> -> [S, ..3] _3)
|
||||||
|
array!(impl<S> Vec4<S> -> [S, ..4] _4)
|
||||||
|
|
||||||
/// Operations specific to numeric two-dimensional vectors.
|
/// Operations specific to numeric two-dimensional vectors.
|
||||||
impl<S: Primitive> Vec2<S> {
|
impl<S: Primitive> Vec2<S> {
|
||||||
|
#[inline] pub fn unit_x() -> Vec2<S> { Vec2::new(one(), zero()) }
|
||||||
|
#[inline] pub fn unit_y() -> Vec2<S> { Vec2::new(zero(), one()) }
|
||||||
|
|
||||||
/// The perpendicular dot product of the vector and `other`.
|
/// The perpendicular dot product of the vector and `other`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn perp_dot(&self, other: &Vec2<S>) -> S {
|
pub fn perp_dot(&self, other: &Vec2<S>) -> S {
|
||||||
(self.x * other.y) - (self.y * other.x)
|
(self.x * other.y) - (self.y * other.x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn extend(&self, z: S)-> Vec3<S> {
|
||||||
|
Vec3::new(self.x.clone(), self.y.clone(), z)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Operations specific to numeric three-dimensional vectors.
|
/// Operations specific to numeric three-dimensional vectors.
|
||||||
impl<S: Primitive> Vec3<S> {
|
impl<S: Primitive> Vec3<S> {
|
||||||
|
#[inline] pub fn unit_x() -> Vec3<S> { Vec3::new(one(), zero(), zero()) }
|
||||||
|
#[inline] pub fn unit_y() -> Vec3<S> { Vec3::new(zero(), one(), zero()) }
|
||||||
|
#[inline] pub fn unit_z() -> Vec3<S> { Vec3::new(zero(), zero(), one()) }
|
||||||
|
|
||||||
/// Returns the cross product of the vector and `other`.
|
/// Returns the cross product of the vector and `other`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cross(&self, other: &Vec3<S>) -> Vec3<S> {
|
pub fn cross(&self, other: &Vec3<S>) -> Vec3<S> {
|
||||||
|
@ -222,6 +177,29 @@ impl<S: Primitive> Vec3<S> {
|
||||||
pub fn cross_self(&mut self, other: &Vec3<S>) {
|
pub fn cross_self(&mut self, other: &Vec3<S>) {
|
||||||
*self = self.cross(other)
|
*self = self.cross(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn extend(&self, w: S)-> Vec4<S> {
|
||||||
|
Vec4::new(self.x.clone(), self.y.clone(), self.z.clone(), w)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn truncate(&self)-> Vec2<S> {
|
||||||
|
Vec2::new(self.x.clone(), self.y.clone()) //ignore Z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Operations specific to numeric four-dimensional vectors.
|
||||||
|
impl<S: Primitive> Vec4<S> {
|
||||||
|
#[inline] pub fn unit_x() -> Vec4<S> { Vec4::new(one(), zero(), zero(), zero()) }
|
||||||
|
#[inline] pub fn unit_y() -> Vec4<S> { Vec4::new(zero(), one(), zero(), zero()) }
|
||||||
|
#[inline] pub fn unit_z() -> Vec4<S> { Vec4::new(zero(), zero(), one(), zero()) }
|
||||||
|
#[inline] pub fn unit_w() -> Vec4<S> { Vec4::new(zero(), zero(), zero(), one()) }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn truncate(&self)-> Vec3<S> {
|
||||||
|
Vec3::new(self.x.clone(), self.y.clone(), self.z.clone()) //ignore W
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specifies geometric operations for vectors. This is only implemented for
|
/// Specifies geometric operations for vectors. This is only implemented for
|
||||||
|
|
Loading…
Reference in a new issue