batbox_la/vec/
_4d.rs

1use super::*;
2
3/// 4 dimensional vector.
4#[allow(non_camel_case_types)]
5#[repr(C)]
6#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
7pub struct vec4<T>(pub T, pub T, pub T, pub T);
8
9impl<T: std::fmt::Display> std::fmt::Display for vec4<T> {
10    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
11        write!(fmt, "({}, {}, {}, {})", self.x, self.y, self.z, self.w)
12    }
13}
14
15impl<T> From<[T; 4]> for vec4<T> {
16    fn from(arr: [T; 4]) -> vec4<T> {
17        let [x, y, z, w] = arr;
18        vec4(x, y, z, w)
19    }
20}
21
22/// Data structure used to provide access to coordinates with the dot notation, e.g. `v.x`
23#[repr(C)]
24pub struct XYZW<T> {
25    #[allow(missing_docs)]
26    pub x: T,
27    #[allow(missing_docs)]
28    pub y: T,
29    #[allow(missing_docs)]
30    pub z: T,
31    #[allow(missing_docs)]
32    pub w: T,
33}
34
35impl<T> Deref for XYZW<T> {
36    type Target = [T; 4];
37    fn deref(&self) -> &[T; 4] {
38        unsafe { std::mem::transmute(self) }
39    }
40}
41
42impl<T> DerefMut for XYZW<T> {
43    fn deref_mut(&mut self) -> &mut [T; 4] {
44        unsafe { std::mem::transmute(self) }
45    }
46}
47
48impl<T> Deref for vec4<T> {
49    type Target = XYZW<T>;
50    fn deref(&self) -> &XYZW<T> {
51        unsafe { std::mem::transmute(self) }
52    }
53}
54
55impl<T> DerefMut for vec4<T> {
56    fn deref_mut(&mut self) -> &mut XYZW<T> {
57        unsafe { std::mem::transmute(self) }
58    }
59}
60
61impl<T> vec4<T> {
62    /// Get first two components as a [vec2]
63    pub fn xy(self) -> vec2<T> {
64        vec2(self.0, self.1)
65    }
66
67    /// Get first three components as a [vec3]
68    pub fn xyz(self) -> vec3<T> {
69        vec3(self.0, self.1, self.2)
70    }
71
72    /// Map every value (coordinate).
73    pub fn map<U, F: Fn(T) -> U>(self, f: F) -> vec4<U> {
74        vec4(f(self.0), f(self.1), f(self.2), f(self.3))
75    }
76
77    /// Zip two vectors together
78    pub fn zip<U>(self, v: vec4<U>) -> vec4<(T, U)> {
79        vec4((self.0, v.0), (self.1, v.1), (self.2, v.2), (self.3, v.3))
80    }
81}
82
83impl<T: Clone> vec4<T> {
84    /// Construct a vector with all components set to specified value
85    pub fn splat(value: T) -> Self {
86        Self(value.clone(), value.clone(), value.clone(), value)
87    }
88}
89
90impl<T: UNum> vec4<T> {
91    /// A zero 4-d vector
92    pub const ZERO: Self = vec4(T::ZERO, T::ZERO, T::ZERO, T::ZERO);
93
94    /// A unit X
95    pub const UNIT_X: Self = Self(T::ONE, T::ZERO, T::ZERO, T::ZERO);
96
97    /// A unit Y
98    pub const UNIT_Y: Self = Self(T::ZERO, T::ONE, T::ZERO, T::ZERO);
99
100    /// A unit Z
101    pub const UNIT_Z: Self = Self(T::ZERO, T::ZERO, T::ONE, T::ZERO);
102
103    /// A unit W
104    pub const UNIT_W: Self = Self(T::ZERO, T::ZERO, T::ZERO, T::ONE);
105}
106
107impl<T: Copy + Num> vec4<T> {
108    /// Calculate dot product of two vectors.
109    ///
110    /// # Examples
111    /// ```
112    /// # use batbox_la::*;
113    /// assert_eq!(vec4::dot(vec4(1, 2, 3, 4), vec4(3, 4, 5, 6)), 50);
114    /// ```
115    pub fn dot(a: Self, b: Self) -> T {
116        a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w
117    }
118}
119
120impl<T: Float> vec4<T> {
121    /// Convert a homogenous 4d vector into 3d
122    ///
123    /// Same as self.xyz() / self.w
124    pub fn into_3d(self) -> vec3<T> {
125        self.xyz() / self.w
126    }
127}