use std::fmt;
use std::fmt::Display;
use std::ops;
#[derive(Debug, Clone, Copy)]
pub struct Vector3 {
pub x: f64,
pub y: f64,
pub z: f64
}
impl Default for Vector3 {
fn default() -> Self {
Vector3 { x: 0.0, y: 0.0, z: 0.0 }
}
}
impl Display for Vector3 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[x: {}, y: {}, z: {}]", self.x, self.y, self.z)
}
}
impl Vector3 {
pub fn new(x: f64, y: f64, z: f64) -> Self {
Vector3 { x: x, y: y, z: z }
}
pub fn set(&mut self, x: f64, y: f64, z: f64) {
self.x = x;
self.y = y;
self.z = z;
}
pub fn set_from_spherical(&mut self, azimuthal_angle: f64, polar_angle: f64) {
let cos_azim = azimuthal_angle.cos();
let sin_azim = azimuthal_angle.sin();
let cos_polar = polar_angle.cos();
let sin_polar = polar_angle.sin();
self.set(cos_azim * sin_polar, sin_azim * sin_polar, cos_polar);
}
pub fn set_random_direction(&mut self) {
let u = crate::random::random_double();
let v = crate::random::random_double();
let theta = std::f64::consts::PI * 2.0 * u;
let phi = (2.0 * v - 1.0).acos();
self.set_from_spherical(theta, phi);
}
pub fn length(&self) -> f64 {
(self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
}
pub fn length_squared(&self) -> f64 {
self.x * self.x + self.y * self.y + self.z * self.z
}
pub fn distance(&self, other: &Vector3) -> f64 {
((self.x - other.x) * (self.x - other.x) + (self.y - other.y) * (self.y - other.y) + (self.z - other.z) * (self.z - other.z)).sqrt()
}
pub fn distance_squared(&self, other: &Vector3) -> f64 {
(self.x - other.x) * (self.x - other.x) + (self.y - other.y) * (self.y - other.y) + (self.z - other.z) * (self.z - other.z)
}
pub fn dot(&self, other: &Vector3) -> f64 {
self.x * other.x + self.y * other.y + self.z * other.z
}
pub fn cross(&self, other: &Vector3) -> Vector3 {
Vector3::new(self.y * other.z - self.z * other.y, self.z * other.x - self.x * other.z, self.x * other.y - self.y * other.x)
}
pub fn lerp(&mut self, target: &Vector3, alpha: f64) {
self.x += alpha * (target.x - self.x);
self.y += alpha * (target.y - self.y);
self.z += alpha * (target.z - self.z);
}
pub fn nor(&mut self) {
let length = self.length_squared();
if length == 0.0 || length == 1.0 {
return;
}
self.multiply_scalar(1.0 / length.sqrt());
}
pub fn slerp(&mut self, target: &Vector3, alpha: f64) {
let dot = self.dot(target);
if dot > 0.9995 || dot < -0.9995 {
self.lerp(target, alpha);
return;
}
let theta0 = dot.acos();
let theta = theta0 * alpha;
let st = theta.sin();
let tx = target.x - self.x * dot;
let ty = target.y - self.y * dot;
let tz = target.z - self.z * dot;
let l2 = tx * tx + ty * ty + tz * tz;
let dl = st * (if l2 < 0.0001 { 1.0 } else { l2.sqrt() });
self.multiply_scalar(theta.cos());
self.add(&Vector3::new(tx * dl, ty * dl, tz * dl));
self.nor();
}
pub fn copy(&self) -> Self {
Vector3 { x: self.x, y: self.y, z: self.z }
}
pub fn add(&mut self, other: &Vector3) {
self.x += other.x;
self.y += other.y;
self.z += other.z;
}
pub fn subtract(&mut self, other: &Vector3) {
self.x -= other.x;
self.y -= other.y;
self.z -= other.z;
}
pub fn multiply(&mut self, other: &Vector3) {
self.x *= other.x;
self.y *= other.y;
self.z *= other.z;
}
pub fn divide(&mut self, other: &Vector3) {
self.x /= other.x;
self.y /= other.y;
self.z /= other.z;
}
pub fn add_scalar(&mut self, scalar: f64) {
self.x += scalar;
self.y += scalar;
self.z += scalar;
}
pub fn subtract_scalar(&mut self, scalar: f64) {
self.x -= scalar;
self.y -= scalar;
self.z -= scalar;
}
pub fn multiply_scalar(&mut self, scalar: f64) {
self.x *= scalar;
self.y *= scalar;
self.z *= scalar;
}
pub fn divide_scalar(&mut self, scalar: f64) {
self.x /= scalar;
self.y /= scalar;
self.z /= scalar;
}
}
impl ops::Add for Vector3 {
type Output = Vector3;
fn add(self, other: Vector3) -> Vector3 {
Vector3 { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z }
}
}
impl ops::Sub for Vector3 {
type Output = Vector3;
fn sub(self, other: Vector3) -> Vector3 {
Vector3 { x: self.x - other.x, y: self.y - other.y, z: self.z - other.z }
}
}
impl ops::Mul for Vector3 {
type Output = Vector3;
fn mul(self, other: Vector3) -> Vector3 {
Vector3 { x: self.x * other.x, y: self.y * other.y, z: self.z * other.z }
}
}
impl ops::Div for Vector3 {
type Output = Vector3;
fn div(self, other: Vector3) -> Vector3 {
Vector3 { x: self.x / other.x, y: self.y / other.y, z: self.z / other.z }
}
}
impl ops::Add<f64> for Vector3 {
type Output = Vector3;
fn add(self, scalar: f64) -> Vector3 {
Vector3 { x: self.x + scalar, y: self.y + scalar, z: self.z + scalar }
}
}
impl ops::Sub<f64> for Vector3 {
type Output = Vector3;
fn sub(self, scalar: f64) -> Vector3 {
Vector3 { x: self.x - scalar, y: self.y - scalar, z: self.z - scalar }
}
}
impl ops::Mul<f64> for Vector3 {
type Output = Vector3;
fn mul(self, scalar: f64) -> Vector3 {
Vector3 { x: self.x * scalar, y: self.y * scalar, z: self.z * scalar }
}
}
impl ops::Div<f64> for Vector3 {
type Output = Vector3;
fn div(self, scalar: f64) -> Vector3 {
Vector3 { x: self.x / scalar, y: self.y / scalar, z: self.z / scalar }
}
}
impl ops::AddAssign for Vector3 {
fn add_assign(&mut self, other: Vector3) {
self.add(&other);
}
}
impl ops::SubAssign for Vector3 {
fn sub_assign(&mut self, other: Vector3) {
self.subtract(&other);
}
}
impl ops::MulAssign for Vector3 {
fn mul_assign(&mut self, other: Vector3) {
self.multiply(&other);
}
}
impl ops::DivAssign for Vector3 {
fn div_assign(&mut self, other: Vector3) {
self.divide(&other);
}
}
impl ops::AddAssign<f64> for Vector3 {
fn add_assign(&mut self, scalar: f64) {
self.add_scalar(scalar);
}
}
impl ops::SubAssign<f64> for Vector3 {
fn sub_assign(&mut self, scalar: f64) {
self.subtract_scalar(scalar);
}
}
impl ops::MulAssign<f64> for Vector3 {
fn mul_assign(&mut self, scalar: f64) {
self.multiply_scalar(scalar);
}
}
impl ops::DivAssign<f64> for Vector3 {
fn div_assign(&mut self, scalar: f64) {
self.divide_scalar(scalar);
}
}
impl ops::Neg for Vector3 {
type Output = Vector3;
fn neg(self) -> Vector3 {
Vector3 { x: -self.x, y: -self.y, z: -self.z }
}
}