use core::num::{Zero, One, Algebraic, abs}; use core::rand::{Rand, Rng, RngUtil}; use std::cmp::FuzzyEq; use traits::dim::Dim; use traits::dot::Dot; use traits::cross::Cross; use traits::basis::Basis; use traits::norm::Norm; #[deriving(Eq)] pub struct Vec3 { x : T, y : T, z : T } pub fn Vec3(x: T, y: T, z: T) -> Vec3 { Vec3 {x: x, y: y, z: z} } impl Dim for Vec3 { fn dim() -> uint { 3 } } impl> Add, Vec3> for Vec3 { fn add(&self, other: &Vec3) -> Vec3 { Vec3(self.x + other.x, self.y + other.y, self.z + other.z) } } impl> Sub, Vec3> for Vec3 { fn sub(&self, other: &Vec3) -> Vec3 { Vec3(self.x - other.x, self.y - other.y, self.z - other.z) } } impl> Neg> for Vec3 { fn neg(&self) -> Vec3 { Vec3(-self.x, -self.y, -self.z) } } impl + Add + Algebraic> Dot for Vec3 { fn dot(&self, other : &Vec3) -> T { self.x * other.x + self.y * other.y + self.z * other.z } } impl + Add + Quot + Algebraic> Norm for Vec3 { fn sqnorm(&self) -> T { self.dot(self) } fn norm(&self) -> T { self.sqnorm().sqrt() } fn normalized(&self) -> Vec3 { let l = self.norm(); Vec3(self.x / l, self.y / l, self.z / l) } fn normalize(&mut self) -> T { let l = self.norm(); self.x /= l; self.y /= l; self.z /= l; l } } impl + Sub> Cross> for Vec3 { fn cross(&self, other : &Vec3) -> Vec3 { Vec3( self.y * other.z - self.z * other.y, self.z * other.x - self.x * other.z, self.x * other.y - self.y * other.x ) } } impl Zero for Vec3 { fn zero() -> Vec3 { let _0 = Zero::zero(); Vec3(_0, _0, _0) } fn is_zero(&self) -> bool { self.x.is_zero() && self.y.is_zero() && self.z.is_zero() } } impl + Ord + Mul + Sub + Add + Quot + Algebraic> Basis for Vec3 { fn canonical_basis() -> ~[Vec3] { // FIXME: this should be static ~[ Vec3(One::one(), Zero::zero(), Zero::zero()), Vec3(Zero::zero(), One::one(), Zero::zero()), Vec3(Zero::zero(), Zero::zero(), One::one()) ] } fn orthogonal_subspace_basis(&self) -> ~[Vec3] { let a = if (abs(self.x) > abs(self.y)) { Vec3(self.z, Zero::zero(), -self.x).normalized() } else { Vec3(Zero::zero(), -self.z, self.y).normalized() }; ~[ a, a.cross(self) ] } } impl> FuzzyEq for Vec3 { fn fuzzy_eq(&self, other: &Vec3) -> bool { self.x.fuzzy_eq(&other.x) && self.y.fuzzy_eq(&other.y) && self.z.fuzzy_eq(&other.z) } fn fuzzy_eq_eps(&self, other: &Vec3, epsilon: &T) -> bool { self.x.fuzzy_eq_eps(&other.x, epsilon) && self.y.fuzzy_eq_eps(&other.y, epsilon) && self.z.fuzzy_eq_eps(&other.z, epsilon) } } impl Rand for Vec3 { fn rand(rng: &R) -> Vec3 { Vec3(rng.gen(), rng.gen(), rng.gen()) } } impl ToStr for Vec3 { fn to_str(&self) -> ~str { ~"Vec3 " + "{ x : " + self.x.to_str() + ", y : " + self.y.to_str() + ", z : " + self.z.to_str() + " }" } }