vect 2.0.0

A library for providing vectors for game development that use a Unity-like API.
Documentation
//! Standard implementation of a 3D Vector.
//! 
//! This particular implementation uses 64-bit floating point numbers as its scalar components. 
//! It does so to ease compatibility with [piston.rs](https://www.piston.rs/), as that is what it uses by default for its scalars.

use std::ops;

use super::prelude::{Vector, Vector2};

#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
pub struct Vector3 {
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

impl Vector3 {

    /// Creates a new `Vector3`
    pub fn new(x: f64, y: f64, z: f64) -> Self {
        Vector3 { x, y, z }
    }

    /// Shorthand for `Vector3 { x: 0.0, y: 1.0, z: 0.0 }`
    pub fn up() -> Self {
        Vector3 {
            y: 1.0,
            .. Vector3::zero()
        }
    }

    /// Shorthand for `Vector3 { x: 0.0, y: -1.0, z: 0.0 }`
    pub fn down() -> Self {
        Vector3 {
            y: -1.0,
            .. Vector3::zero()
        }
    }

    /// Shorthand for `Vector3 { x: -1.0, y: 0.0, z: 0.0 }`
    pub fn left() -> Self {
        Vector3 {
            x: -1.0,
            .. Vector3::zero()
        }
    }

    /// Shorthand for `Vector3 { x: 1.0, y: 0.0, z: 0.0 }`
    pub fn right() -> Self {
        Vector3 {
            x: 1.0,
            .. Vector3::zero()
        }
    }

    /// Shorthand for `Vector3 {x: 0.0, y: 0.0, z: 1.0 }`
    pub fn forward() -> Self {
        Vector3 {
            z: 1.0,
            .. Vector3::zero()
        }
    }

    /// Shorthand for `Vector3 {x: 0.0, y: 0.0, z: -1.0 }`
    pub fn back() -> Self {
        Vector3 {
            z: -1.0,
            .. Vector3::zero()
        }
    }

    /// Defines the cross product between two vectors
    /// 
    /// Example:
    /// ```
    /// # use vect::prelude::*;
    /// let a = Vector3::new(3.0, -3.0, 1.0);
    /// let b = Vector3::new(4.0, 9.0, 2.0);
    /// let res = a.cross(b);
    /// let expected = Vector3::new(-15.0, -2.0, 39.0);
    /// 
    /// assert_eq!(res, expected);
    /// ```
    pub fn cross(self, other: Self) -> Self {
        Vector3 {
            x: self.y * other.z - self.z * other.y,
            y: self.z * other.x - self.x * other.z,
            z: self.x * other.y - self.y * other.x,
        }
    }

    /// Returns the distance between two vectors.
    /// 
    /// `a.distance(b)` is the same as `(a - b).magnitude()`.
    pub fn distance(&self, other: &Self) -> f64 {
        (*self - *other).magnitude()
    }
}

impl ops::Add for Vector3 {
    type Output = Self;

    /// Adds two vectors together
    fn add(self, other: Self) -> Self {
        Vector3 {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z,
        }
    }
}

impl ops::AddAssign for Vector3 {

    /// Adds two vectors together, and assigns the result into the first vector
    fn add_assign(&mut self, other: Self) {
        *self = *self + other;
    }
}

impl ops::Sub for Vector3 {
    type Output = Self;

    /// Subtracts two vectors from each other
    fn sub(self, other: Self) -> Self {
        Vector3 {
            x: self.x - other.x,
            y: self.y - other.y,
            z: self.z - other.z,
        }
    }
}

impl ops::SubAssign for Vector3 {

    /// Subtracts two vectors from each other, and assigns the result into the first vector
    fn sub_assign(&mut self, other: Self) {
        *self = *self - other;
    }
}

impl ops::Mul<f64> for Vector3 {
    type Output = Self;

    /// Multiplies a vector with a scalar
    fn mul(self, rhs: f64) -> Self {
        Vector3 {
            x: self.x * rhs,
            y: self.y * rhs,
            z: self.z * rhs,
        }
    }
}

impl ops::MulAssign<f64> for Vector3 {

    /// Multiplies a vector with a scalar, and assigns the result back into the vector
    fn mul_assign(&mut self, other: f64) {
        *self = *self * other;
    }
}

impl ops::Mul<Vector3> for f64 {

    /// Multiplies a scalar with a vector
    type Output = Vector3;

    fn mul(self, rhs: Vector3) -> Vector3 {
        Vector3 {
            x: self * rhs.x,
            y: self * rhs.y,
            z: self * rhs.z,
        }
    }
}

impl ops::Div<f64> for Vector3 {
    type Output = Self;

    /// Divides a vector by a scalar
    fn div(self, other: f64) -> Self {
        Vector3 {
            x: self.x / other,
            y: self.y / other,
            z: self.z / other,
        }
    }
}

impl ops::DivAssign<f64> for Vector3 {
    /// Divides a vector by a scalar, and assigns the result back into the vector
    fn div_assign(&mut self, other: f64) {
        *self = *self / other;
    }
}

impl ops::Div<Vector3> for f64 {
    type Output = Vector3;

    /// Divides a scalar by a vector
    fn div(self, other: Vector3) -> Vector3 {
        Vector3 {
            x: self / other.x,
            y: self / other.y,
            z: self / other.z,
        }
    }
}

impl Vector for Vector3 {
    type Scalar = f64;

    fn zero() -> Self {
        Vector3 {
            x: 0.0,
            y: 0.0,
            z: 0.0,
        }
    }

    fn magnitude(&self) -> Self::Scalar {
        self.sqr_magnitude().sqrt()
    }

    fn normalized(self) -> Self {
        let mag = self.magnitude();
        self / mag
    }

    fn normalize(&mut self) {
        *self = self.normalized();
    }

    fn sqr_magnitude(&self) -> Self::Scalar {
        (self.x.powi(2) + self.y.powi(2) + self.z.powi(2))
    }

    fn angle(&self, other: &Self) -> Self::Scalar {
        let dot = self.dot(other);
        let mag = self.magnitude() * other.magnitude();
        (dot / mag).acos()
    }

    fn clamp_magnitude(self, max_len: Self::Scalar) -> Self {
        if self.magnitude() > max_len {
            self / max_len
        } else {
            self
        }
    }

    fn dot(&self, other: &Self) -> Self::Scalar {
        self.x * other.x + self.y * other.y
    }

    fn scale(self, other: Self) -> Self {
        Vector3 {
            x: self.x * other.x,
            y: self.y * other.y,
            z: self.z * other.z,
        }
    }

    fn lerp(self, other: Self, t: Self::Scalar) -> Self {
        if t <= 0.0 {
            self
        } else if t >= 1.0 {
            other
        } else {
            self.lerp_unclamped(other, t)
        }
    }

    fn lerp_unclamped(self, other: Self, t: Self::Scalar) -> Self {
        (1.0 - t) * self + t * other
    }

    // fn move_towards(self, other: Self, max_distance_delta: Self::Scalar) -> Self {
    //     unimplemented!("Unsure how this is supposed to be implemented");
    // }

    /// Reflects the vector along the `normal` vector.
    /// 
    /// Example:
    /// 
    /// ```
    /// # use vect::prelude::*;
    /// let a = Vector3::new(1.0, 2.0, 0.0);
    /// let n = Vector3::up();
    /// let r = a.reflect(n);
    /// 
    /// assert_eq!(r, Vector3::new(1.0, -2.0, 0.0));
    /// ```
    fn reflect(self, normal: Self) -> Self {
        -2.0 * self.dot(&normal) * normal + self
    }
}

impl From<Vector2> for Vector3 {

    /// Creates a `Vector3` from a `Vector2`, adding a z component of 0
    fn from(vector: Vector2) -> Vector3 {
        Vector3 {
            x: vector.x,
            y: vector.y,
            z: 0.0,
        }
    }
}