// 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. //! Abstract vector types use math::{Dimensioned, SwapComponents}; pub trait Vec: Dimensioned + SwapComponents {} /// Vectors with numeric components pub trait NumVec: Neg { pub fn add_t(&self, value: T) -> Self; pub fn sub_t(&self, value: T) -> Self; pub fn mul_t(&self, value: T) -> Self; pub fn div_t(&self, value: T) -> Self; pub fn rem_t(&self, value: T) -> Self; pub fn add_v(&self, other: &Self) -> Self; pub fn sub_v(&self, other: &Self) -> Self; pub fn mul_v(&self, other: &Self) -> Self; pub fn div_v(&self, other: &Self) -> Self; pub fn rem_v(&self, other: &Self) -> Self; pub fn neg_self(&mut self); pub fn add_self_t(&mut self, value: T); pub fn sub_self_t(&mut self, value: T); pub fn mul_self_t(&mut self, value: T); pub fn div_self_t(&mut self, value: T); pub fn rem_self_t(&mut self, value: T); pub fn add_self_v(&mut self, other: &Self); pub fn sub_self_v(&mut self, other: &Self); pub fn mul_self_v(&mut self, other: &Self); pub fn div_self_v(&mut self, other: &Self); pub fn rem_self_v(&mut self, other: &Self); pub fn dot(&self, other: &Self) -> T; } /// Vectors with floating point components pub trait FloatVec: NumVec + ApproxEq { pub fn magnitude2(&self) -> T; pub fn magnitude(&self) -> T; pub fn angle(&self, other: &Self) -> T; pub fn normalize(&self) -> Self; pub fn normalize_to(&self, magnitude: T) -> Self; pub fn lerp(&self, other: &Self, amount: T) -> Self; pub fn normalize_self(&mut self); pub fn normalize_self_to(&mut self, magnitude: T); pub fn lerp_self(&mut self, other: &Self, amount: T); } /// Vectors with orderable components pub trait OrdVec: Vec { pub fn lt_t(&self, value: T) -> BV; pub fn le_t(&self, value: T) -> BV; pub fn ge_t(&self, value: T) -> BV; pub fn gt_t(&self, value: T) -> BV; pub fn lt_v(&self, other: &Self) -> BV; pub fn le_v(&self, other: &Self) -> BV; pub fn ge_v(&self, other: &Self) -> BV; pub fn gt_v(&self, other: &Self) -> BV; } /// Vectors with components that can be tested for equality pub trait EqVec: Eq { pub fn eq_t(&self, value: T) -> BV; pub fn ne_t(&self, value: T) -> BV; pub fn eq_v(&self, other: &Self) -> BV; pub fn ne_v(&self, other: &Self) -> BV; } /// Vectors with boolean components pub trait BoolVec: Vec + Not { pub fn any(&self) -> bool; pub fn all(&self) -> bool; } #[deriving(Clone, Eq)] pub struct Vec2 { x: T, y: T } // GLSL-style type aliases pub type vec2 = Vec2; pub type dvec2 = Vec2; pub type bvec2 = Vec2; pub type ivec2 = Vec2; 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; pub trait ToVec2 { pub fn to_vec2(&self) -> Vec2; } pub trait AsVec2 { pub fn as_vec2<'a>(&'a self) -> &'a Vec2; pub fn as_mut_vec2<'a>(&'a mut self) -> &'a mut Vec2; } impl_dimensioned!(Vec2, T, 2) impl_swap_components!(Vec2) impl_approx!(Vec2 { x, y }) impl Vec2 { /// Construct a new vector from the supplied components. #[inline] pub fn new(x: T, y: T) -> Vec2 { Vec2 { x: x, y: y } } } impl Vec2 { /// Construct a new vector with each component set to `value`. #[inline] pub fn from_value(value: T) -> Vec2 { Vec2::new(value.clone(), value.clone()) } } impl ToVec3 for Vec2 { /// Converts the vector to a three-dimensional homogeneous vector: /// `[x, y] -> [x, y, 0]` pub fn to_vec3(&self) -> Vec3 { Vec3::new((*self).index(0).clone(), (*self).index(1).clone(), zero!(T)) } } /// Constants for two-dimensional vectors. impl Vec2 { /// Returns a two-dimensional vector with each component set to `1`. #[inline] pub fn identity() -> Vec2 { Vec2::new(one!(T), one!(T)) } /// Returns a two-dimensional vector with each component set to `0`. #[inline] pub fn zero() -> Vec2 { Vec2::new(zero!(T), zero!(T)) } /// Returns a zeroed two-dimensional vector with the `x` component set to `1`. #[inline] pub fn unit_x() -> Vec2 { Vec2::new(one!(T), zero!(T)) } /// Returns a zeroed two-dimensional vector with the `y` component set to `1`. #[inline] pub fn unit_y() -> Vec2 { Vec2::new(zero!(T), one!(T)) } } /// Numeric operations specific to two-dimensional vectors. impl Vec2 { /// The perpendicular dot product of the vector and `other`. #[inline] pub fn perp_dot(&self, other: &Vec2) -> T { (*self.index(0) * *other.index(1)) - (*self.index(1) * *other.index(0)) } } impl Vec for Vec2 {} impl NumVec for Vec2 { /// Returns a new vector with `value` added to each component. #[inline] pub fn add_t(&self, value: T) -> Vec2 { Vec2::new(*self.index(0) + value, *self.index(1) + value) } /// Returns a new vector with `value` subtracted from each component. #[inline] pub fn sub_t(&self, value: T) -> Vec2 { Vec2::new(*self.index(0) - value, *self.index(1) - value) } /// Returns the scalar multiplication of the vector with `value`. #[inline] pub fn mul_t(&self, value: T) -> Vec2 { Vec2::new(*self.index(0) * value, *self.index(1) * value) } /// Returns a new vector with each component divided by `value`. #[inline] pub fn div_t(&self, value: T) -> Vec2 { Vec2::new(*self.index(0) / value, *self.index(1) / value) } /// Returns the remainder of each component divided by `value`. #[inline] pub fn rem_t(&self, value: T) -> Vec2 { Vec2::new(*self.index(0) % value, *self.index(1) % value) } #[inline] pub fn add_v(&self, other: &Vec2) -> Vec2 { Vec2::new(*self.index(0) + *other.index(0), *self.index(1) + *other.index(1)) } #[inline] pub fn sub_v(&self, other: &Vec2) -> Vec2 { Vec2::new(*self.index(0) - *other.index(0), *self.index(1) - *other.index(1)) } #[inline] pub fn mul_v(&self, other: &Vec2) -> Vec2 { Vec2::new(*self.index(0) * *other.index(0), *self.index(1) * *other.index(1)) } #[inline] pub fn div_v(&self, other: &Vec2) -> Vec2 { Vec2::new(*self.index(0) / *other.index(0), *self.index(1) / *other.index(1)) } #[inline] pub fn rem_v(&self, other: &Vec2) -> Vec2 { Vec2::new(*self.index(0) % *other.index(0), *self.index(1) % *other.index(1)) } #[inline] pub fn neg_self(&mut self) { *self.index_mut(0) = -*self.index(0); *self.index_mut(1) = -*self.index(1); } #[inline] pub fn add_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) + value; *self.index_mut(1) = *self.index(1) + value; } #[inline] pub fn sub_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) - value; *self.index_mut(1) = *self.index(1) - value; } #[inline] pub fn mul_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) * value; *self.index_mut(1) = *self.index(1) * value; } #[inline] pub fn div_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) / value; *self.index_mut(1) = *self.index(1) / value; } #[inline] pub fn rem_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) % value; *self.index_mut(1) = *self.index(1) % value; } #[inline] pub fn add_self_v(&mut self, other: &Vec2) { *self.index_mut(0) = *self.index(0) + *other.index(0); *self.index_mut(1) = *self.index(1) + *other.index(1); } #[inline] pub fn sub_self_v(&mut self, other: &Vec2) { *self.index_mut(0) = *self.index(0) - *other.index(0); *self.index_mut(1) = *self.index(1) - *other.index(1); } #[inline] pub fn mul_self_v(&mut self, other: &Vec2) { *self.index_mut(0) = *self.index(0) * *other.index(0); *self.index_mut(1) = *self.index(1) * *other.index(1); } #[inline] pub fn div_self_v(&mut self, other: &Vec2) { *self.index_mut(0) = *self.index(0) / *other.index(0); *self.index_mut(1) = *self.index(1) / *other.index(1); } #[inline] pub fn rem_self_v(&mut self, other: &Vec2) { *self.index_mut(0) = *self.index(0) % *other.index(0); *self.index_mut(1) = *self.index(1) % *other.index(1); } /// Returns the dot product of the vector and `other`. #[inline] pub fn dot(&self, other: &Vec2) -> T { *self.index(0) * *other.index(0) + *self.index(1) * *other.index(1) } } impl Neg> for Vec2 { /// Returns the vector with each component negated. #[inline] pub fn neg(&self) -> Vec2 { Vec2::new(-*self.index(0), -*self.index(1)) } } impl FloatVec for Vec2 { /// Returns the squared magnitude of the vector. This does not perform a /// square root operation like in the `magnitude` method and can therefore /// be more efficient for comparing the magnitudes of two vectors. #[inline] pub fn magnitude2(&self) -> T { self.dot(self) } /// Returns the magnitude (length) of the vector. #[inline] pub fn magnitude(&self) -> T { self.magnitude2().sqrt() } /// Returns the angle between the vector and `other`. #[inline] pub fn angle(&self, other: &Vec2) -> T { self.perp_dot(other).atan2(&self.dot(other)) } /// Returns the result of normalizing the vector to a magnitude of `1`. #[inline] pub fn normalize(&self) -> Vec2 { self.normalize_to(one!(T)) } /// Returns the result of normalizing the vector to `magnitude`. #[inline] pub fn normalize_to(&self, magnitude: T) -> Vec2 { self.mul_t(magnitude / self.magnitude()) } /// Returns the result of linarly interpolating the magnitude of the vector /// to the magnitude of `other` by the specified amount. #[inline] pub fn lerp(&self, other: &Vec2, amount: T) -> Vec2 { self.add_v(&other.sub_v(self).mul_t(amount)) } /// Normalises the vector to a magnitude of `1`. #[inline] pub fn normalize_self(&mut self) { let rlen = self.magnitude().recip(); self.mul_self_t(rlen); } /// Normalizes the vector to `magnitude`. #[inline] pub fn normalize_self_to(&mut self, magnitude: T) { let n = magnitude / self.magnitude(); self.mul_self_t(n); } /// Linearly interpolates the magnitude of the vector to the magnitude of /// `other` by the specified amount. pub fn lerp_self(&mut self, other: &Vec2, amount: T) { let v = other.sub_v(self).mul_t(amount); self.add_self_v(&v); } } impl OrdVec> for Vec2 { #[inline] pub fn lt_t(&self, value: T) -> Vec2 { Vec2::new(*self.index(0) < value, *self.index(1) < value) } #[inline] pub fn le_t(&self, value: T) -> Vec2 { Vec2::new(*self.index(0) <= value, *self.index(1) <= value) } #[inline] pub fn ge_t(&self, value: T) -> Vec2 { Vec2::new(*self.index(0) >= value, *self.index(1) >= value) } #[inline] pub fn gt_t(&self, value: T) -> Vec2 { Vec2::new(*self.index(0) > value, *self.index(1) > value) } #[inline] pub fn lt_v(&self, other: &Vec2) -> Vec2 { Vec2::new(*self.index(0) < *other.index(0), *self.index(1) < *other.index(1)) } #[inline] pub fn le_v(&self, other: &Vec2) -> Vec2 { Vec2::new(*self.index(0) <= *other.index(0), *self.index(1) <= *other.index(1)) } #[inline] pub fn ge_v(&self, other: &Vec2) -> Vec2 { Vec2::new(*self.index(0) >= *other.index(0), *self.index(1) >= *other.index(1)) } #[inline] pub fn gt_v(&self, other: &Vec2) -> Vec2 { Vec2::new(*self.index(0) > *other.index(0), *self.index(1) > *other.index(1)) } } impl EqVec> for Vec2 { #[inline] pub fn eq_t(&self, value: T) -> Vec2 { Vec2::new(*self.index(0) == value, *self.index(1) == value) } #[inline] pub fn ne_t(&self, value: T) -> Vec2 { Vec2::new(*self.index(0) != value, *self.index(1) != value) } #[inline] pub fn eq_v(&self, other: &Vec2) -> Vec2 { Vec2::new(*self.index(0) == *other.index(0), *self.index(1) == *other.index(1)) } #[inline] pub fn ne_v(&self, other: &Vec2) -> Vec2 { Vec2::new(*self.index(0) != *other.index(0), *self.index(1) != *other.index(1)) } } impl BoolVec<[bool,..2]> for Vec2 { /// Returns `true` if any of the components of the vector are equal to /// `true`, otherwise `false`. #[inline] pub fn any(&self) -> bool { *self.index(0) || *self.index(1) } /// Returns `true` if _all_ of the components of the vector are equal to /// `true`, otherwise `false`. #[inline] pub fn all(&self) -> bool { *self.index(0) && *self.index(1) } } impl> Not> for Vec2 { pub fn not(&self) -> Vec2 { Vec2::new(!*self.index(0), !*self.index(1)) } } #[cfg(test)] mod vec2_tests { use math::vec::*; static A: Vec2 = Vec2 { x: 1.0, y: 2.0 }; static B: Vec2 = Vec2 { x: 3.0, y: 4.0 }; static F1: float = 1.5; static F2: float = 0.5; #[test] fn test_vec2() { let mut mut_a = A; assert_eq!(Vec2::new::(1.0, 2.0), A); assert_eq!(Vec2::from_value(1.0), Vec2::new::(1.0, 1.0)); assert_eq!(Vec2::zero(), Vec2::new::(0.0, 0.0)); assert_eq!(Vec2::unit_x(), Vec2::new::(1.0, 0.0)); assert_eq!(Vec2::unit_y(), Vec2::new::(0.0, 1.0)); assert_eq!(Vec2::identity(), Vec2::new::(1.0, 1.0)); *mut_a.index_mut(0) = 42.0; *mut_a.index_mut(1) = 43.0; assert_eq!(mut_a, Vec2::new::(42.0, 43.0)); mut_a = A; mut_a.swap(0, 1); assert_eq!(*mut_a.index(0), *A.index(1)); assert_eq!(*mut_a.index(1), *A.index(0)); mut_a = A; assert_eq!(A.x, 1.0); assert_eq!(A.y, 2.0); assert_eq!(*A.index(0), 1.0); assert_eq!(*A.index(1), 2.0); assert_eq!(-A, Vec2::new::(-1.0, -2.0)); assert_eq!(A.neg(), Vec2::new::(-1.0, -2.0)); assert_eq!(A.mul_t(F1), Vec2::new::( 1.5, 3.0)); assert_eq!(A.div_t(F2), Vec2::new::( 2.0, 4.0)); assert_eq!(A.add_v(&B), Vec2::new::( 4.0, 6.0)); assert_eq!(A.sub_v(&B), Vec2::new::( -2.0, -2.0)); assert_eq!(A.mul_v(&B), Vec2::new::( 3.0, 8.0)); assert_eq!(A.div_v(&B), Vec2::new::(1.0/3.0, 2.0/4.0)); mut_a.neg_self(); assert_eq!(mut_a, -A); mut_a = A; mut_a.mul_self_t(F1); assert_eq!(mut_a, A.mul_t(F1)); mut_a = A; mut_a.div_self_t(F2); assert_eq!(mut_a, A.div_t(F2)); mut_a = A; mut_a.add_self_v(&B); assert_eq!(mut_a, A.add_v(&B)); mut_a = A; mut_a.sub_self_v(&B); assert_eq!(mut_a, A.sub_v(&B)); mut_a = A; mut_a.mul_self_v(&B); assert_eq!(mut_a, A.mul_v(&B)); mut_a = A; mut_a.div_self_v(&B); assert_eq!(mut_a, A.div_v(&B)); } #[test] fn test_vec2_approx_eq() { assert!(!Vec2::new::(0.000001, 0.000001).approx_eq(&Vec2::new::(0.0, 0.0))); assert!(Vec2::new::(0.0000001, 0.0000001).approx_eq(&Vec2::new::(0.0, 0.0))); } static E_A: Vec2 = Vec2 { x: 5.0, y: 12.0 }; // (5, 12, 13) Pythagorean triple static E_B: Vec2 = Vec2 { x: 3.0, y: 4.0 }; // (3, 4, 5) Pythagorean triple #[test] fn test_vec2_euclidean() { assert_eq!(E_A.magnitude(), 13.0); assert_eq!(E_A.magnitude2(), 13.0 * 13.0); assert_eq!(E_B.magnitude(), 5.0); assert_eq!(E_B.magnitude2(), 5.0 * 5.0); assert!(Vec2::new::(1.0, 0.0).angle(&Vec2::new::(0.0, 1.0)).approx_eq(&Real::frac_pi_2())); assert!(Vec2::new::(10.0, 0.0).angle(&Vec2::new::(0.0, 5.0)).approx_eq(&Real::frac_pi_2())); assert!(Vec2::new::(-1.0, 0.0).angle(&Vec2::new::(0.0, 1.0)).approx_eq(&-Real::frac_pi_2::())); assert!(Vec2::new::(3.0, 4.0).normalize().approx_eq(&Vec2::new::(3.0/5.0, 4.0/5.0))); // TODO: test normalize_to, normalize_self, and normalize_self_to let c = Vec2::new::(-2.0, -1.0); let d = Vec2::new::( 1.0, 0.0); assert_eq!(c.lerp(&d, 0.75), Vec2::new::(0.250, -0.250)); let mut mut_c = c; mut_c.lerp_self(&d, 0.75); assert_eq!(mut_c, c.lerp(&d, 0.75)); } #[test] fn test_vec2_boolean() { let tf = Vec2::new(true, false); let ff = Vec2::new(false, false); let tt = Vec2::new(true, true); assert_eq!(tf.any(), true); assert_eq!(tf.all(), false); assert_eq!(!tf, Vec2::new(false, true)); assert_eq!(ff.any(), false); assert_eq!(ff.all(), false); assert_eq!(!ff, Vec2::new(true, true)); assert_eq!(tt.any(), true); assert_eq!(tt.all(), true); assert_eq!(!tt, Vec2::new(false, false)); } } #[deriving(Clone, Eq)] pub struct Vec3 { x: T, y: T, z: T } // GLSL-style type aliases pub type vec3 = Vec3; pub type dvec3 = Vec3; pub type bvec3 = Vec3; pub type ivec3 = Vec3; 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; pub trait ToVec3 { pub fn to_vec3(&self) -> Vec3; } pub trait AsVec3 { pub fn as_vec3<'a>(&'a self) -> &'a Vec3; pub fn as_mut_vec3<'a>(&'a mut self) -> &'a mut Vec3; } impl_dimensioned!(Vec3, T, 3) impl_swap_components!(Vec3) impl_approx!(Vec3 { x, y, z }) impl Vec3 { /// Construct a new vector from the supplied components. #[inline] pub fn new(x: T, y: T, z: T) -> Vec3 { Vec3 { x: x, y: y, z: z } } } impl Vec3 { /// Construct a new vector with each component set to `value`. #[inline] pub fn from_value(value: T) -> Vec3 { Vec3::new(value.clone(), value.clone(), value.clone()) } } impl ToVec4 for Vec3 { /// Converts the vector to a four-dimensional homogeneous vector: /// `[x, y, z] -> [x, y, z, 0]` pub fn to_vec4(&self) -> Vec4 { Vec4::new((*self).index(0).clone(), (*self).index(1).clone(), (*self).index(2).clone(), zero!(T)) } } /// Constants for three-dimensional vectors. impl Vec3 { /// Returns a three-dimensional vector with each component set to `1`. #[inline] pub fn identity() -> Vec3 { Vec3::new(one!(T), one!(T), one!(T)) } /// Returns a three-dimensional vector with each component set to `0`. #[inline] pub fn zero() -> Vec3 { Vec3::new(zero!(T), zero!(T), zero!(T)) } /// Returns a zeroed three-dimensional vector with the `x` component set to `1`. #[inline] pub fn unit_x() -> Vec3 { Vec3::new(one!(T), zero!(T), zero!(T)) } /// Returns a zeroed three-dimensional vector with the `y` component set to `1`. #[inline] pub fn unit_y() -> Vec3 { Vec3::new(zero!(T), one!(T), zero!(T)) } /// Returns a zeroed three-dimensional vector with the `z` component set to `1`. #[inline] pub fn unit_z() -> Vec3 { Vec3::new(zero!(T), zero!(T), one!(T)) } } /// Numeric operations specific to three-dimensional vectors. impl Vec3 { /// Returns the cross product of the vector and `other`. #[inline] pub fn cross(&self, other: &Vec3) -> Vec3 { Vec3::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))) } /// Calculates the cross product of the vector and `other`, then stores the /// result in `self`. #[inline] pub fn cross_self(&mut self, other: &Vec3) { *self = self.cross(other) } } impl Vec for Vec3 {} impl NumVec for Vec3 { /// Returns a new vector with `value` added to each component. #[inline] pub fn add_t(&self, value: T) -> Vec3 { Vec3::new(*self.index(0) + value, *self.index(1) + value, *self.index(2) + value) } /// Returns a new vector with `value` subtracted from each component. #[inline] pub fn sub_t(&self, value: T) -> Vec3 { Vec3::new(*self.index(0) - value, *self.index(1) - value, *self.index(2) - value) } /// Returns the scalar multiplication of the vector with `value`. #[inline] pub fn mul_t(&self, value: T) -> Vec3 { Vec3::new(*self.index(0) * value, *self.index(1) * value, *self.index(2) * value) } /// Returns a new vector with each component divided by `value`. #[inline] pub fn div_t(&self, value: T) -> Vec3 { Vec3::new(*self.index(0) / value, *self.index(1) / value, *self.index(2) / value) } /// Returns the remainder of each component divided by `value`. #[inline] pub fn rem_t(&self, value: T) -> Vec3 { Vec3::new(*self.index(0) % value, *self.index(1) % value, *self.index(2) % value) } #[inline] pub fn add_v(&self, other: &Vec3) -> Vec3 { Vec3::new(*self.index(0) + *other.index(0), *self.index(1) + *other.index(1), *self.index(2) + *other.index(2)) } #[inline] pub fn sub_v(&self, other: &Vec3) -> Vec3 { Vec3::new(*self.index(0) - *other.index(0), *self.index(1) - *other.index(1), *self.index(2) - *other.index(2)) } #[inline] pub fn mul_v(&self, other: &Vec3) -> Vec3 { Vec3::new(*self.index(0) * *other.index(0), *self.index(1) * *other.index(1), *self.index(2) * *other.index(2)) } #[inline] pub fn div_v(&self, other: &Vec3) -> Vec3 { Vec3::new(*self.index(0) / *other.index(0), *self.index(1) / *other.index(1), *self.index(2) / *other.index(2)) } #[inline] pub fn rem_v(&self, other: &Vec3) -> Vec3 { Vec3::new(*self.index(0) % *other.index(0), *self.index(1) % *other.index(1), *self.index(2) % *other.index(2)) } #[inline] pub 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] pub fn add_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) + value; *self.index_mut(1) = *self.index(1) + value; *self.index_mut(2) = *self.index(2) + value; } #[inline] pub fn sub_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) - value; *self.index_mut(1) = *self.index(1) - value; *self.index_mut(2) = *self.index(2) - value; } #[inline] pub fn mul_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) * value; *self.index_mut(1) = *self.index(1) * value; *self.index_mut(2) = *self.index(2) * value; } #[inline] pub fn div_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) / value; *self.index_mut(1) = *self.index(1) / value; *self.index_mut(2) = *self.index(2) / value; } #[inline] pub fn rem_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) % value; *self.index_mut(1) = *self.index(1) % value; *self.index_mut(2) = *self.index(2) % value; } #[inline] pub fn add_self_v(&mut self, other: &Vec3) { *self.index_mut(0) = *self.index(0) + *other.index(0); *self.index_mut(1) = *self.index(1) + *other.index(1); *self.index_mut(2) = *self.index(2) + *other.index(2); } #[inline] pub fn sub_self_v(&mut self, other: &Vec3) { *self.index_mut(0) = *self.index(0) - *other.index(0); *self.index_mut(1) = *self.index(1) - *other.index(1); *self.index_mut(2) = *self.index(2) - *other.index(2); } #[inline] pub fn mul_self_v(&mut self, other: &Vec3) { *self.index_mut(0) = *self.index(0) * *other.index(0); *self.index_mut(1) = *self.index(1) * *other.index(1); *self.index_mut(2) = *self.index(2) * *other.index(2); } #[inline] pub fn div_self_v(&mut self, other: &Vec3) { *self.index_mut(0) = *self.index(0) / *other.index(0); *self.index_mut(1) = *self.index(1) / *other.index(1); *self.index_mut(2) = *self.index(2) / *other.index(2); } #[inline] pub fn rem_self_v(&mut self, other: &Vec3) { *self.index_mut(0) = *self.index(0) % *other.index(0); *self.index_mut(1) = *self.index(1) % *other.index(1); *self.index_mut(2) = *self.index(2) % *other.index(2); } /// Returns the dot product of the vector and `other`. #[inline] pub fn dot(&self, other: &Vec3) -> T { *self.index(0) * *other.index(0) + *self.index(1) * *other.index(1) + *self.index(2) * *other.index(2) } } impl Neg> for Vec3 { /// Returns the vector with each component negated. #[inline] pub fn neg(&self) -> Vec3 { Vec3::new(-*self.index(0), -*self.index(1), -*self.index(2)) } } impl FloatVec for Vec3 { /// Returns the squared magnitude of the vector. This does not perform a /// square root operation like in the `magnitude` method and can therefore /// be more efficient for comparing the magnitudes of two vectors. #[inline] pub fn magnitude2(&self) -> T { self.dot(self) } /// Returns the magnitude (length) of the vector. #[inline] pub fn magnitude(&self) -> T { self.magnitude2().sqrt() } /// Returns the angle between the vector and `other`. #[inline] pub fn angle(&self, other: &Vec3) -> T { self.cross(other).magnitude().atan2(&self.dot(other)) } /// Returns the result of normalizing the vector to a magnitude of `1`. #[inline] pub fn normalize(&self) -> Vec3 { self.normalize_to(one!(T)) } /// Returns the result of normalizing the vector to `magnitude`. #[inline] pub fn normalize_to(&self, magnitude: T) -> Vec3 { self.mul_t(magnitude / self.magnitude()) } /// Returns the result of linarly interpolating the magnitude of the vector /// to the magnitude of `other` by the specified amount. #[inline] pub fn lerp(&self, other: &Vec3, amount: T) -> Vec3 { self.add_v(&other.sub_v(self).mul_t(amount)) } /// Normalises the vector to a magnitude of `1`. #[inline] pub fn normalize_self(&mut self) { let rlen = self.magnitude().recip(); self.mul_self_t(rlen); } /// Normalizes the vector to `magnitude`. #[inline] pub fn normalize_self_to(&mut self, magnitude: T) { let n = magnitude / self.magnitude(); self.mul_self_t(n); } /// Linearly interpolates the magnitude of the vector to the magnitude of /// `other` by the specified amount. pub fn lerp_self(&mut self, other: &Vec3, amount: T) { let v = other.sub_v(self).mul_t(amount); self.add_self_v(&v); } } impl OrdVec> for Vec3 { #[inline] pub fn lt_t(&self, value: T) -> Vec3 { Vec3::new(*self.index(0) < value, *self.index(1) < value, *self.index(2) < value) } #[inline] pub fn le_t(&self, value: T) -> Vec3 { Vec3::new(*self.index(0) <= value, *self.index(1) <= value, *self.index(2) <= value) } #[inline] pub fn ge_t(&self, value: T) -> Vec3 { Vec3::new(*self.index(0) >= value, *self.index(1) >= value, *self.index(2) >= value) } #[inline] pub fn gt_t(&self, value: T) -> Vec3 { Vec3::new(*self.index(0) > value, *self.index(1) > value, *self.index(2) > value) } #[inline] pub fn lt_v(&self, other: &Vec3) -> Vec3 { Vec3::new(*self.index(0) < *other.index(0), *self.index(1) < *other.index(1), *self.index(2) < *other.index(2)) } #[inline] pub fn le_v(&self, other: &Vec3) -> Vec3 { Vec3::new(*self.index(0) <= *other.index(0), *self.index(1) <= *other.index(1), *self.index(2) <= *other.index(2)) } #[inline] pub fn ge_v(&self, other: &Vec3) -> Vec3 { Vec3::new(*self.index(0) >= *other.index(0), *self.index(1) >= *other.index(1), *self.index(2) >= *other.index(2)) } #[inline] pub fn gt_v(&self, other: &Vec3) -> Vec3 { Vec3::new(*self.index(0) > *other.index(0), *self.index(1) > *other.index(1), *self.index(2) > *other.index(2)) } } impl EqVec> for Vec3 { #[inline] pub fn eq_t(&self, value: T) -> Vec3 { Vec3::new(*self.index(0) == value, *self.index(1) == value, *self.index(2) == value) } #[inline] pub fn ne_t(&self, value: T) -> Vec3 { Vec3::new(*self.index(0) != value, *self.index(1) != value, *self.index(2) != value) } #[inline] pub fn eq_v(&self, other: &Vec3) -> Vec3 { Vec3::new(*self.index(0) == *other.index(0), *self.index(1) == *other.index(1), *self.index(2) == *other.index(2)) } #[inline] pub fn ne_v(&self, other: &Vec3) -> Vec3 { Vec3::new(*self.index(0) != *other.index(0), *self.index(1) != *other.index(1), *self.index(2) != *other.index(2)) } } impl BoolVec<[bool,..3]> for Vec3 { /// Returns `true` if any of the components of the vector are equal to /// `true`, otherwise `false`. #[inline] pub fn any(&self) -> bool { *self.index(0) || *self.index(1) || *self.index(2) } /// Returns `true` if _all_ of the components of the vector are equal to /// `true`, otherwise `false`. #[inline] pub fn all(&self) -> bool { *self.index(0) && *self.index(1) && *self.index(2) } } impl> Not> for Vec3 { pub fn not(&self) -> Vec3 { Vec3::new(!*self.index(0), !*self.index(1), !*self.index(2)) } } #[cfg(test)] mod vec3_tests{ use math::vec::*; static A: Vec3 = Vec3 { x: 1.0, y: 2.0, z: 3.0 }; static B: Vec3 = Vec3 { x: 4.0, y: 5.0, z: 6.0 }; static F1: float = 1.5; static F2: float = 0.5; #[test] fn test_vec3() { let mut mut_a = A; assert_eq!(Vec3::new::(1.0, 2.0, 3.0), A); assert_eq!(Vec3::from_value(1.0), Vec3::new::(1.0, 1.0, 1.0)); assert_eq!(Vec3::zero(), Vec3::new::(0.0, 0.0, 0.0)); assert_eq!(Vec3::unit_x(), Vec3::new::(1.0, 0.0, 0.0)); assert_eq!(Vec3::unit_y(), Vec3::new::(0.0, 1.0, 0.0)); assert_eq!(Vec3::unit_z(), Vec3::new::(0.0, 0.0, 1.0)); assert_eq!(Vec3::identity(), Vec3::new::(1.0, 1.0, 1.0)); *mut_a.index_mut(0) = 42.0; *mut_a.index_mut(1) = 43.0; *mut_a.index_mut(2) = 44.0; assert_eq!(mut_a, Vec3::new::(42.0, 43.0, 44.0)); mut_a = A; mut_a.swap(0, 2); assert_eq!(*mut_a.index(0), *A.index(2)); assert_eq!(*mut_a.index(2), *A.index(0)); mut_a = A; mut_a.swap(1, 2); assert_eq!(*mut_a.index(1), *A.index(2)); assert_eq!(*mut_a.index(2), *A.index(1)); mut_a = A; assert_eq!(A.x, 1.0); assert_eq!(A.y, 2.0); assert_eq!(A.z, 3.0); assert_eq!(*A.index(0), 1.0); assert_eq!(*A.index(1), 2.0); assert_eq!(*A.index(2), 3.0); assert_eq!(A.cross(&B), Vec3::new::(-3.0, 6.0, -3.0)); mut_a.cross_self(&B); assert_eq!(mut_a, A.cross(&B)); mut_a = A; assert_eq!(-A, Vec3::new::(-1.0, -2.0, -3.0)); assert_eq!(A.neg(), Vec3::new::(-1.0, -2.0, -3.0)); assert_eq!(A.mul_t(F1), Vec3::new::( 1.5, 3.0, 4.5)); assert_eq!(A.div_t(F2), Vec3::new::( 2.0, 4.0, 6.0)); assert_eq!(A.add_v(&B), Vec3::new::( 5.0, 7.0, 9.0)); assert_eq!(A.sub_v(&B), Vec3::new::( -3.0, -3.0, -3.0)); assert_eq!(A.mul_v(&B), Vec3::new::( 4.0, 10.0, 18.0)); assert_eq!(A.div_v(&B), Vec3::new::(1.0/4.0, 2.0/5.0, 3.0/6.0)); mut_a.neg_self(); assert_eq!(mut_a, -A); mut_a = A; mut_a.mul_self_t(F1); assert_eq!(mut_a, A.mul_t(F1)); mut_a = A; mut_a.div_self_t(F2); assert_eq!(mut_a, A.div_t(F2)); mut_a = A; mut_a.add_self_v(&B); assert_eq!(mut_a, A.add_v(&B)); mut_a = A; mut_a.sub_self_v(&B); assert_eq!(mut_a, A.sub_v(&B)); mut_a = A; mut_a.mul_self_v(&B); assert_eq!(mut_a, A.mul_v(&B)); mut_a = A; mut_a.div_self_v(&B); assert_eq!(mut_a, A.div_v(&B)); } #[test] fn test_vec3_approx_eq() { assert!(!Vec3::new::(0.000001, 0.000001, 0.000001).approx_eq(&Vec3::new::(0.0, 0.0, 0.0))); assert!(Vec3::new::(0.0000001, 0.0000001, 0.0000001).approx_eq(&Vec3::new::(0.0, 0.0, 0.0))); } static E_A: Vec3 = Vec3 { x: 2.0, y: 3.0, z: 6.0 }; // (2, 3, 6, 7) Pythagorean quadruple static E_B: Vec3 = Vec3 { x: 1.0, y: 4.0, z: 8.0 }; // (1, 4, 8, 9) Pythagorean quadruple #[test] fn test_vec3_euclidean() { assert_eq!(E_A.magnitude(), 7.0); assert_eq!(E_A.magnitude2(), 7.0 * 7.0); assert_eq!(E_B.magnitude(), 9.0); assert_eq!(E_B.magnitude2(), 9.0 * 9.0); assert!(Vec3::new::(1.0, 0.0, 1.0).angle(&Vec3::new::(1.0, 1.0, 0.0)).approx_eq(&Real::frac_pi_3())); assert!(Vec3::new::(10.0, 0.0, 10.0).angle(&Vec3::new::(5.0, 5.0, 0.0)).approx_eq(&Real::frac_pi_3())); assert!(Vec3::new::(-1.0, 0.0, -1.0).angle(&Vec3::new::(1.0, -1.0, 0.0)).approx_eq(&(2.0 * Real::frac_pi_3()))); assert!(Vec3::new::(2.0, 3.0, 6.0).normalize().approx_eq(&Vec3::new::(2.0/7.0, 3.0/7.0, 6.0/7.0))); // TODO: test normalize_to, normalize_self, and normalize_self_to let c = Vec3::new::(-2.0, -1.0, 1.0); let d = Vec3::new::( 1.0, 0.0, 0.5); assert_eq!(c.lerp(&d, 0.75), Vec3::new::(0.250, -0.250, 0.625)); let mut mut_c = c; mut_c.lerp_self(&d, 0.75); assert_eq!(mut_c, c.lerp(&d, 0.75)); } #[test] fn test_vec3_boolean() { let tft = Vec3::new(true, false, true); let fff = Vec3::new(false, false, false); let ttt = Vec3::new(true, true, true); assert_eq!(tft.any(), true); assert_eq!(tft.all(), false); assert_eq!(!tft, Vec3::new(false, true, false)); assert_eq!(fff.any(), false); assert_eq!(fff.all(), false); assert_eq!(!fff, Vec3::new(true, true, true)); assert_eq!(ttt.any(), true); assert_eq!(ttt.all(), true); assert_eq!(!ttt, Vec3::new(false, false, false)); } } #[deriving(Clone, Eq)] pub struct Vec4 { x: T, y: T, z: T, w: T } // GLSL-style type aliases pub type vec4 = Vec4; pub type dvec4 = Vec4; pub type bvec4 = Vec4; pub type ivec4 = Vec4; 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; pub trait ToVec4 { pub fn to_vec4(&self) -> Vec4; } pub trait AsVec4 { pub fn as_vec4<'a>(&'a self) -> &'a Vec4; pub fn as_mut_vec4<'a>(&'a mut self) -> &'a mut Vec4; } impl_dimensioned!(Vec4, T, 4) impl_swap_components!(Vec4) impl_approx!(Vec4 { x, y, z, w }) impl Vec4 { /// Construct a new vector from the supplied components. #[inline] pub fn new(x: T, y: T, z: T, w: T) -> Vec4 { Vec4 { x: x, y: y, z: z, w: w } } } impl Vec4 { /// Construct a new vector with each component set to `value`. #[inline] pub fn from_value(value: T) -> Vec4 { Vec4::new(value.clone(), value.clone(), value.clone(), value.clone()) } } /// Constants for four-dimensional vectors. impl Vec4 { /// Returns a four-dimensional vector with each component set to `1`. #[inline] pub fn identity() -> Vec4 { Vec4::new(one!(T), one!(T), one!(T), one!(T)) } /// Returns a four-dimensional vector with each component set to `0`. #[inline] pub fn zero() -> Vec4 { Vec4::new(zero!(T), zero!(T), zero!(T), zero!(T)) } /// Returns a zeroed four-dimensional vector with the `x` component set to `1`. #[inline] pub fn unit_x() -> Vec4 { Vec4::new(one!(T), zero!(T), zero!(T), zero!(T)) } /// Returns a zeroed four-dimensional vector with the `y` component set to `1`. #[inline] pub fn unit_y() -> Vec4 { Vec4::new(zero!(T), one!(T), zero!(T), zero!(T)) } /// Returns a zeroed four-dimensional vector with the `z` component set to `1`. #[inline] pub fn unit_z() -> Vec4 { Vec4::new(zero!(T), zero!(T), one!(T), zero!(T)) } /// Returns a zeroed four-dimensional vector with the `w` component set to `1`. #[inline] pub fn unit_w() -> Vec4 { Vec4::new(zero!(T), zero!(T), zero!(T), one!(T)) } } impl Vec for Vec4 {} impl NumVec for Vec4 { /// Returns a new vector with `value` added to each component. #[inline] pub fn add_t(&self, value: T) -> Vec4 { Vec4::new(*self.index(0) + value, *self.index(1) + value, *self.index(2) + value, *self.index(3) + value) } /// Returns a new vector with `value` subtracted from each component. #[inline] pub fn sub_t(&self, value: T) -> Vec4 { Vec4::new(*self.index(0) - value, *self.index(1) - value, *self.index(2) - value, *self.index(3) - value) } /// Returns the scalar multiplication of the vector with `value`. #[inline] pub fn mul_t(&self, value: T) -> Vec4 { Vec4::new(*self.index(0) * value, *self.index(1) * value, *self.index(2) * value, *self.index(3) * value) } /// Returns a new vector with each component divided by `value`. #[inline] pub fn div_t(&self, value: T) -> Vec4 { Vec4::new(*self.index(0) / value, *self.index(1) / value, *self.index(2) / value, *self.index(3) / value) } /// Returns the remainder of each component divided by `value`. #[inline] pub fn rem_t(&self, value: T) -> Vec4 { Vec4::new(*self.index(0) % value, *self.index(1) % value, *self.index(2) % value, *self.index(3) % value) } #[inline] pub fn add_v(&self, other: &Vec4) -> Vec4 { Vec4::new(*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] pub fn sub_v(&self, other: &Vec4) -> Vec4 { Vec4::new(*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] pub fn mul_v(&self, other: &Vec4) -> Vec4 { Vec4::new(*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] pub fn div_v(&self, other: &Vec4) -> Vec4 { Vec4::new(*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] pub fn rem_v(&self, other: &Vec4) -> Vec4 { Vec4::new(*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] pub 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] pub fn add_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) + value; *self.index_mut(1) = *self.index(1) + value; *self.index_mut(2) = *self.index(2) + value; *self.index_mut(3) = *self.index(3) + value; } #[inline] pub fn sub_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) - value; *self.index_mut(1) = *self.index(1) - value; *self.index_mut(2) = *self.index(2) - value; *self.index_mut(3) = *self.index(3) - value; } #[inline] pub fn mul_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) * value; *self.index_mut(1) = *self.index(1) * value; *self.index_mut(2) = *self.index(2) * value; *self.index_mut(3) = *self.index(3) * value; } #[inline] pub fn div_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) / value; *self.index_mut(1) = *self.index(1) / value; *self.index_mut(2) = *self.index(2) / value; *self.index_mut(3) = *self.index(3) / value; } #[inline] pub fn rem_self_t(&mut self, value: T) { *self.index_mut(0) = *self.index(0) % value; *self.index_mut(1) = *self.index(1) % value; *self.index_mut(2) = *self.index(2) % value; *self.index_mut(3) = *self.index(3) % value; } #[inline] pub fn add_self_v(&mut self, other: &Vec4) { *self.index_mut(0) = *self.index(0) + *other.index(0); *self.index_mut(1) = *self.index(1) + *other.index(1); *self.index_mut(2) = *self.index(2) + *other.index(2); *self.index_mut(3) = *self.index(3) + *other.index(3); } #[inline] pub fn sub_self_v(&mut self, other: &Vec4) { *self.index_mut(0) = *self.index(0) - *other.index(0); *self.index_mut(1) = *self.index(1) - *other.index(1); *self.index_mut(2) = *self.index(2) - *other.index(2); *self.index_mut(3) = *self.index(3) - *other.index(3); } #[inline] pub fn mul_self_v(&mut self, other: &Vec4) { *self.index_mut(0) = *self.index(0) * *other.index(0); *self.index_mut(1) = *self.index(1) * *other.index(1); *self.index_mut(2) = *self.index(2) * *other.index(2); *self.index_mut(3) = *self.index(3) * *other.index(3); } #[inline] pub fn div_self_v(&mut self, other: &Vec4) { *self.index_mut(0) = *self.index(0) / *other.index(0); *self.index_mut(1) = *self.index(1) / *other.index(1); *self.index_mut(2) = *self.index(2) / *other.index(2); *self.index_mut(3) = *self.index(3) / *other.index(3); } #[inline] pub fn rem_self_v(&mut self, other: &Vec4) { *self.index_mut(0) = *self.index(0) % *other.index(0); *self.index_mut(1) = *self.index(1) % *other.index(1); *self.index_mut(2) = *self.index(2) % *other.index(2); *self.index_mut(3) = *self.index(3) % *other.index(3); } /// Returns the dot product of the vector and `other`. #[inline] pub 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) } } impl Neg> for Vec4 { /// Returns the vector with each component negated. #[inline] pub fn neg(&self) -> Vec4 { Vec4::new(-*self.index(0), -*self.index(1), -*self.index(2), -*self.index(3)) } } impl FloatVec for Vec4 { /// Returns the squared magnitude of the vector. This does not perform a /// square root operation like in the `magnitude` method and can therefore /// be more efficient for comparing the magnitudes of two vectors. #[inline] pub fn magnitude2(&self) -> T { self.dot(self) } /// Returns the magnitude (length) of the vector. #[inline] pub fn magnitude(&self) -> T { self.magnitude2().sqrt() } /// Returns the angle between the vector and `other`. #[inline] pub fn angle(&self, other: &Vec4) -> T { (self.dot(other) / (self.magnitude() * other.magnitude())).acos() } /// Returns the result of normalizing the vector to a magnitude of `1`. #[inline] pub fn normalize(&self) -> Vec4 { self.normalize_to(one!(T)) } /// Returns the result of normalizing the vector to `magnitude`. #[inline] pub fn normalize_to(&self, magnitude: T) -> Vec4 { self.mul_t(magnitude / self.magnitude()) } /// Returns the result of linarly interpolating the magnitude of the vector /// to the magnitude of `other` by the specified amount. #[inline] pub fn lerp(&self, other: &Vec4, amount: T) -> Vec4 { self.add_v(&other.sub_v(self).mul_t(amount)) } /// Normalises the vector to a magnitude of `1`. #[inline] pub fn normalize_self(&mut self) { let rlen = self.magnitude().recip(); self.mul_self_t(rlen); } /// Normalizes the vector to `magnitude`. #[inline] pub fn normalize_self_to(&mut self, magnitude: T) { let n = magnitude / self.magnitude(); self.mul_self_t(n); } /// Linearly interpolates the magnitude of the vector to the magnitude of /// `other` by the specified amount. pub fn lerp_self(&mut self, other: &Vec4, amount: T) { let v = other.sub_v(self).mul_t(amount); self.add_self_v(&v); } } impl OrdVec> for Vec4 { #[inline] pub fn lt_t(&self, value: T) -> Vec4 { Vec4::new(*self.index(0) < value, *self.index(1) < value, *self.index(2) < value, *self.index(3) < value) } #[inline] pub fn le_t(&self, value: T) -> Vec4 { Vec4::new(*self.index(0) <= value, *self.index(1) <= value, *self.index(2) <= value, *self.index(3) <= value) } #[inline] pub fn ge_t(&self, value: T) -> Vec4 { Vec4::new(*self.index(0) >= value, *self.index(1) >= value, *self.index(2) >= value, *self.index(3) >= value) } #[inline] pub fn gt_t(&self, value: T) -> Vec4 { Vec4::new(*self.index(0) > value, *self.index(1) > value, *self.index(2) > value, *self.index(3) > value) } #[inline] pub fn lt_v(&self, other: &Vec4) -> Vec4 { Vec4::new(*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] pub fn le_v(&self, other: &Vec4) -> Vec4 { Vec4::new(*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] pub fn ge_v(&self, other: &Vec4) -> Vec4 { Vec4::new(*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] pub fn gt_v(&self, other: &Vec4) -> Vec4 { Vec4::new(*self.index(0) > *other.index(0), *self.index(1) > *other.index(1), *self.index(2) > *other.index(2), *self.index(3) > *other.index(3)) } } impl EqVec> for Vec4 { #[inline] pub fn eq_t(&self, value: T) -> Vec4 { Vec4::new(*self.index(0) == value, *self.index(1) == value, *self.index(2) == value, *self.index(3) == value) } #[inline] pub fn ne_t(&self, value: T) -> Vec4 { Vec4::new(*self.index(0) != value, *self.index(1) != value, *self.index(2) != value, *self.index(3) != value) } #[inline] pub fn eq_v(&self, other: &Vec4) -> Vec4 { Vec4::new(*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] pub fn ne_v(&self, other: &Vec4) -> Vec4 { Vec4::new(*self.index(0) != *other.index(0), *self.index(1) != *other.index(1), *self.index(2) != *other.index(2), *self.index(3) != *other.index(3)) } } impl BoolVec<[bool,..4]> for Vec4 { /// Returns `true` if any of the components of the vector are equal to /// `true`, otherwise `false`. #[inline] pub fn any(&self) -> bool { *self.index(0) || *self.index(1) || *self.index(2) || *self.index(3) } /// Returns `true` if _all_ of the components of the vector are equal to /// `true`, otherwise `false`. #[inline] pub fn all(&self) -> bool { *self.index(0) && *self.index(1) && *self.index(2) && *self.index(3) } } impl> Not> for Vec4 { pub fn not(&self) -> Vec4 { Vec4::new(!*self.index(0), !*self.index(1), !*self.index(2), !*self.index(3)) } } #[cfg(test)] mod vec4_tests { use math::vec::*; static A: Vec4 = Vec4 { x: 1.0, y: 2.0, z: 3.0, w: 4.0 }; static B: Vec4 = Vec4 { x: 5.0, y: 6.0, z: 7.0, w: 8.0 }; static F1: float = 1.5; static F2: float = 0.5; #[test] fn test_vec4() { let mut mut_a = A; assert_eq!(Vec4::new::(1.0, 2.0, 3.0, 4.0), A); assert_eq!(Vec4::from_value(1.0), Vec4::new::(1.0, 1.0, 1.0, 1.0)); *mut_a.index_mut(0) = 42.0; *mut_a.index_mut(1) = 43.0; *mut_a.index_mut(2) = 44.0; *mut_a.index_mut(3) = 45.0; assert_eq!(mut_a, Vec4::new::(42.0, 43.0, 44.0, 45.0)); mut_a = A; mut_a.swap(0, 3); assert_eq!(*mut_a.index(0), *A.index(3)); assert_eq!(*mut_a.index(3), *A.index(0)); mut_a = A; mut_a.swap(1, 2); assert_eq!(*mut_a.index(1), *A.index(2)); assert_eq!(*mut_a.index(2), *A.index(1)); mut_a = A; assert_eq!(Vec4::zero(), Vec4::new::(0.0, 0.0, 0.0, 0.0)); assert_eq!(Vec4::unit_x(), Vec4::new::(1.0, 0.0, 0.0, 0.0)); assert_eq!(Vec4::unit_y(), Vec4::new::(0.0, 1.0, 0.0, 0.0)); assert_eq!(Vec4::unit_z(), Vec4::new::(0.0, 0.0, 1.0, 0.0)); assert_eq!(Vec4::unit_w(), Vec4::new::(0.0, 0.0, 0.0, 1.0)); assert_eq!(Vec4::identity(), Vec4::new::(1.0, 1.0, 1.0, 1.0)); assert_eq!(A.x, 1.0); assert_eq!(A.y, 2.0); assert_eq!(A.z, 3.0); assert_eq!(A.w, 4.0); assert_eq!(*A.index(0), 1.0); assert_eq!(*A.index(1), 2.0); assert_eq!(*A.index(2), 3.0); assert_eq!(*A.index(3), 4.0); assert_eq!(-A, Vec4::new::(-1.0, -2.0, -3.0, -4.0)); assert_eq!(A.neg(), Vec4::new::(-1.0, -2.0, -3.0, -4.0)); assert_eq!(A.mul_t(F1), Vec4::new::( 1.5, 3.0, 4.5, 6.0)); assert_eq!(A.div_t(F2), Vec4::new::( 2.0, 4.0, 6.0, 8.0)); assert_eq!(A.add_v(&B), Vec4::new::( 6.0, 8.0, 10.0, 12.0)); assert_eq!(A.sub_v(&B), Vec4::new::( -4.0, -4.0, -4.0, -4.0)); assert_eq!(A.mul_v(&B), Vec4::new::( 5.0, 12.0, 21.0, 32.0)); assert_eq!(A.div_v(&B), Vec4::new::(1.0/5.0, 2.0/6.0, 3.0/7.0, 4.0/8.0)); assert_eq!(A.dot(&B), 70.0); mut_a.neg_self(); assert_eq!(mut_a, -A); mut_a = A; mut_a.mul_self_t(F1); assert_eq!(mut_a, A.mul_t(F1)); mut_a = A; mut_a.div_self_t(F2); assert_eq!(mut_a, A.div_t(F2)); mut_a = A; mut_a.add_self_v(&B); assert_eq!(mut_a, A.add_v(&B)); mut_a = A; mut_a.sub_self_v(&B); assert_eq!(mut_a, A.sub_v(&B)); mut_a = A; mut_a.mul_self_v(&B); assert_eq!(mut_a, A.mul_v(&B)); mut_a = A; mut_a.div_self_v(&B); assert_eq!(mut_a, A.div_v(&B)); } #[test] fn test_vec4_approx_eq() { assert!(!Vec4::new::(0.000001, 0.000001, 0.000001, 0.000001).approx_eq(&Vec4::new::(0.0, 0.0, 0.0, 0.0))); assert!(Vec4::new::(0.0000001, 0.0000001, 0.0000001, 0.0000001).approx_eq(&Vec4::new::(0.0, 0.0, 0.0, 0.0))); } static E_A: Vec4 = Vec4 { x: 1.0, y: 2.0, z: 4.0, w: 10.0 }; // (1, 2, 4, 10, 11) Pythagorean quintuple static E_B: Vec4 = Vec4 { x: 1.0, y: 2.0, z: 8.0, w: 10.0 }; // (1, 2, 8, 10, 13) Pythagorean quintuple #[test] fn test_vec4_euclidean() { assert_eq!(E_A.magnitude(), 11.0); assert_eq!(E_A.magnitude2(), 11.0 * 11.0); assert_eq!(E_B.magnitude(), 13.0); assert_eq!(E_B.magnitude2(), 13.0 * 13.0); assert!(Vec4::new::(1.0, 0.0, 1.0, 0.0).angle(&Vec4::new::(0.0, 1.0, 0.0, 1.0)).approx_eq(&Real::frac_pi_2())); assert!(Vec4::new::(10.0, 0.0, 10.0, 0.0).angle(&Vec4::new::(0.0, 5.0, 0.0, 5.0)).approx_eq(&Real::frac_pi_2())); assert!(Vec4::new::(-1.0, 0.0, -1.0, 0.0).angle(&Vec4::new::(0.0, 1.0, 0.0, 1.0)).approx_eq(&Real::frac_pi_2())); assert!(Vec4::new::(1.0, 2.0, 4.0, 10.0).normalize().approx_eq(&Vec4::new::(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0))); // TODO: test normalize_to, normalize_self, and normalize_self_to let c = Vec4::new::(-2.0, -1.0, 1.0, 2.0); let d = Vec4::new::( 1.0, 0.0, 0.5, 1.0); assert_eq!(c.lerp(&d, 0.75), Vec4::new::(0.250, -0.250, 0.625, 1.250)); let mut mut_c = c; mut_c.lerp_self(&d, 0.75); assert_eq!(mut_c, c.lerp(&d, 0.75)); } #[test] fn test_vec4_boolean() { let tftf = Vec4::new(true, false, true, false); let ffff = Vec4::new(false, false, false, false); let tttt = Vec4::new(true, true, true, true); assert_eq!(tftf.any(), true); assert_eq!(tftf.all(), false); assert_eq!(!tftf, Vec4::new(false, true, false, true)); assert_eq!(ffff.any(), false); assert_eq!(ffff.all(), false); assert_eq!(!ffff, Vec4::new(true, true, true, true)); assert_eq!(tttt.any(), true); assert_eq!(tttt.all(), true); assert_eq!(!tttt, Vec4::new(false, false, false, false)); } }