#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use {
num_traits::{AsPrimitive, CheckedDiv},
std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
#[repr(C)]
#[derive(Clone, PartialEq, Eq, Debug, Copy, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Vector3<T> {
pub x: T,
pub y: T,
pub z: T,
}
impl<T> Vector3<T> {
pub const fn new(x: T, y: T, z: T) -> Self {
Self { x, y, z }
}
pub fn into_other<U>(self) -> Vector3<U>
where
T: Into<U>,
{
Vector3 {
x: self.x.into(),
y: self.y.into(),
z: self.z.into(),
}
}
pub fn try_into_other<U>(self) -> Result<Vector3<U>, T::Error>
where
T: TryInto<U>,
{
Ok(Vector3 {
x: self.x.try_into()?,
y: self.y.try_into()?,
z: self.z.try_into()?,
})
}
pub fn as_other<U: 'static + Copy>(self) -> Vector3<U>
where
T: AsPrimitive<U>,
{
Vector3 {
x: self.x.as_(),
y: self.y.as_(),
z: self.z.as_(),
}
}
}
pub type Vector3f = Vector3<f32>;
pub type Vector3i = Vector3<i32>;
impl<T: Mul<Output = T> + Add<Output = T> + Copy> Vector3<T> {
pub fn dot(self, rhs: Self) -> T {
self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
}
pub fn length_sq(self) -> T {
self.dot(self)
}
}
impl<T: Mul<Output = T> + Sub<Output = T> + Copy> Vector3<T> {
pub fn cross(self, rhs: Self) -> Vector3<T> {
Vector3 {
x: self.y * rhs.z - self.z * rhs.y,
y: self.z * rhs.x - self.x * rhs.z,
z: self.x * rhs.y - self.y * rhs.x,
}
}
}
impl<T: Mul<Output = T>> Vector3<T> {
pub fn cwise_mul(self, rhs: Self) -> Vector3<T> {
Self {
x: self.x * rhs.x,
y: self.y * rhs.y,
z: self.z * rhs.z,
}
}
}
impl<T: Div<Output = T>> Vector3<T> {
pub fn cwise_div(self, rhs: Self) -> Vector3<T> {
Vector3 {
x: self.x / rhs.x,
y: self.y / rhs.y,
z: self.z / rhs.z,
}
}
}
impl<T: Div<Output = T> + CheckedDiv> Vector3<T> {
pub fn cwise_checked_div(self, rhs: Self) -> Option<Vector3<T>> {
let x = self.x.checked_div(&rhs.x)?;
let y = self.y.checked_div(&rhs.y)?;
let z = self.z.checked_div(&rhs.z)?;
Some(Vector3 { x, y, z })
}
}
impl<T: Add> Add for Vector3<T> {
type Output = Vector3<T::Output>;
fn add(self, rhs: Vector3<T>) -> Vector3<T::Output> {
Vector3 {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
}
}
}
impl<T: AddAssign> AddAssign for Vector3<T> {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
self.z += rhs.z;
}
}
impl<T: Sub> Sub for Vector3<T> {
type Output = Vector3<T::Output>;
fn sub(self, rhs: Vector3<T>) -> Vector3<T::Output> {
Vector3 {
x: self.x - rhs.x,
y: self.y - rhs.y,
z: self.z - rhs.z,
}
}
}
impl<T: SubAssign> SubAssign for Vector3<T> {
fn sub_assign(&mut self, rhs: Self) {
self.x -= rhs.x;
self.y -= rhs.y;
self.z -= rhs.z;
}
}
impl<T: Mul + Copy> Mul<T> for Vector3<T> {
type Output = Vector3<T::Output>;
fn mul(self, rhs: T) -> Vector3<T::Output> {
Vector3 {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}
impl<T: MulAssign + Copy> MulAssign<T> for Vector3<T> {
fn mul_assign(&mut self, rhs: T) {
self.x *= rhs;
self.y *= rhs;
self.z *= rhs;
}
}
impl<T: Div + Copy> Div<T> for Vector3<T> {
type Output = Vector3<T::Output>;
fn div(self, rhs: T) -> Vector3<T::Output> {
Vector3 {
x: self.x / rhs,
y: self.y / rhs,
z: self.z / rhs,
}
}
}
impl<T: DivAssign + Copy> DivAssign<T> for Vector3<T> {
fn div_assign(&mut self, rhs: T) {
self.x /= rhs;
self.y /= rhs;
self.z /= rhs;
}
}
impl<T: CheckedDiv> Vector3<T> {
pub fn checked_div(self, rhs: T) -> Option<Vector3<T>> {
let x = self.x.checked_div(&rhs)?;
let y = self.y.checked_div(&rhs)?;
let z = self.z.checked_div(&rhs)?;
Some(Vector3 { x, y, z })
}
}
impl<T: Neg<Output = T>> Neg for Vector3<T> {
type Output = Self;
fn neg(self) -> Self {
Vector3 {
x: -self.x,
y: -self.y,
z: -self.z,
}
}
}
impl<T> From<(T, T, T)> for Vector3<T> {
fn from(src: (T, T, T)) -> Self {
Self {
x: src.0,
y: src.1,
z: src.2,
}
}
}
impl<T> From<Vector3<T>> for (T, T, T) {
fn from(vec: Vector3<T>) -> Self {
(vec.x, vec.y, vec.z)
}
}
impl<T> From<[T; 3]> for Vector3<T> {
fn from([x, y, z]: [T; 3]) -> Self {
Self { x, y, z }
}
}
impl<T> From<Vector3<T>> for [T; 3] {
fn from(vec: Vector3<T>) -> Self {
[vec.x, vec.y, vec.z]
}
}