use std::{
fmt::Display,
hash::{Hash, Hasher},
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use parry3d::{
math::{Point, Vector},
na::{Translation3, Unit},
};
use spacetimedb::SpacetimeType;
use super::Mat3;
#[derive(SpacetimeType, Default, Debug, Clone, Copy, PartialEq)]
pub struct Vec3 {
pub x: f32,
pub y: f32,
pub z: f32,
}
impl Vec3 {
pub const ZERO: Self = Self {
x: 0.0,
y: 0.0,
z: 0.0,
};
pub const ONE: Self = Self {
x: 1.0,
y: 1.0,
z: 1.0,
};
pub const X: Self = Self {
x: 1.0,
y: 0.0,
z: 0.0,
};
pub const Y: Self = Self {
x: 0.0,
y: 1.0,
z: 0.0,
};
pub const Z: Self = Self {
x: 0.0,
y: 0.0,
z: 1.0,
};
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self { x, y, z }
}
pub fn splat(value: f32) -> Self {
Self {
x: value,
y: value,
z: value,
}
}
pub fn length(self) -> f32 {
(self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
}
pub fn normalize(self) -> Self {
let len = self.length();
if len == 0.0 {
return Self::ZERO;
}
Self {
x: self.x / len,
y: self.y / len,
z: self.z / len,
}
}
pub fn normalize_or(self, fallback: Vec3) -> Vec3 {
let len = self.length();
if len > 1e-5 {
self / len
} else {
fallback
}
}
pub fn normalize_or_zero(self) -> Self {
let len = self.length();
if len > 1e-5 {
self / len
} else {
Self::ZERO
}
}
pub fn dot(self, other: impl Into<Self>) -> f32 {
let other = other.into();
self.x * other.x + self.y * other.y + self.z * other.z
}
pub fn cross(self, other: impl Into<Self>) -> Self {
let other = other.into();
Self {
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,
}
}
pub fn length_squared(self) -> f32 {
self.x * self.x + self.y * self.y + self.z * self.z
}
pub fn project_onto_plane(self, normal: Vec3) -> Self {
let dot_product = self.dot(normal);
Self {
x: self.x - dot_product * normal.x,
y: self.y - dot_product * normal.y,
z: self.z - dot_product * normal.z,
}
}
pub fn transform(self, matrix: [[f32; 4]; 4]) -> Self {
let x =
self.x * matrix[0][0] + self.y * matrix[0][1] + self.z * matrix[0][2] + matrix[0][3];
let y =
self.x * matrix[1][0] + self.y * matrix[1][1] + self.z * matrix[1][2] + matrix[1][3];
let z =
self.x * matrix[2][0] + self.y * matrix[2][1] + self.z * matrix[2][2] + matrix[2][3];
Self { x, y, z }
}
pub fn abs(&self) -> Self {
Self {
x: self.x.abs(),
y: self.y.abs(),
z: self.z.abs(),
}
}
pub fn min(self, other: Vec3) -> Self {
Self {
x: self.x.min(other.x),
y: self.y.min(other.y),
z: self.z.min(other.z),
}
}
}
impl Hash for Vec3 {
fn hash<H: Hasher>(&self, state: &mut H) {
self.x.to_bits().hash(state);
self.y.to_bits().hash(state);
self.z.to_bits().hash(state);
}
}
impl From<&Vec3> for Vec3 {
fn from(value: &Vec3) -> Self {
*value
}
}
impl From<Vec3> for parry3d::na::Vector3<f32> {
fn from(value: Vec3) -> Self {
parry3d::na::Vector3::new(value.x, value.y, value.z)
}
}
impl From<parry3d::na::Vector3<f32>> for Vec3 {
fn from(value: parry3d::na::Vector3<f32>) -> Self {
Self {
x: value.x,
y: value.y,
z: value.z,
}
}
}
impl From<Vec3> for Unit<Vector<f32>> {
fn from(value: Vec3) -> Self {
let vec = parry3d::na::Vector3::new(value.x, value.y, value.z);
Unit::new_normalize(vec)
}
}
impl From<Unit<Vector<f32>>> for Vec3 {
fn from(value: Unit<Vector<f32>>) -> Self {
Self {
x: value.x,
y: value.y,
z: value.z,
}
}
}
impl From<Point<f32>> for Vec3 {
fn from(p: Point<f32>) -> Self {
Self {
x: p.x,
y: p.y,
z: p.z,
}
}
}
impl From<Vec3> for Point<f32> {
fn from(v: Vec3) -> Self {
Point::new(v.x, v.y, v.z)
}
}
impl From<Vec3> for Translation3<f32> {
fn from(v: Vec3) -> Self {
Translation3::new(v.x, v.y, v.z)
}
}
impl Add for Vec3 {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
}
}
}
impl AddAssign for Vec3 {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
self.z += rhs.z;
}
}
impl Add for &Vec3 {
type Output = Vec3;
fn add(self, rhs: Self) -> Self::Output {
Vec3 {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
}
}
}
impl AddAssign for &mut Vec3 {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
self.z += rhs.z;
}
}
impl Sub for Vec3 {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self {
x: self.x - rhs.x,
y: self.y - rhs.y,
z: self.z - rhs.z,
}
}
}
impl SubAssign for Vec3 {
fn sub_assign(&mut self, rhs: Self) {
self.x -= rhs.x;
self.y -= rhs.y;
self.z -= rhs.z;
}
}
impl Sub for &Vec3 {
type Output = Vec3;
fn sub(self, rhs: Self) -> Self::Output {
Vec3 {
x: self.x - rhs.x,
y: self.y - rhs.y,
z: self.z - rhs.z,
}
}
}
impl SubAssign for &mut Vec3 {
fn sub_assign(&mut self, rhs: Self) {
self.x -= rhs.x;
self.y -= rhs.y;
self.z -= rhs.z;
}
}
impl Sub<&Vec3> for Vec3 {
type Output = Self;
fn sub(self, rhs: &Vec3) -> Self::Output {
Self {
x: self.x - rhs.x,
y: self.y - rhs.y,
z: self.z - rhs.z,
}
}
}
impl Mul for Vec3 {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
Self {
x: self.x * rhs.x,
y: self.y * rhs.y,
z: self.z * rhs.z,
}
}
}
impl MulAssign for Vec3 {
fn mul_assign(&mut self, rhs: Self) {
self.x *= rhs.x;
self.y *= rhs.y;
self.z *= rhs.z;
}
}
impl Mul for &Vec3 {
type Output = Vec3;
fn mul(self, rhs: Self) -> Self::Output {
Vec3 {
x: self.x * rhs.x,
y: self.y * rhs.y,
z: self.z * rhs.z,
}
}
}
impl MulAssign for &mut Vec3 {
fn mul_assign(&mut self, rhs: Self) {
self.x *= rhs.x;
self.y *= rhs.y;
self.z *= rhs.z;
}
}
impl Mul<Mat3> for Vec3 {
type Output = Vec3;
fn mul(self, rhs: Mat3) -> Self::Output {
Vec3 {
x: self.x * rhs.m11 + self.y * rhs.m12 + self.z * rhs.m13,
y: self.x * rhs.m21 + self.y * rhs.m22 + self.z * rhs.m23,
z: self.x * rhs.m31 + self.y * rhs.m32 + self.z * rhs.m33,
}
}
}
impl Div for Vec3 {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
Self {
x: self.x / rhs.x,
y: self.y / rhs.y,
z: self.z / rhs.z,
}
}
}
impl DivAssign for Vec3 {
fn div_assign(&mut self, rhs: Self) {
self.x /= rhs.x;
self.y /= rhs.y;
self.z /= rhs.z;
}
}
impl Div for &Vec3 {
type Output = Vec3;
fn div(self, rhs: Self) -> Self::Output {
Vec3 {
x: self.x / rhs.x,
y: self.y / rhs.y,
z: self.z / rhs.z,
}
}
}
impl DivAssign for &mut Vec3 {
fn div_assign(&mut self, rhs: Self) {
self.x /= rhs.x;
self.y /= rhs.y;
self.z /= rhs.z;
}
}
impl Neg for Vec3 {
type Output = Self;
fn neg(self) -> Self::Output {
Self {
x: -self.x,
y: -self.y,
z: -self.z,
}
}
}
impl Neg for &Vec3 {
type Output = Vec3;
fn neg(self) -> Self::Output {
Vec3 {
x: -self.x,
y: -self.y,
z: -self.z,
}
}
}
impl Add<f32> for Vec3 {
type Output = Self;
fn add(self, rhs: f32) -> Self::Output {
Self {
x: self.x + rhs,
y: self.y + rhs,
z: self.z + rhs,
}
}
}
impl AddAssign<f32> for Vec3 {
fn add_assign(&mut self, rhs: f32) {
self.x += rhs;
self.y += rhs;
self.z += rhs;
}
}
impl Sub<f32> for Vec3 {
type Output = Self;
fn sub(self, rhs: f32) -> Self::Output {
Self {
x: self.x - rhs,
y: self.y - rhs,
z: self.z - rhs,
}
}
}
impl SubAssign<f32> for Vec3 {
fn sub_assign(&mut self, rhs: f32) {
self.x -= rhs;
self.y -= rhs;
self.z -= rhs;
}
}
impl Mul<f32> for Vec3 {
type Output = Self;
fn mul(self, rhs: f32) -> Self::Output {
Self {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}
impl Mul<&Vec3> for f32 {
type Output = Vec3;
fn mul(self, rhs: &Vec3) -> Self::Output {
Vec3 {
x: self * rhs.x,
y: self * rhs.y,
z: self * rhs.z,
}
}
}
impl MulAssign<f32> for Vec3 {
fn mul_assign(&mut self, rhs: f32) {
self.x *= rhs;
self.y *= rhs;
self.z *= rhs;
}
}
impl Div<f32> for Vec3 {
type Output = Self;
fn div(self, rhs: f32) -> Self::Output {
Self {
x: self.x / rhs,
y: self.y / rhs,
z: self.z / rhs,
}
}
}
impl DivAssign<f32> for Vec3 {
fn div_assign(&mut self, rhs: f32) {
self.x /= rhs;
self.y /= rhs;
self.z /= rhs;
}
}
impl Mul<Vec3> for f32 {
type Output = Vec3;
fn mul(self, rhs: Vec3) -> Self::Output {
Vec3 {
x: self * rhs.x,
y: self * rhs.y,
z: self * rhs.z,
}
}
}
impl MulAssign<f32> for &mut Vec3 {
fn mul_assign(&mut self, rhs: f32) {
self.x *= rhs;
self.y *= rhs;
self.z *= rhs;
}
}
impl Display for Vec3 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Vec3({}, {}, {})", self.x, self.y, self.z)
}
}