use num::{cast, Float, Num};
use std::ops::{self, Index, IndexMut};
use serde::{Deserialize, Serialize};
#[derive(Debug, Eq, PartialEq, Clone, Default, Hash, Serialize, Deserialize)]
pub struct Vec2<T>(pub T, pub T);
impl<T: Copy + 'static> Vec2<T> {
pub fn from<U: cast::AsPrimitive<T>>(other: &Vec2<U>) -> Vec2<T> {
Vec2(other.0.as_(), other.1.as_())
}
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Hash, Serialize, Deserialize)]
pub struct Vec3<T>(pub T, pub T, pub T);
impl<T: Copy> Vec3<T> {
pub fn to_arr(&self) -> [T; 3] {
[self.0, self.1, self.2]
}
}
impl<T: Copy + 'static, U: cast::AsPrimitive<T>> From<&Vec3<U>> for Vec3<T> {
fn from(other: &Vec3<U>) -> Self {
Vec3(other.0.as_(), other.1.as_(), other.2.as_())
}
}
impl<T: Copy + 'static, U: cast::AsPrimitive<T>> From<&[U; 3]> for Vec3<T> {
fn from(other: &[U; 3]) -> Self {
Vec3(other[0].as_(), other[1].as_(), other[2].as_())
}
}
impl<T: Copy + 'static, U: cast::AsPrimitive<T>> Into<[T; 3]> for Vec3<U> {
fn into(self) -> [T; 3] {
[self.0.as_(), self.1.as_(), self.2.as_()]
}
}
impl<T: Num + Copy + Default> ops::Add<&Vec3<T>> for &Vec3<T> {
type Output = Vec3<T>;
fn add(self, rhs: &Vec3<T>) -> Self::Output {
Vec3::<T>(self.0 + rhs.0, self.1 + rhs.1, self.2 + rhs.2)
}
}
impl<T: Num + Copy + Default> ops::Add<Vec3<T>> for Vec3<T> {
type Output = Vec3<T>;
fn add(self, rhs: Vec3<T>) -> Self::Output {
Vec3::<T>(self.0 + rhs.0, self.1 + rhs.1, self.2 + rhs.2)
}
}
impl<T: Num + Copy + Default> ops::Sub<&Vec3<T>> for &Vec3<T> {
type Output = Vec3<T>;
fn sub(self, rhs: &Vec3<T>) -> Self::Output {
Vec3::<T>(self.0 - rhs.0, self.1 - rhs.1, self.2 - rhs.2)
}
}
impl<T: Num + Copy + Default> ops::Sub<Vec3<T>> for Vec3<T> {
type Output = Vec3<T>;
fn sub(self, rhs: Vec3<T>) -> Self::Output {
Vec3::<T>(self.0 - rhs.0, self.1 - rhs.1, self.2 - rhs.2)
}
}
impl<T: Num + Copy + Default> ops::Mul<&Vec3<T>> for &Vec3<T> {
type Output = Vec3<T>;
fn mul(self, rhs: &Vec3<T>) -> Self::Output {
let mut result = Vec3::default();
result.0 = self.0 * rhs.0;
result.1 = self.1 * rhs.1;
result.2 = self.2 * rhs.2;
result
}
}
impl<T: Num + Copy + Default> ops::Mul<T> for &Vec3<T> {
type Output = Vec3<T>;
fn mul(self, rhs: T) -> Self::Output {
let mut result = Vec3::default();
result.0 = self.0 * rhs;
result.1 = self.1 * rhs;
result.2 = self.2 * rhs;
result
}
}
impl<T: Num + Copy + Default + ops::AddAssign> ops::AddAssign<Vec3<T>> for Vec3<T> {
fn add_assign(&mut self, rhs: Vec3<T>) {
self.0 += rhs.0;
self.1 += rhs.1;
self.2 += rhs.2;
}
}
impl<T: Num + Copy + Default + ops::AddAssign> ops::AddAssign<[T; 3]> for Vec3<T> {
fn add_assign(&mut self, rhs: [T; 3]) {
self.0 += rhs[0];
self.1 += rhs[1];
self.2 += rhs[2];
}
}
impl<T: Num + Copy + Default + ops::SubAssign> ops::SubAssign<Vec3<T>> for Vec3<T> {
fn sub_assign(&mut self, rhs: Vec3<T>) {
self.0 -= rhs.0;
self.1 -= rhs.1;
self.2 -= rhs.2;
}
}
impl<T: Num + Copy + Default + ops::MulAssign> ops::MulAssign<Vec3<T>> for Vec3<T> {
fn mul_assign(&mut self, rhs: Vec3<T>) {
self.0 *= rhs.0;
self.1 *= rhs.1;
self.2 *= rhs.2;
}
}
impl<T: Num + Copy + Default + ops::MulAssign> ops::MulAssign<T> for Vec3<T> {
fn mul_assign(&mut self, rhs: T) {
self.0 *= rhs;
self.1 *= rhs;
self.2 *= rhs;
}
}
impl<T: Num + Copy + Default + ops::DivAssign> ops::DivAssign<T> for Vec3<T> {
fn div_assign(&mut self, rhs: T) {
self.0 /= rhs;
self.1 /= rhs;
self.2 /= rhs;
}
}
impl<T> Vec3<T>
where
T: Num + Copy,
{
pub fn add(&self, other: &Self) -> Self {
Vec3(self.0 + other.0, self.1 + other.1, self.2 + other.2)
}
pub fn sub(&self, other: &Self) -> Self {
Vec3(self.0 - other.0, self.1 - other.1, self.2 - other.2)
}
pub fn copy(&mut self, other: &Self) -> &Self {
self.0 = other.0;
self.1 = other.1;
self.2 = other.2;
self
}
pub fn set(&mut self, x: T, y: T, z: T) -> &Self {
self.0 = x;
self.1 = y;
self.2 = z;
self
}
pub fn scale(&self, scale: T) -> Self {
Vec3(self.0 * scale, self.1 * scale, self.2 * scale)
}
pub fn scale_and_add(&self, other: &Self, scale: T) -> Self {
Vec3(
self.0 + other.0 * scale,
self.1 + other.1 * scale,
self.2 + other.2 * scale,
)
}
pub fn from_arr(arr: [T; 3]) -> Self {
Vec3(arr[0], arr[1], arr[2])
}
}
impl<T> Vec3<T>
where
T: Float,
{
pub fn len(&self) -> T {
(self.0 * self.0 + self.1 * self.1 + self.2 * self.2).sqrt()
}
pub fn max(&self, other: &Self) -> Self {
Vec3(
Float::max(self.0, other.0),
Float::max(self.1, other.1),
Float::max(self.2, other.2),
)
}
pub fn min(&self, other: &Self) -> Self {
Vec3(
Float::min(self.0, other.0),
Float::min(self.1, other.1),
Float::min(self.2, other.2),
)
}
}
impl Vec3<f32> {
pub fn rotate_y(&self, origin: &Self, angle: f32) -> Self {
let ox = origin[0];
let oz = origin[2];
let px = self[0] - ox;
let pz = self[2] - oz;
let sc = angle.sin();
let cc = angle.cos();
Self(ox + pz * sc + px * cc, self[1], oz + pz * cc - px * sc)
}
pub fn normalize(&self) -> Self {
let Self(x, y, z) = self;
let len = x * x + y * y + z * z;
if len > 0.0 {
let len = 1.0 / len.sqrt();
return Self(self.0 * len, self.1 * len, self.2 * len);
}
self.to_owned()
}
pub fn sq_distance(&self, other: &Self) -> f32 {
let Self(x, y, z) = self;
let Self(ox, oy, oz) = other;
let dx = x - ox;
let dy = y - oy;
let dz = z - oz;
dx * dx + dy * dy + dz * dz
}
pub fn set_mag(&mut self, mag: f32) -> &Self {
let len = self.len();
self.0 /= len;
self.1 /= len;
self.2 /= len;
self.scale(mag);
self
}
pub fn limit(&mut self, mag: f32) -> &Self {
if self.len() > mag {
self.set_mag(mag);
}
self
}
}
impl<T: Num + Clone> Index<usize> for Vec3<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
if index == 0 {
&self.0
} else if index == 1 {
&self.1
} else if index == 2 {
&self.2
} else {
panic!("Index out of bounds for accessing Vec3.");
}
}
}
impl<T: Num + Clone> IndexMut<usize> for Vec3<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
if index == 0 {
&mut self.0
} else if index == 1 {
&mut self.1
} else if index == 2 {
&mut self.2
} else {
panic!("Index out of bounds for accessing Vec3.");
}
}
}
impl<T: Num + Clone> From<Vec<T>> for Vec3<T> {
fn from(vec: Vec<T>) -> Self {
let x = vec[0].clone();
let y = vec[1].clone();
let z = vec[2].clone();
Self(x, y, z)
}
}