Skip to main content

ty_math/
ty_vector3.rs

1use std::ops::{Add, Mul, Sub};
2
3/// A 3D vector generic over its component type `T`.
4///
5/// The component type defaults to `f64`, so `TyVector3` is the `f64` vector;
6/// see `TyVector3F32`, `TyVector3F64`, and `TyVector3U32` for the common
7/// instantiations.
8#[derive(Clone, Copy, Debug, Default, PartialEq)]
9pub struct TyVector3<T = f64> {
10    /// The `x` component.
11    pub x: T,
12
13    /// The `y` component.
14    pub y: T,
15
16    /// The `z` component.
17    pub z: T,
18}
19
20impl<T> TyVector3<T> {
21    /// Creates a new vector from `x`, `y`, and `z` components.
22    pub fn new(x: T, y: T, z: T) -> Self {
23        Self { x, y, z }
24    }
25}
26
27impl<T: Add<Output = T> + Copy + Mul<Output = T> + Sub<Output = T>> TyVector3<T> {
28    /// Returns the cross product of `self` and `other`.
29    pub fn cross(&self, other: &Self) -> Self {
30        Self {
31            x: self.y * other.z - self.z * other.y,
32            y: self.z * other.x - self.x * other.z,
33            z: self.x * other.y - self.y * other.x,
34        }
35    }
36
37    /// Returns the dot product of `self` and `other`.
38    pub fn dot(&self, other: &Self) -> T {
39        self.x * other.x + self.y * other.y + self.z * other.z
40    }
41}
42
43impl<T: Add<Output = T>> Add for TyVector3<T> {
44    type Output = Self;
45
46    fn add(self, rhs: Self) -> Self {
47        Self {
48            x: self.x + rhs.x,
49            y: self.y + rhs.y,
50            z: self.z + rhs.z,
51        }
52    }
53}
54
55impl<T: Sub<Output = T>> Sub for TyVector3<T> {
56    type Output = Self;
57
58    fn sub(self, rhs: Self) -> Self {
59        Self {
60            x: self.x - rhs.x,
61            y: self.y - rhs.y,
62            z: self.z - rhs.z,
63        }
64    }
65}
66
67impl<T: Copy + Mul<Output = T>> Mul<T> for TyVector3<T> {
68    type Output = Self;
69
70    fn mul(self, rhs: T) -> Self {
71        Self {
72            x: self.x * rhs,
73            y: self.y * rhs,
74            z: self.z * rhs,
75        }
76    }
77}
78
79/// Implements the float-only vector operations (magnitude and scalar-on-the-left
80/// multiplication) for a concrete floating-point component type.
81macro_rules! impl_ty_vector3_float {
82    ($t:ty) => {
83        impl TyVector3<$t> {
84            /// Returns the Euclidean length of this vector.
85            pub fn magnitude(&self) -> $t {
86                (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
87            }
88        }
89
90        impl Mul<TyVector3<$t>> for $t {
91            type Output = TyVector3<$t>;
92
93            fn mul(self, rhs: TyVector3<$t>) -> TyVector3<$t> {
94                TyVector3 {
95                    x: self * rhs.x,
96                    y: self * rhs.y,
97                    z: self * rhs.z,
98                }
99            }
100        }
101    };
102}
103
104impl_ty_vector3_float!(f32);
105impl_ty_vector3_float!(f64);