348 lines
7.2 KiB
Rust
348 lines
7.2 KiB
Rust
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<Flt> 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<Vec3u> 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<Real> for Vec3 {
|
|
fn mul_assign(&mut self, other: Real) {
|
|
self.x *= other;
|
|
self.y *= other;
|
|
self.z *= other;
|
|
}
|
|
}
|
|
|
|
impl Mul<Real> for Vec3 {
|
|
type Output = Self;
|
|
fn mul(self, other: Real) -> Self {
|
|
let mut work = self.clone();
|
|
work *= other;
|
|
work
|
|
}
|
|
}
|
|
|
|
impl MulAssign<Flt> for Vec3 {
|
|
fn mul_assign(&mut self, other: Flt) {
|
|
self.x *= other;
|
|
self.y *= other;
|
|
self.z *= other;
|
|
}
|
|
}
|
|
|
|
impl Mul<Flt> for Vec3 {
|
|
type Output = Self;
|
|
fn mul(self, other: Flt) -> Self {
|
|
let mut work = self.clone();
|
|
work *= other;
|
|
work
|
|
}
|
|
}
|
|
|
|
impl DivAssign<Real> for Vec3 {
|
|
fn div_assign(&mut self, other: Real) {
|
|
*self *= Real::from_inner(1.0) / other;
|
|
}
|
|
}
|
|
|
|
impl Div<Real> for Vec3 {
|
|
type Output = Self;
|
|
fn div(self, other: Real) -> Self {
|
|
let mut work = self.clone();
|
|
work /= other;
|
|
work
|
|
}
|
|
}
|
|
|
|
impl DivAssign<Flt> for Vec3 {
|
|
fn div_assign(&mut self, other: Flt) {
|
|
*self *= 1.0 / other;
|
|
}
|
|
}
|
|
|
|
impl Div<Flt> 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<I: Iterator<Item = Self>>(iter: I) -> Self {
|
|
iter.fold(Self::default(), |a, b| a + b)
|
|
}
|
|
}
|