// Copyright 2013 The Lmath Developers. For a full listing of the authors, // refer to the AUTHORS file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use std::cast::transmute; use std::cmp::ApproxEq; use std::num::{Zero, One}; use num::NumAssign; /// The base generic vector trait. /// /// # Type parameters /// /// - `T`: The type of the components. This is intended to support boolean, /// integer, unsigned integer, and floating point types. pub trait BaseVec: Eq { /// The component of the vector at the index `i` fn index<'a>(&'a self, i: uint) -> &'a T; /// Construct the vector from a single value, copying it to each component fn from_value(value: T) -> Self; /// A pointer to the first component of the vector fn to_ptr(&self) -> *T; /// Get a mutable reference to the component at `i` fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T; /// Swap two components of the vector in place fn swap(&mut self, a: uint, b: uint); } /// A generic 2-dimensional vector pub trait BaseVec2: BaseVec { fn new(x: T, y: T) -> Self; } /// A generic 3-dimensional vector pub trait BaseVec3: BaseVec { fn new(x: T, y: T, z: T) -> Self; } /// A generic 4-dimensional vector pub trait BaseVec4: BaseVec { fn new(x: T, y: T, z: T, w: T) -> Self; } /// A vector with numeric components pub trait NumVec: BaseVec + Neg { /// The standard basis vector /// /// # Return value /// /// A vector with each component set to one fn identity() -> Self; /// The null vector /// /// # Return value /// /// A vector with each component set to zero fn zero() -> Self; /// True if the vector is equal to zero fn is_zero(&self) -> bool; /// The scalar multiplication of the vector and `value` fn mul_t(&self, value: T) -> Self; /// The scalar division of the vector and `value` fn div_t(&self, value: T) -> Self; /// Component-wise vector addition fn add_v(&self, other: &Self) -> Self; /// Component-wise vector subtraction fn sub_v(&self, other: &Self) -> Self; /// Component-wise vector multiplication fn mul_v(&self, other: &Self) -> Self; /// Component-wise vector division fn div_v(&self, other: &Self) -> Self; /// The dot product of the vector and `other` fn dot(&self, other: &Self) -> T; /// Negate the vector fn neg_self(&mut self); /// Multiply the vector by a scalar fn mul_self_t(&mut self, value: T); /// Divide the vector by a scalar fn div_self_t(&mut self, value: T); /// Set the vector to the component-wise vector sum fn add_self_v(&mut self, other: &Self); /// Set the vector to the component-wise vector difference fn sub_self_v(&mut self, other: &Self); /// Set the vector to the component-wise vector product fn mul_self_v(&mut self, other: &Self); /// Set the vector to the component-wise vector quotient fn div_self_v(&mut self, other: &Self); } /// A 2-dimensional vector with numeric components pub trait NumVec2: NumVec { fn unit_x() -> Self; fn unit_y() -> Self; /// The perp dot product of the vector and `other` fn perp_dot(&self, other: &Self) -> T; } /// A 3-dimensional vector with numeric components pub trait NumVec3: NumVec { fn unit_x() -> Self; fn unit_y() -> Self; fn unit_z() -> Self; /// The cross product of the vector and `other` fn cross(&self, other: &Self) -> Self; /// Set to the cross product of the vector and `other` fn cross_self(&mut self, other: &Self); } /// A 4-dimensional vector with numeric components pub trait NumVec4: NumVec { fn unit_x() -> Self; fn unit_y() -> Self; fn unit_z() -> Self; fn unit_w() -> Self; } pub trait ToHomogeneous { /// Convert to a homogenous coordinate fn to_homogeneous(&self) -> H; } /// A Euclidean (or Affine) vector /// /// # Type parameters /// /// - `T`: The type of the components. This should be a floating point type. pub trait AffineVec: NumVec { /// The squared length of the vector. This is useful for comparisons where /// the exact length does not need to be calculated. fn length2(&self) -> T; /// The length of the vector /// /// # Performance notes /// /// For instances where the exact length of the vector does not need to be /// known, for example for quaternion-quaternion length comparisons, /// it is advisable to use the `length2` method instead. fn length(&self) -> T; /// The squared distance between the vector and `other`. fn distance2(&self, other: &Self) -> T; /// The distance between the vector and `other` fn distance(&self, other: &Self) -> T; /// The angle between the vector and `other` in radians fn angle(&self, other: &Self) -> T; /// The normalized vector fn normalize(&self) -> Self; /// Set the length of the vector whilst preserving the direction fn normalize_to(&self, length: T) -> Self; /// Linearly intoperlate between the vector and `other` /// /// # Return value /// /// The intoperlated vector fn lerp(&self, other: &Self, amount: T) -> Self; /// Normalize the vector fn normalize_self(&mut self); /// Set the vector to a specified length whilst preserving the direction fn normalize_self_to(&mut self, length: T); /// Linearly intoperlate the vector towards `other` fn lerp_self(&mut self, other: &Self, amount: T); } /// Component-wise vector comparison methods /// /// The methods contained in this trait correspond to the relational functions /// mentioned in Section 8.7 of the [GLSL 4.30.6 specification] /// (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). pub trait OrdVec: BaseVec { /// Component-wise compare of `self < other` fn less_than(&self, other: &Self) -> BoolVec; /// Component-wise compare of `self <= other` fn less_than_equal(&self, other: &Self) -> BoolVec; /// Component-wise compare of `self > other` fn greater_than(&self, other: &Self) -> BoolVec; /// Component-wise compare of `self >= other` fn greater_than_equal(&self, other: &Self) -> BoolVec; } /// Component-wise equality comparison methods /// /// The methods contained in this trait correspond to the relational functions /// mentioned in Section 8.7 of the [GLSL 4.30.6 specification] /// (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). pub trait EqVec: BaseVec { /// Component-wise compare of `self == other` fn equal(&self, other: &Self) -> BoolVec; /// Component-wise compare of `self != other` fn not_equal(&self, other: &Self) -> BoolVec; } /// A vector with boolean components /// /// The methods contained in this trait correspond to the relational functions /// mentioned in Section 8.7 of the [GLSL 4.30.6 specification] /// (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). pub trait BoolVec: BaseVec { /// `true` if of any component is `true` fn any(&self) -> bool; /// `true` only if all components are `true` fn all(&self) -> bool; /// the component-wise logical complement fn not(&self) -> Self; } pub trait TrigVec: BaseVec { fn radians(&self) -> Self; fn degrees(&self) -> Self; // Triganometric functions fn sin(&self) -> Self; fn cos(&self) -> Self; fn tan(&self) -> Self; // Inverse triganometric functions fn asin(&self) -> Self; fn acos(&self) -> Self; fn atan(&self) -> Self; fn atan2(&self, other: Self) -> Self; // Hyperbolic triganometric functions fn sinh(&self) -> Self; fn cosh(&self) -> Self; fn tanh(&self) -> Self; // fn asinh() -> Self; // fn acosh() -> Self; // fn atanh() -> Self; } pub trait ExpVec: BaseVec { // Exponential functions fn pow_t(&self, n: Self) -> Self; fn pow_v(&self, n: T) -> Self; fn exp(&self) -> Self; fn exp2(&self) -> Self; fn ln(&self) -> Self; fn ln2(&self) -> Self; fn sqrt(&self) -> Self; fn inv_sqrt(&self) -> Self; } pub trait ApproxVec: BaseVec { // Whole-number approximation functions fn floor(&self) -> Self; fn trunc(&self) -> Self; fn round(&self) -> Self; // fn round_even(&self) -> Self; fn ceil(&self) -> Self; fn fract(&self) -> Self; } pub trait SignedVec: BaseVec { fn is_positive(&self) -> BV; fn is_negative(&self) -> BV; fn is_nonpositive(&self) -> BV; fn is_nonnegative(&self) -> BV; fn abs(&self) -> Self; fn sign(&self) -> Self; fn copysign(&self, other: Self) -> Self; } pub trait ExtentVec: BaseVec { fn min_v(&self, other: &Self) -> Self; fn max_v(&self, other: &Self) -> Self; fn clamp_v(&self, mn: &Self, mx: &Self) -> Self; fn min_t(&self, other: T) -> Self; fn max_t(&self, other: T) -> Self; fn clamp_t(&self, mn: T, mx: T) -> Self; } pub trait MixVec: BaseVec { // Functions for blending numbers together fn mix(&self, other: Self, value: Self) -> Self; fn smooth_step(&self, edge0: Self, edge1: Self) -> Self; fn step(&self, edge: Self) -> Self; } // Utility macros macro_rules! zip_vec2( ($a:ident[] $method:ident $b:ident[]) => ( BaseVec2::new($a.index(0).$method($b.index(0)), $a.index(1).$method($b.index(1))) ); ($a:ident[] $method:ident $b:ident) => ( BaseVec2::new($a.index(0).$method(&$b), $a.index(1).$method(&$b)) ); ) macro_rules! zip_vec3( ($a:ident[] $method:ident $b:ident[]) => ( BaseVec3::new($a.index(0).$method($b.index(0)), $a.index(1).$method($b.index(1)), $a.index(2).$method($b.index(2))) ); ($a:ident[] $method:ident $b:ident) => ( BaseVec3::new($a.index(0).$method(&$b), $a.index(1).$method(&$b), $a.index(2).$method(&$b)) ); ) macro_rules! zip_vec4( ($a:ident[] $method:ident $b:ident[]) => ( BaseVec4::new($a.index(0).$method($b.index(0)), $a.index(1).$method($b.index(1)), $a.index(2).$method($b.index(2)), $a.index(3).$method($b.index(3))) ); ($a:ident[] $method:ident $b:ident) => ( BaseVec4::new($a.index(0).$method(&$b), $a.index(1).$method(&$b), $a.index(2).$method(&$b), $a.index(3).$method(&$b)) ); ) macro_rules! zip_assign( ($a:ident[] $method:ident $b:ident[] ..2) => ({ $a.index_mut(0).$method($b.index(0)); $a.index_mut(1).$method($b.index(1)); }); ($a:ident[] $method:ident $b:ident[] ..3) => ({ zip_assign!($a[] $method $b[] ..2); $a.index_mut(2).$method($b.index(2)); }); ($a:ident[] $method:ident $b:ident[] ..4) => ({ zip_assign!($a[] $method $b[] ..3); $a.index_mut(3).$method($b.index(3)); }); ($a:ident[] $method:ident $b:ident ..2) => ({ $a.index_mut(0).$method(&$b); $a.index_mut(1).$method(&$b); }); ($a:ident[] $method:ident $b:ident ..3) => ({ zip_assign!($a[] $method $b ..2); $a.index_mut(2).$method(&$b); }); ($a:ident[] $method:ident $b:ident ..4) => ({ zip_assign!($a[] $method $b ..3); $a.index_mut(3).$method(&$b); }); ) /// A 2-dimensional vector /// /// # Type parameters /// /// - `T`: The type of the components. This is intended to support boolean, /// integer, unsigned integer, and floating point types. /// /// # Fields /// /// - `x`: the first component of the vector /// - `y`: the second component of the vector #[deriving(Eq)] pub struct Vec2 { x: T, y: T } impl BaseVec for Vec2 { #[inline(always)] fn index<'a>(&'a self, i: uint) -> &'a T { unsafe { &'a transmute::<&'a Vec2, &'a [T,..2]>(self)[i] } } #[inline(always)] fn from_value(value: T) -> Vec2 { BaseVec2::new(value, value) } #[inline(always)] fn to_ptr(&self) -> *T { unsafe { cast::transmute(self) } } #[inline(always)] fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { unsafe { &'a mut transmute::<&'a mut Vec2, &'a mut [T,..2]>(self)[i] } } #[inline(always)] fn swap(&mut self, a: uint, b: uint) { let tmp = *self.index(a); *self.index_mut(a) = *self.index(b); *self.index_mut(b) = tmp; } } impl BaseVec2 for Vec2 { #[inline(always)] fn new(x: T, y: T ) -> Vec2 { Vec2 { x: x, y: y } } } impl NumVec for Vec2 { #[inline(always)] fn identity() -> Vec2 { BaseVec2::new(One::one::(), One::one::()) } #[inline(always)] fn zero() -> Vec2 { BaseVec2::new(Zero::zero::(), Zero::zero::()) } #[inline(always)] fn is_zero(&self) -> bool { *self.index(0) == Zero::zero() && *self.index(1) == Zero::zero() } #[inline(always)] fn mul_t(&self, value: T) -> Vec2 { zip_vec2!(self[] mul value) } #[inline(always)] fn div_t(&self, value: T) -> Vec2 { zip_vec2!(self[] div value) } #[inline(always)] fn add_v(&self, other: &Vec2) -> Vec2 { zip_vec2!(self[] add other[]) } #[inline(always)] fn sub_v(&self, other: &Vec2) -> Vec2 { zip_vec2!(self[] sub other[]) } #[inline(always)] fn mul_v(&self, other: &Vec2) -> Vec2 { zip_vec2!(self[] mul other[]) } #[inline(always)] fn div_v(&self, other: &Vec2) -> Vec2 { zip_vec2!(self[] div other[]) } #[inline(always)] fn dot(&self, other: &Vec2) -> T { (*self.index(0)) * (*other.index(0)) + (*self.index(1)) * (*other.index(1)) } #[inline(always)] fn neg_self(&mut self) { *self.index_mut(0) = -self.index(0); *self.index_mut(1) = -self.index(1); } #[inline(always)] fn mul_self_t(&mut self, value: T) { zip_assign!(self[] mul_assign value ..2); } #[inline(always)] fn div_self_t(&mut self, value: T) { zip_assign!(self[] div_assign value ..2); } #[inline(always)] fn add_self_v(&mut self, other: &Vec2) { zip_assign!(self[] add_assign other[] ..2); } #[inline(always)] fn sub_self_v(&mut self, other: &Vec2) { zip_assign!(self[] sub_assign other[] ..2); } #[inline(always)] fn mul_self_v(&mut self, other: &Vec2) { zip_assign!(self[] mul_assign other[] ..2); } #[inline(always)] fn div_self_v(&mut self, other: &Vec2) { zip_assign!(self[] div_assign other[] ..2); } } impl Neg> for Vec2 { #[inline(always)] fn neg(&self) -> Vec2 { BaseVec2::new(-self.index(0), -self.index(1)) } } impl NumVec2 for Vec2 { #[inline(always)] fn unit_x() -> Vec2 { BaseVec2::new(One::one::(), Zero::zero::()) } #[inline(always)] fn unit_y() -> Vec2 { BaseVec2::new(Zero::zero::(), One::one::()) } #[inline(always)] fn perp_dot(&self, other: &Vec2) ->T { (*self.index(0) * *other.index(1)) - (*self.index(1) * *other.index(0)) } } impl ToHomogeneous> for Vec2 { #[inline(always)] fn to_homogeneous(&self) -> Vec3 { BaseVec3::new(self.x, self.y, Zero::zero()) } } impl AffineVec for Vec2 { #[inline(always)] fn length2(&self) -> T { self.dot(self) } #[inline(always)] fn length(&self) -> T { self.length2().sqrt() } #[inline(always)] fn distance2(&self, other: &Vec2) -> T { other.sub_v(self).length2() } #[inline(always)] fn distance(&self, other: &Vec2) -> T { other.distance2(self).sqrt() } #[inline(always)] fn angle(&self, other: &Vec2) -> T { self.perp_dot(other).atan2(self.dot(other)) } #[inline(always)] fn normalize(&self) -> Vec2 { self.mul_t(One::one::()/self.length()) } #[inline(always)] fn normalize_to(&self, length: T) -> Vec2 { self.mul_t(length / self.length()) } #[inline(always)] fn lerp(&self, other: &Vec2, amount: T) -> Vec2 { self.add_v(&other.sub_v(self).mul_t(amount)) } #[inline(always)] fn normalize_self(&mut self) { let n = One::one::() / self.length(); self.mul_self_t(n); } #[inline(always)] fn normalize_self_to(&mut self, length: T) { let n = length / self.length(); self.mul_self_t(n); } fn lerp_self(&mut self, other: &Vec2, amount: T) { let v = other.sub_v(self).mul_t(amount); self.add_self_v(&v); } } impl> ApproxEq for Vec2 { #[inline(always)] fn approx_epsilon() -> T { ApproxEq::approx_epsilon::() } #[inline(always)] fn approx_eq(&self, other: &Vec2) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } #[inline(always)] fn approx_eq_eps(&self, other: &Vec2, epsilon: &T) -> bool { self.index(0).approx_eq_eps(other.index(0), epsilon) && self.index(1).approx_eq_eps(other.index(1), epsilon) } } impl OrdVec> for Vec2 { #[inline(always)] fn less_than(&self, other: &Vec2) -> Vec2 { zip_vec2!(self[] lt other[]) } #[inline(always)] fn less_than_equal(&self, other: &Vec2) -> Vec2 { zip_vec2!(self[] le other[]) } #[inline(always)] fn greater_than(&self, other: &Vec2) -> Vec2 { zip_vec2!(self[] gt other[]) } #[inline(always)] fn greater_than_equal(&self, other: &Vec2) -> Vec2 { zip_vec2!(self[] ge other[]) } } impl EqVec> for Vec2 { #[inline(always)] fn equal(&self, other: &Vec2) -> Vec2 { zip_vec2!(self[] eq other[]) } #[inline(always)] fn not_equal(&self, other: &Vec2) -> Vec2 { zip_vec2!(self[] ne other[]) } } impl BoolVec for Vec2 { #[inline(always)] fn any(&self) -> bool { *self.index(0) || *self.index(1) } #[inline(always)] fn all(&self) -> bool { *self.index(0) && *self.index(1) } #[inline(always)] fn not(&self) -> Vec2 { BaseVec2::new(!*self.index(0), !*self.index(1)) } } // GLSL-style type aliases, corresponding to Section 4.1.5 of the [GLSL 4.30.6 specification] // (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). // a two-component single-precision floating-point vector pub type vec2 = Vec2; // a two-component double-precision floating-point vector pub type dvec2 = Vec2; // a two-component Boolean vector pub type bvec2 = Vec2; // a two-component signed integer vector pub type ivec2 = Vec2; // a two-component unsigned integer vector pub type uvec2 = Vec2; // Rust-style type aliases pub type Vec2f = Vec2; pub type Vec2f32 = Vec2; pub type Vec2f64 = Vec2; pub type Vec2i = Vec2; pub type Vec2i8 = Vec2; pub type Vec2i16 = Vec2; pub type Vec2i32 = Vec2; pub type Vec2i64 = Vec2; pub type Vec2u = Vec2; pub type Vec2u8 = Vec2; pub type Vec2u16 = Vec2; pub type Vec2u32 = Vec2; pub type Vec2u64 = Vec2; pub type Vec2b = Vec2; /// A 3-dimensional vector /// /// # Type parameters /// /// - `T`: The type of the components. This is intended to support boolean, /// integer, unsigned integer, and floating point types. /// /// # Fields /// /// - `x`: the first component of the vector /// - `y`: the second component of the vector /// - `z`: the third component of the vector #[deriving(Eq)] pub struct Vec3 { x: T, y: T, z: T } impl BaseVec for Vec3 { #[inline(always)] fn index<'a>(&'a self, i: uint) -> &'a T { unsafe { &'a transmute::<&'a Vec3, &'a [T,..3]>(self)[i] } } #[inline(always)] fn from_value(value: T) -> Vec3 { BaseVec3::new(value, value, value) } #[inline(always)] fn to_ptr(&self) -> *T { unsafe { cast::transmute(self) } } #[inline(always)] fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { unsafe { &mut transmute::<&'a mut Vec3, &'a mut [T,..3]>(self)[i] } } #[inline(always)] fn swap(&mut self, a: uint, b: uint) { let tmp = *self.index(a); *self.index_mut(a) = *self.index(b); *self.index_mut(b) = tmp; } } impl BaseVec3 for Vec3 { #[inline(always)] fn new(x: T, y: T, z: T) -> Vec3 { Vec3 { x: x, y: y, z: z } } } impl NumVec for Vec3 { #[inline(always)] fn identity() -> Vec3 { BaseVec3::new(One::one::(), One::one::(), One::one::()) } #[inline(always)] fn zero() -> Vec3 { BaseVec3::new(Zero::zero::(), Zero::zero::(), Zero::zero::()) } #[inline(always)] fn is_zero(&self) -> bool { *self.index(0) == Zero::zero() && *self.index(1) == Zero::zero() && *self.index(2) == Zero::zero() } #[inline(always)] fn mul_t(&self, value: T) -> Vec3 { zip_vec3!(self[] mul value) } #[inline(always)] fn div_t(&self, value: T) -> Vec3 { zip_vec3!(self[] div value) } #[inline(always)] fn add_v(&self, other: &Vec3) -> Vec3 { zip_vec3!(self[] add other[]) } #[inline(always)] fn sub_v(&self, other: &Vec3) -> Vec3 { zip_vec3!(self[] sub other[]) } #[inline(always)] fn mul_v(&self, other: &Vec3) -> Vec3 { zip_vec3!(self[] mul other[]) } #[inline(always)] fn div_v(&self, other: &Vec3) -> Vec3 { zip_vec3!(self[] div other[]) } #[inline(always)] fn dot(&self, other: &Vec3) -> T { (*self.index(0)) * (*other.index(0)) + (*self.index(1)) * (*other.index(1)) + (*self.index(2)) * (*other.index(2)) } #[inline(always)] fn neg_self(&mut self) { *self.index_mut(0) = -self.index(0); *self.index_mut(1) = -self.index(1); *self.index_mut(2) = -self.index(2); } #[inline(always)] fn mul_self_t(&mut self, value: T) { zip_assign!(self[] mul_assign value ..3); } #[inline(always)] fn div_self_t(&mut self, value: T) { zip_assign!(self[] div_assign value ..3); } #[inline(always)] fn add_self_v(&mut self, other: &Vec3) { zip_assign!(self[] add_assign other[] ..3); } #[inline(always)] fn sub_self_v(&mut self, other: &Vec3) { zip_assign!(self[] sub_assign other[] ..3); } #[inline(always)] fn mul_self_v(&mut self, other: &Vec3) { zip_assign!(self[] mul_assign other[] ..3); } #[inline(always)] fn div_self_v(&mut self, other: &Vec3) { zip_assign!(self[] div_assign other[] ..3); } } impl Neg> for Vec3 { #[inline(always)] fn neg(&self) -> Vec3 { BaseVec3::new(-self.index(0), -self.index(1), -self.index(2)) } } impl NumVec3 for Vec3 { #[inline(always)] fn unit_x() -> Vec3 { BaseVec3::new(One::one::(), Zero::zero::(), Zero::zero::()) } #[inline(always)] fn unit_y() -> Vec3 { BaseVec3::new(Zero::zero::(), One::one::(), Zero::zero::()) } #[inline(always)] fn unit_z() -> Vec3 { BaseVec3::new(Zero::zero::(), Zero::zero::(), One::one::()) } #[inline(always)] fn cross(&self, other: &Vec3) -> Vec3 { BaseVec3::new((*self.index(1) * *other.index(2)) - (*self.index(2) * *other.index(1)), (*self.index(2) * *other.index(0)) - (*self.index(0) * *other.index(2)), (*self.index(0) * *other.index(1)) - (*self.index(1) * *other.index(0))) } #[inline(always)] fn cross_self(&mut self, other: &Vec3) { *self = self.cross(other); } } impl ToHomogeneous> for Vec3 { #[inline(always)] fn to_homogeneous(&self) -> Vec4 { BaseVec4::new(self.x, self.y, self.z, Zero::zero()) } } impl AffineVec for Vec3 { #[inline(always)] fn length2(&self) -> T { self.dot(self) } #[inline(always)] fn length(&self) -> T { self.length2().sqrt() } #[inline(always)] fn distance2(&self, other: &Vec3) -> T { other.sub_v(self).length2() } #[inline(always)] fn distance(&self, other: &Vec3) -> T { other.distance2(self).sqrt() } #[inline(always)] fn angle(&self, other: &Vec3) -> T { self.cross(other).length().atan2(self.dot(other)) } #[inline(always)] fn normalize(&self) -> Vec3 { self.mul_t(One::one::()/self.length()) } #[inline(always)] fn normalize_to(&self, length: T) -> Vec3 { self.mul_t(length / self.length()) } #[inline(always)] fn lerp(&self, other: &Vec3, amount: T) -> Vec3 { self.add_v(&other.sub_v(self).mul_t(amount)) } #[inline(always)] fn normalize_self(&mut self) { let n = One::one::() / self.length(); self.mul_self_t(n); } #[inline(always)] fn normalize_self_to(&mut self, length: T) { let n = length / self.length(); self.mul_self_t(n); } fn lerp_self(&mut self, other: &Vec3, amount: T) { let v = other.sub_v(self).mul_t(amount); self.add_self_v(&v); } } impl> ApproxEq for Vec3 { #[inline(always)] fn approx_epsilon() -> T { ApproxEq::approx_epsilon::() } #[inline(always)] fn approx_eq(&self, other: &Vec3) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } #[inline(always)] fn approx_eq_eps(&self, other: &Vec3, epsilon: &T) -> bool { self.index(0).approx_eq_eps(other.index(0), epsilon) && self.index(1).approx_eq_eps(other.index(1), epsilon) && self.index(2).approx_eq_eps(other.index(2), epsilon) } } impl OrdVec> for Vec3 { #[inline(always)] fn less_than(&self, other: &Vec3) -> Vec3 { zip_vec3!(self[] lt other[]) } #[inline(always)] fn less_than_equal(&self, other: &Vec3) -> Vec3 { zip_vec3!(self[] le other[]) } #[inline(always)] fn greater_than(&self, other: &Vec3) -> Vec3 { zip_vec3!(self[] gt other[]) } #[inline(always)] fn greater_than_equal(&self, other: &Vec3) -> Vec3 { zip_vec3!(self[] ge other[]) } } impl EqVec> for Vec3 { #[inline(always)] fn equal(&self, other: &Vec3) -> Vec3 { zip_vec3!(self[] eq other[]) } #[inline(always)] fn not_equal(&self, other: &Vec3) -> Vec3 { zip_vec3!(self[] ne other[]) } } impl BoolVec for Vec3 { #[inline(always)] fn any(&self) -> bool { *self.index(0) || *self.index(1) || *self.index(2) } #[inline(always)] fn all(&self) -> bool { *self.index(0) && *self.index(1) && *self.index(2) } #[inline(always)] fn not(&self) -> Vec3 { BaseVec3::new(!*self.index(0), !*self.index(1), !*self.index(2)) } } // GLSL-style type aliases, corresponding to Section 4.1.5 of the [GLSL 4.30.6 specification] // (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). // a three-component single-precision floating-point vector pub type vec3 = Vec3; // a three-component double-precision floating-point vector pub type dvec3 = Vec3; // a three-component Boolean vector pub type bvec3 = Vec3; // a three-component signed integer vector pub type ivec3 = Vec3; // a three-component unsigned integer vector pub type uvec3 = Vec3; // Rust-style type aliases pub type Vec3f = Vec3; pub type Vec3f32 = Vec3; pub type Vec3f64 = Vec3; pub type Vec3i = Vec3; pub type Vec3i8 = Vec3; pub type Vec3i16 = Vec3; pub type Vec3i32 = Vec3; pub type Vec3i64 = Vec3; pub type Vec3u = Vec3; pub type Vec3u8 = Vec3; pub type Vec3u16 = Vec3; pub type Vec3u32 = Vec3; pub type Vec3u64 = Vec3; pub type Vec3b = Vec3; /// A 4-dimensional vector /// /// # Type parameters /// /// - `T`: The type of the components. This is intended to support boolean, /// integer, unsigned integer, and floating point types. /// /// # Fields /// /// - `x`: the first component of the vector /// - `y`: the second component of the vector /// - `z`: the third component of the vector /// - `w`: the fourth component of the vector #[deriving(Eq)] pub struct Vec4 { x: T, y: T, z: T, w: T } impl BaseVec for Vec4 { #[inline(always)] fn index<'a>(&'a self, i: uint) -> &'a T { unsafe { &'a transmute::<&'a Vec4, &'a [T,..4]>(self)[i] } } #[inline(always)] fn from_value(value: T) -> Vec4 { BaseVec4::new(value, value, value, value) } #[inline(always)] fn to_ptr(&self) -> *T { unsafe { cast::transmute(self) } } #[inline(always)] fn index_mut<'a>(&'a mut self, i: uint) -> &'a mut T { unsafe { &'a mut transmute::< &'a mut Vec4, &'a mut [T,..4]>(self)[i] } } #[inline(always)] fn swap(&mut self, a: uint, b: uint) { let tmp = *self.index(a); *self.index_mut(a) = *self.index(b); *self.index_mut(b) = tmp; } } impl BaseVec4 for Vec4 { #[inline(always)] fn new(x: T, y: T, z: T, w: T) -> Vec4 { Vec4 { x: x, y: y, z: z, w: w } } } impl NumVec for Vec4 { #[inline(always)] fn identity() -> Vec4 { BaseVec4::new(One::one::(), One::one::(), One::one::(), One::one::()) } #[inline(always)] fn zero() -> Vec4 { BaseVec4::new(Zero::zero::(), Zero::zero::(), Zero::zero::(), Zero::zero::()) } #[inline(always)] fn is_zero(&self) -> bool { *self.index(0) == Zero::zero() && *self.index(1) == Zero::zero() && *self.index(2) == Zero::zero() && *self.index(3) == Zero::zero() } #[inline(always)] fn mul_t(&self, value: T) -> Vec4 { zip_vec4!(self[] mul value) } #[inline(always)] fn div_t(&self, value: T) -> Vec4 { zip_vec4!(self[] div value) } #[inline(always)] fn add_v(&self, other: &Vec4) -> Vec4 { zip_vec4!(self[] add other[]) } #[inline(always)] fn sub_v(&self, other: &Vec4) -> Vec4 { zip_vec4!(self[] sub other[]) } #[inline(always)] fn mul_v(&self, other: &Vec4) -> Vec4 { zip_vec4!(self[] mul other[]) } #[inline(always)] fn div_v(&self, other: &Vec4) -> Vec4 { zip_vec4!(self[] div other[]) } #[inline(always)] fn dot(&self, other: &Vec4) -> T { (*self.index(0)) * (*other.index(0)) + (*self.index(1)) * (*other.index(1)) + (*self.index(2)) * (*other.index(2)) + (*self.index(3)) * (*other.index(3)) } #[inline(always)] fn neg_self(&mut self) { *self.index_mut(0) = -self.index(0); *self.index_mut(1) = -self.index(1); *self.index_mut(2) = -self.index(2); *self.index_mut(3) = -self.index(3); } #[inline(always)] fn mul_self_t(&mut self, value: T) { zip_assign!(self[] mul_assign value ..4); } #[inline(always)] fn div_self_t(&mut self, value: T) { zip_assign!(self[] div_assign value ..4); } #[inline(always)] fn add_self_v(&mut self, other: &Vec4) { zip_assign!(self[] add_assign other[] ..4); } #[inline(always)] fn sub_self_v(&mut self, other: &Vec4) { zip_assign!(self[] sub_assign other[] ..4); } #[inline(always)] fn mul_self_v(&mut self, other: &Vec4) { zip_assign!(self[] mul_assign other[] ..4); } #[inline(always)] fn div_self_v(&mut self, other: &Vec4) { zip_assign!(self[] div_assign other[] ..4); } } impl Neg> for Vec4 { #[inline(always)] fn neg(&self) -> Vec4 { BaseVec4::new(-self.index(0), -self.index(1), -self.index(2), -self.index(3)) } } impl NumVec4 for Vec4 { #[inline(always)] fn unit_x() -> Vec4 { BaseVec4::new(One::one::(), Zero::zero::(), Zero::zero::(), Zero::zero::()) } #[inline(always)] fn unit_y() -> Vec4 { BaseVec4::new(Zero::zero::(), One::one::(), Zero::zero::(), Zero::zero::()) } #[inline(always)] fn unit_z() -> Vec4 { BaseVec4::new(Zero::zero::(), Zero::zero::(), One::one::(), Zero::zero::()) } #[inline(always)] fn unit_w() -> Vec4 { BaseVec4::new(Zero::zero::(), Zero::zero::(), Zero::zero::(), One::one::()) } } impl AffineVec for Vec4 { #[inline(always)] fn length2(&self) -> T { self.dot(self) } #[inline(always)] fn length(&self) -> T { self.length2().sqrt() } #[inline(always)] fn distance2(&self, other: &Vec4) -> T { other.sub_v(self).length2() } #[inline(always)] fn distance(&self, other: &Vec4) -> T { other.distance2(self).sqrt() } #[inline(always)] fn angle(&self, other: &Vec4) -> T { (self.dot(other) / (self.length() * other.length())).acos() } #[inline(always)] fn normalize(&self) -> Vec4 { self.mul_t(One::one::()/self.length()) } #[inline(always)] fn normalize_to(&self, length: T) -> Vec4 { self.mul_t(length / self.length()) } #[inline(always)] fn lerp(&self, other: &Vec4, amount: T) -> Vec4 { self.add_v(&other.sub_v(self).mul_t(amount)) } #[inline(always)] fn normalize_self(&mut self) { let n = One::one::() / self.length(); self.mul_self_t(n); } #[inline(always)] fn normalize_self_to(&mut self, length: T) { let n = length / self.length(); self.mul_self_t(n); } fn lerp_self(&mut self, other: &Vec4, amount: T) { let v = other.sub_v(self).mul_t(amount); self.add_self_v(&v); } } impl> ApproxEq for Vec4 { #[inline(always)] fn approx_epsilon() -> T { ApproxEq::approx_epsilon::() } #[inline(always)] fn approx_eq(&self, other: &Vec4) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) } #[inline(always)] fn approx_eq_eps(&self, other: &Vec4, epsilon: &T) -> bool { self.index(0).approx_eq_eps(other.index(0), epsilon) && self.index(1).approx_eq_eps(other.index(1), epsilon) && self.index(2).approx_eq_eps(other.index(2), epsilon) && self.index(3).approx_eq_eps(other.index(3), epsilon) } } impl OrdVec> for Vec4 { #[inline(always)] fn less_than(&self, other: &Vec4) -> Vec4 { zip_vec4!(self[] lt other[]) } #[inline(always)] fn less_than_equal(&self, other: &Vec4) -> Vec4 { zip_vec4!(self[] le other[]) } #[inline(always)] fn greater_than(&self, other: &Vec4) -> Vec4 { zip_vec4!(self[] gt other[]) } #[inline(always)] fn greater_than_equal(&self, other: &Vec4) -> Vec4 { zip_vec4!(self[] ge other[]) } } impl EqVec> for Vec4 { #[inline(always)] fn equal(&self, other: &Vec4) -> Vec4 { zip_vec4!(self[] eq other[]) } #[inline(always)] fn not_equal(&self, other: &Vec4) -> Vec4 { zip_vec4!(self[] ne other[]) } } impl BoolVec for Vec4 { #[inline(always)] fn any(&self) -> bool { *self.index(0) || *self.index(1) || *self.index(2) || *self.index(3) } #[inline(always)] fn all(&self) -> bool { *self.index(0) && *self.index(1) && *self.index(2) && *self.index(3) } #[inline(always)] fn not(&self) -> Vec4 { BaseVec4::new(!*self.index(0), !*self.index(1), !*self.index(2), !*self.index(3)) } } // GLSL-style type aliases, corresponding to Section 4.1.5 of the [GLSL 4.30.6 specification] // (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). // a four-component single-precision floating-point vector pub type vec4 = Vec4; // a four-component double-precision floating-point vector pub type dvec4 = Vec4; // a four-component Boolean vector pub type bvec4 = Vec4; // a four-component signed integer vector pub type ivec4 = Vec4; // a four-component unsigned integer vector pub type uvec4 = Vec4; // Rust-style type aliases pub type Vec4f = Vec4; pub type Vec4f32 = Vec4; pub type Vec4f64 = Vec4; pub type Vec4i = Vec4; pub type Vec4i8 = Vec4; pub type Vec4i16 = Vec4; pub type Vec4i32 = Vec4; pub type Vec4i64 = Vec4; pub type Vec4u = Vec4; pub type Vec4u8 = Vec4; pub type Vec4u16 = Vec4; pub type Vec4u32 = Vec4; pub type Vec4u64 = Vec4; pub type Vec4b = Vec4;