#![allow(dead_code)]
use std::ops::{Add, Sub, Neg, Mul, Div};
use std::cmp::{PartialEq, PartialOrd, Ordering};
pub use num::{Zero, One, Num};
use num;
use super::float::Float;
use super::Vec2;
use super::unit::ToRad;
use std::fmt;
use clamp::Clamp;
use std::iter::IntoIterator;
#[derive(Copy, Clone, Debug)]
pub struct Vec3<T>(pub T, pub T, pub T);
impl<T: Copy> IntoIterator for Vec3<T> {
type Item = T;
type IntoIter = Vec3Iterator<T>;
fn into_iter(self) -> Self::IntoIter {
Vec3Iterator {
v: self,
index: 0,
}
}
}
pub struct Vec3Iterator<T> {
v: Vec3<T>,
index: usize,
}
impl<T: Copy> Iterator for Vec3Iterator<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
let result = match self.index {
0 => Some(self.v.0),
1 => Some(self.v.1),
2 => Some(self.v.2),
_ => return None,
};
self.index += 1;
result
}
}
impl<T: fmt::Display> fmt::Display for Vec3<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Vec3({}, {}, {})", self.0, self.1, self.2)
}
}
impl<T: One> One for Vec3<T> {
fn one() -> Self {
Vec3(T::one(), T::one(), T::one())
}
}
impl<T: Float> Vec3<T> {
pub fn almost_equal<N: num::Float>(self, other: Self, abs_tol: N) -> bool {
self.0.almost_equal(other.0, abs_tol) && self.1.almost_equal(other.1, abs_tol) &&
self.2.almost_equal(other.2, abs_tol)
}
pub fn is_nan(self) -> bool {
self.0.is_nan() && self.1.is_nan() && self.2.is_nan()
}
pub fn round(&self) -> Self {
Vec3(self.0.round(), self.1.round(), self.2.round())
}
}
impl<T: Add<Output = T>> Add for Vec3<T> {
type Output = Vec3<T>;
fn add(self, _rhs: Self) -> Self {
Vec3(self.0 + _rhs.0, self.1 + _rhs.1, self.2 + _rhs.2)
}
}
impl<T: Add<Output = T> + Copy> Vec3<T> {
pub fn add_scalar(self, _rhs: T) -> Self {
Vec3(self.0 + _rhs, self.1 + _rhs, self.2 + _rhs)
}
}
impl<T: Neg<Output = T>> Neg for Vec3<T> {
type Output = Self;
fn neg(self) -> Self {
Vec3(-self.0, -self.1, -self.2)
}
}
impl<T: Sub<Output = T>> Sub for Vec3<T> {
type Output = Self;
fn sub(self, _rhs: Self) -> Self {
Vec3(self.0 - _rhs.0, self.1 - _rhs.1, self.2 - _rhs.2)
}
}
impl<T: Sub<Output = T> + Copy> Vec3<T> {
pub fn sub_scalar(self, _rhs: T) -> Self {
Vec3(self.0 - _rhs, self.1 - _rhs, self.2 - _rhs)
}
}
impl<T: Mul<Output = T>> Mul for Vec3<T> {
type Output = Self;
fn mul(self, _rhs: Self) -> Self {
Vec3(self.0 * _rhs.0, self.1 * _rhs.1, self.2 * _rhs.2)
}
}
impl<T: Mul<Output = T> + Copy> Vec3<T> {
pub fn mul_scalar(self, _rhs: T) -> Self {
Vec3(self.0 * _rhs, self.1 * _rhs, self.2 * _rhs)
}
}
impl<T: Div<Output = T>> Div for Vec3<T> {
type Output = Vec3<T>;
fn div(self, _rhs: Self) -> Self {
Vec3(self.0 / _rhs.0, self.1 / _rhs.1, self.2 / _rhs.2)
}
}
impl<T: Div<Output = T> + Copy> Vec3<T> {
pub fn div_scalar(self, _rhs: T) -> Self {
Vec3(self.0 / _rhs, self.1 / _rhs, self.2 / _rhs)
}
}
impl<T: Clamp<Elem = T> + Copy> Clamp for Vec3<T> {
type Elem = T;
fn clamp(self, min: T, max: T) -> Self {
Vec3(self.0.clamp(min, max),
self.1.clamp(min, max),
self.2.clamp(min, max))
}
}
impl<T> AsRef<Vec3<T>> for Vec3<T> {
fn as_ref(&self) -> &Self {
self
}
}
impl<T: PartialOrd> Vec3<T> {
pub fn any_less<O: AsRef<Self>>(&self, other: O) -> bool {
let o = other.as_ref();
self.0 < o.0 || self.1 < o.1 || self.2 < o.2
}
pub fn any_greater<O: AsRef<Self>>(&self, other: O) -> bool {
let o = other.as_ref();
self.0 > o.0 || self.1 > o.1 || self.2 > o.2
}
}
impl<T: PartialEq> PartialEq for Vec3<T> {
fn eq(&self, _rhs: &Self) -> bool {
self.0 == _rhs.0 && self.1 == _rhs.1 && self.2 == _rhs.2
}
}
impl<T: PartialOrd> PartialOrd for Vec3<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if self.0 < other.0 && self.1 < other.1 && self.2 < other.2 {
Some(Ordering::Less)
} else if self.0 > other.0 && self.1 > other.1 && self.2 > other.2 {
Some(Ordering::Greater)
} else if self == other {
Some(Ordering::Equal)
} else {
None
}
}
}
impl<T: PartialOrd> Vec3<T> {
pub fn min(self, other: Self) -> Self {
Vec3(if self.0 < other.0 {
self.0
} else {
other.0
},
if self.1 < other.1 {
self.1
} else {
other.1
},
if self.2 < other.2 {
self.2
} else {
other.2
})
}
pub fn max(self, other: Self) -> Self {
Vec3(if self.0 > other.0 {
self.0
} else {
other.0
},
if self.1 > other.1 {
self.1
} else {
other.1
},
if self.2 > other.2 {
self.2
} else {
other.2
})
}
}
impl<T: Zero> Zero for Vec3<T> {
fn zero() -> Self {
Vec3(Zero::zero(), Zero::zero(), Zero::zero())
}
fn is_zero(&self) -> bool {
self.0.is_zero() && self.1.is_zero() && self.2.is_zero()
}
}
impl<T: Num + Copy> Vec3<T> {
pub fn dot(self, b: Self) -> T {
self.0 * b.0 + self.1 * b.1 + self.2 * b.2
}
pub fn length_sq(self) -> T {
self.dot(self)
}
}
impl<T: Float> Vec3<T> {
pub fn length(self) -> T {
self.length_sq().sqrt()
}
pub fn normalize(self) -> Option<Self> {
let length = self.length();
if length == T::zero() {
None
} else {
Some(self.div_scalar(length))
}
}
pub fn project(self, other: Self) -> Self {
other.mul_scalar(self.dot(other) / other.length_sq())
}
pub fn lerp(self, other: Self, t: T) -> Self {
self * other.mul_scalar(t)
}
}
impl<F, T> Vec3<T>
where F: Float,
T: Float + ToRad<Output = F>
{
pub fn cart_to_sphere(self) -> (F, Vec2<T>) {
let r = self.length();
let theta = (self.2 / r).acos();
let phi = self.1.atan2(self.0);
(r.to_rad().0, Vec2(theta, phi))
}
}
swizzle!(x, Vec3);
swizzle!(y, Vec3);
swizzle!(z, Vec3);
swizzle!(2, Vec3);
swizzle!(3, Vec3);