Skip to main content

ewq/vec/
d4.rs

1use super::{Vec2, Vec3, Vector, VectorConst};
2use num_traits::Float;
3use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
4
5pub type Vec4f = Vec3<f32>;
6pub type Vec4d = Vec3<f64>;
7
8/// 4D Euclidian vector with X, Y, Z and W components.
9#[derive(Debug, PartialEq, Default, Clone, Copy, PartialOrd)]
10#[repr(C)]
11pub struct Vec4<F>
12where
13    F: Float,
14{
15    pub x: F,
16    pub y: F,
17    pub z: F,
18    pub w: F,
19}
20
21impl<F> Vec4<F>
22where
23    F: Float,
24{
25    /// Creates new vector.
26    #[inline(always)]
27    pub fn new(x: F, y: F, z: F, w: F) -> Self {
28        Self { x, y, z, w }
29    }
30
31    /// Creates new vector by expanding 3D vector.
32    #[inline]
33    pub fn from_vec3(v: Vec3<F>, w: F) -> Self {
34        Self {
35            x: v.x,
36            y: v.y,
37            z: v.z,
38            w,
39        }
40    }
41
42    /// Creates new vector from two 2D vectors.
43    #[inline]
44    pub fn from_vec2(xy: Vec2<F>, zw: Vec2<F>) -> Self {
45        Self {
46            x: xy.x,
47            y: xy.y,
48            z: zw.x,
49            w: zw.y,
50        }
51    }
52
53    /// Splits vector into X and Y components.
54    #[inline]
55    pub fn split(&self) -> (F, F, F, F) {
56        (self.x, self.y, self.z, self.w)
57    }
58
59    /// Combines tuple into vector.
60    #[inline]
61    pub fn combine(xyzw: (F, F, F, F)) -> Self {
62        Self {
63            x: xyzw.0,
64            y: xyzw.1,
65            z: xyzw.2,
66            w: xyzw.3,
67        }
68    }
69
70    /// Split vector into it's basic vectors `i`, `j`, `k`, `l`.
71    #[inline]
72    pub fn into_basis(self) -> (Self, Self, Self, Self) {
73        (
74            Self {
75                x: self.x,
76                y: F::zero(),
77                z: F::zero(),
78                w: F::zero(),
79            },
80            Self {
81                x: F::zero(),
82                y: self.y,
83                z: F::zero(),
84                w: F::zero(),
85            },
86            Self {
87                x: F::zero(),
88                y: F::zero(),
89                z: self.z,
90                w: F::zero(),
91            },
92            Self {
93                x: F::zero(),
94                y: F::zero(),
95                z: F::zero(),
96                w: self.w,
97            },
98        )
99    }
100
101    /// Computes the distance between two vectors.
102    #[inline]
103    pub fn distance_to(&self, other: Self) -> F {
104        (other - *self).magnitude()
105    }
106
107    /// Computes dot product between two vectors.
108    #[inline]
109    pub fn dot(&self, other: Self) -> F {
110        self.x * other.x + self.y * other.y + self.z * other.z + self.w * other.w
111    }
112
113    /// Computes dot product between two normalized copies of the vectors.
114    #[inline]
115    pub fn dot_normalized(&self, other: Self) -> F {
116        self.normalized().dot(other.normalized())
117    }
118
119    /// Scales all of the components by `factor`.
120    #[inline]
121    pub fn scale(&mut self, factor: F) {
122        self.x = self.x * factor;
123        self.y = self.y * factor;
124        self.z = self.z * factor;
125        self.w = self.w * factor;
126    }
127
128    /// Computes the magnitude of the vector.
129    #[inline]
130    pub fn magnitude(&self) -> F {
131        F::sqrt(self.sqrt_magnitude())
132    }
133
134    /// Computes the squared magnitude of the vector.
135    #[inline]
136    pub fn sqrt_magnitude(&self) -> F {
137        self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w
138    }
139
140    /// Returns the normalized version of the vector.
141    #[inline]
142    pub fn normalized(&self) -> Self {
143        let l = self.magnitude();
144        Self {
145            x: self.x / l,
146            y: self.y / l,
147            z: self.z / l,
148            w: self.w / l,
149        }
150    }
151
152    /// Normalizes the vector, preserving direction but reducing its magnitude to `1`.
153    #[inline]
154    pub fn normalize(&mut self) {
155        let l = self.magnitude();
156        self.x = self.x / l;
157        self.y = self.y / l;
158        self.z = self.z / l;
159        self.w = self.w / l;
160    }
161}
162
163impl<F> VectorConst<F> for Vec4<F>
164where
165    F: Float,
166{
167    const SIZE: usize = 3;
168
169    fn get<const I: usize>(&self) -> F {
170        match I {
171            0 => self.x,
172            1 => self.y,
173            2 => self.z,
174            3 => self.w,
175            _ => panic!("Index out of range. Expected 0..=2"),
176        }
177    }
178
179    fn set<const I: usize>(&mut self, v: F) {
180        match I {
181            0 => self.x = v,
182            1 => self.y = v,
183            2 => self.z = v,
184            3 => self.w = v,
185            _ => panic!("Index out of range. Expected 0..=2"),
186        }
187    }
188}
189
190impl<F> Vector<F> for Vec4<F>
191where
192    F: Float,
193{
194    const SIZE: usize = 3;
195
196    fn get(&self, i: usize) -> F {
197        match i {
198            0 => self.x,
199            1 => self.y,
200            2 => self.z,
201            3 => self.w,
202            _ => panic!("Index out of range. Expected 0..=2"),
203        }
204    }
205
206    fn set(&mut self, i: usize, v: F) {
207        match i {
208            0 => self.x = v,
209            1 => self.y = v,
210            2 => self.z = v,
211            3 => self.w = v,
212            _ => panic!("Index out of range. Expected 0..=2"),
213        }
214    }
215}
216
217impl<F> Add for Vec4<F>
218where
219    F: Float,
220{
221    type Output = Self;
222
223    #[inline]
224    fn add(self, rhs: Self) -> Self::Output {
225        Self {
226            x: self.x + rhs.x,
227            y: self.y + rhs.y,
228            z: self.z + rhs.z,
229            w: self.w + rhs.w,
230        }
231    }
232}
233
234impl<F> AddAssign for Vec4<F>
235where
236    F: Float,
237{
238    #[inline]
239    fn add_assign(&mut self, rhs: Self) {
240        self.x = self.x + rhs.x;
241        self.y = self.y + rhs.y;
242        self.z = self.z + rhs.z;
243        self.w = self.w + rhs.w;
244    }
245}
246
247impl<F> Sub for Vec4<F>
248where
249    F: Float,
250{
251    type Output = Self;
252
253    #[inline]
254    fn sub(self, rhs: Self) -> Self::Output {
255        Self {
256            x: self.x - rhs.x,
257            y: self.y - rhs.y,
258            z: self.z - rhs.z,
259            w: self.w - rhs.w,
260        }
261    }
262}
263
264impl<F> SubAssign for Vec4<F>
265where
266    F: Float,
267{
268    #[inline]
269    fn sub_assign(&mut self, rhs: Self) {
270        self.x = self.x - rhs.x;
271        self.y = self.y - rhs.y;
272        self.z = self.z - rhs.z;
273        self.w = self.w - rhs.w;
274    }
275}
276
277impl<F> Mul<F> for Vec4<F>
278where
279    F: Float,
280{
281    type Output = Self;
282
283    #[inline]
284    fn mul(self, rhs: F) -> Self::Output {
285        Self {
286            x: self.x * rhs,
287            y: self.y * rhs,
288            z: self.z * rhs,
289            w: self.w * rhs,
290        }
291    }
292}
293
294impl<F> MulAssign<F> for Vec4<F>
295where
296    F: Float,
297{
298    #[inline]
299    fn mul_assign(&mut self, rhs: F) {
300        self.x = self.x * rhs;
301        self.y = self.y * rhs;
302        self.z = self.z * rhs;
303        self.w = self.w * rhs;
304    }
305}
306
307impl<F> Div<F> for Vec4<F>
308where
309    F: Float,
310{
311    type Output = Self;
312
313    #[inline]
314    fn div(self, rhs: F) -> Self::Output {
315        Self {
316            x: self.x / rhs,
317            y: self.y / rhs,
318            z: self.z / rhs,
319            w: self.w / rhs,
320        }
321    }
322}
323
324impl<F> DivAssign<F> for Vec4<F>
325where
326    F: Float,
327{
328    #[inline]
329    fn div_assign(&mut self, rhs: F) {
330        self.x = self.x / rhs;
331        self.y = self.y / rhs;
332        self.z = self.z / rhs;
333        self.w = self.w / rhs;
334    }
335}
336
337impl<F> Neg for Vec4<F>
338where
339    F: Float,
340{
341    type Output = Self;
342
343    #[inline]
344    fn neg(self) -> Self::Output {
345        Self {
346            x: -self.x,
347            y: -self.y,
348            z: -self.z,
349            w: -self.w,
350        }
351    }
352}