use crate::flt::{Flt, Real}; use super::Vec3u; use serde::{Serialize, Deserialize}; use std::convert::From; use std::iter::Sum; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub}; fn round(f: Real) -> Real { Real::from_inner(f.into_inner().round()) } #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)] pub struct Vec2 { pub x: Real, pub y: Real, } impl Add for Vec2 { type Output = Vec2; fn add(self, other: Vec2) -> Vec2 { let mut ret = self.clone(); ret += other; ret } } impl AddAssign for Vec2 { fn add_assign(&mut self, other: Vec2) { self.x += other.x; self.y += other.y; } } impl Neg for Vec2 { type Output = Vec2; fn neg(self) -> Vec2 { Vec2 { x: -self.x, y: -self.y, } } } impl Sub for Vec2 { type Output = Vec2; fn sub(self, other: Vec2) -> Vec2 { self + (-other) } } impl Mul for Vec2 { type Output = Vec2; fn mul(self, s: Flt) -> Vec2 { Vec2 { x: self.x * s, y: self.y * s, } } } impl Into<(Flt, Flt)> for Vec2 { fn into(self) -> (Flt, Flt) { (self.x(), self.y()) } } impl Into<(Real, Real)> for Vec2 { fn into(self) -> (Real, Real) { (self.x, self.y) } } impl Vec2 { pub fn new(x: Flt, y: Flt) -> Self { Self { x: x.into(), y: y.into(), } } pub fn x(&self) -> Flt { self.x.into() } pub fn y(&self) -> Flt { self.y.into() } pub fn round(&self) -> Vec2 { Vec2 { x: round(self.x), y: round(self.y), } } pub fn distance_sq(&self, other: Self) -> Flt { (*self - other).mag_sq() } pub fn mag_sq(&self) -> Flt { (self.x*self.x + self.y*self.y).into() } pub fn mag(&self) -> Flt { self.mag_sq().sqrt() } pub fn with_mag(&self, new_mag: Flt) -> Vec2 { if new_mag == 0.0 { // avoid div-by-zero if self.mag() == 0 and new_mag == 0 Vec2::new(0.0, 0.0) } else { let scale = Real::from_inner(new_mag) / self.mag(); self.clone() * scale.into_inner() } } } #[derive(Copy, Clone, Debug, Default, PartialEq, Serialize, Deserialize)] pub struct Vec3 { pub(crate) x: Real, pub(crate) y: Real, pub(crate) z: Real, } impl Vec3 { pub fn new(x: Flt, y: Flt, z: Flt) -> Self { Self { x: x.into(), y: y.into(), z: z.into() } } pub fn unit() -> Self { Self::new(1.0, 1.0, 1.0) } pub fn zero() -> Self { Self::new(0.0, 0.0, 0.0) } pub fn x(&self) -> Flt { self.x.into() } pub fn y(&self) -> Flt { self.y.into() } pub fn z(&self) -> Flt { self.z.into() } pub fn xy(&self) -> Vec2 { Vec2::new(self.x(), self.y()) } pub fn mag(&self) -> Flt { let Vec3 { x, y, z } = *self; (x*x + y*y + z*z).into_inner().sqrt() } pub fn component_sum(&self) -> Flt { (self.x + self.y + self.z).into() } pub fn dot(&self, other: Self) -> Flt { self.elem_mul(other).component_sum() } pub fn cross(&self, other: Self) -> Self { // det( i j k | // | s.x s.y s.z | // | o.x o.y o.z ) let x = self.y * other.z - other.y * self.z; let y = other.z * self.z - self.x * other.z; let z = self.x * other.y - other.x * self.y; Self { x, y, z } } /// Perform element-wise multiplication with `other`. pub fn elem_mul(&self, other: Self) -> Self { Self { x: self.x * other.x, y: self.y * other.y, z: self.z * other.z, } } /// Perform element-wise division with `other`. pub fn elem_div(&self, other: Self) -> Self { Self { x: self.x / other.x, y: self.y / other.y, z: self.z / other.z, } } pub fn with_mag(&self, new_mag: Flt) -> Vec3 { if new_mag == 0.0 { // avoid div-by-zero if self.mag() == 0 and new_mag == 0 Self::zero() } else { let scale = Real::from_inner(new_mag) / self.mag(); self.clone() * scale.into_inner() } } /// Normalizes to 1.0 length, unless it's the zero vector, in which case length remains zero. pub fn norm(&self) -> Vec3 { if *self == Self::zero() { *self } else { self.with_mag(1.0) } } pub fn round(&self) -> Vec3 { Self::new(self.x().round(), self.y().round(), self.z().round()) } } impl Into<(Flt, Flt, Flt)> for Vec3 { fn into(self) -> (Flt, Flt, Flt) { (self.x(), self.y(), self.z()) } } impl From<(Flt, Flt, Flt)> for Vec3 { fn from((x, y, z): (Flt, Flt, Flt)) -> Self { Self::new(x, y, z) } } impl From<(Real, Real, Real)> for Vec3 { fn from((x, y, z): (Real, Real, Real)) -> Self { Self { x, y, z } } } impl From for Vec3 { fn from(v: Vec3u) -> Self { Self::new(v.x() as _, v.y() as _, v.z() as _) } } impl AddAssign for Vec3 { fn add_assign(&mut self, other: Self) { self.x += other.x; self.y += other.y; self.z += other.z; } } impl Add for Vec3 { type Output = Self; fn add(self, other: Self) -> Self { let mut work = self.clone(); work += other; work } } impl Sub for Vec3 { type Output = Self; fn sub(self, other: Self) -> Self { Self { x: self.x - other.x, y: self.y - other.y, z: self.z - other.z, } } } impl Neg for Vec3 { type Output = Self; fn neg(self) -> Self { Self { x: -self.x, y: -self.y, z: -self.z, } } } impl MulAssign for Vec3 { fn mul_assign(&mut self, other: Real) { self.x *= other; self.y *= other; self.z *= other; } } impl Mul for Vec3 { type Output = Self; fn mul(self, other: Real) -> Self { let mut work = self.clone(); work *= other; work } } impl MulAssign for Vec3 { fn mul_assign(&mut self, other: Flt) { self.x *= other; self.y *= other; self.z *= other; } } impl Mul for Vec3 { type Output = Self; fn mul(self, other: Flt) -> Self { let mut work = self.clone(); work *= other; work } } impl DivAssign for Vec3 { fn div_assign(&mut self, other: Real) { *self *= Real::from_inner(1.0) / other; } } impl Div for Vec3 { type Output = Self; fn div(self, other: Real) -> Self { let mut work = self.clone(); work /= other; work } } impl DivAssign for Vec3 { fn div_assign(&mut self, other: Flt) { *self *= 1.0 / other; } } impl Div for Vec3 { type Output = Self; fn div(self, other: Flt) -> Self { let mut work = self.clone(); work /= other; work } } impl Sum for Vec3 { fn sum>(iter: I) -> Self { iter.fold(Self::default(), |a, b| a + b) } }