gfx_maths/
vec3.rs

1use std::{fmt::Display, ops::Neg};
2
3use auto_ops::{impl_op_ex, impl_op_ex_commutative};
4
5use crate::Vec4;
6
7#[derive(Debug, Clone, Copy, PartialEq)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[repr(C)]
10pub struct Vec3 {
11    pub x: f32,
12    pub y: f32,
13    pub z: f32,
14}
15
16impl Default for Vec3 {
17    /// Creates a zero vector
18    fn default() -> Self {
19        Self::zero()
20    }
21}
22
23impl Display for Vec3 {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        let Self { x, y, z } = self;
26        write!(f, "({x}, {y}, {z})")
27    }
28}
29
30impl Vec3 {
31    pub const fn new(x: f32, y: f32, z: f32) -> Self {
32        Self { x, y, z }
33    }
34
35    /// Creates (0, 0, 0)
36    pub const fn zero() -> Self {
37        Self {
38            x: 0.0,
39            y: 0.0,
40            z: 0.0,
41        }
42    }
43
44    /// Creates (1, 1, 1)
45    pub const fn one() -> Self {
46        Self {
47            x: 1.0,
48            y: 1.0,
49            z: 1.0,
50        }
51    }
52
53    /// Returns the square of the vector's length.
54    ///
55    /// Faster to compute than [`magnitude()`](Self::magnitude())
56    pub fn sqr_magnitude(&self) -> f32 {
57        self.x * self.x + self.y * self.y + self.z * self.z
58    }
59
60    /// Returns the vector's length
61    pub fn magnitude(&self) -> f32 {
62        self.sqr_magnitude().sqrt()
63    }
64
65    /// Normalizes `self` in place
66    pub fn normalize(&mut self) -> &mut Self {
67        let m = self.magnitude();
68        self.x /= m;
69        self.y /= m;
70        self.z /= m;
71        self
72    }
73    /// Returns a normalized copy of `self`
74    #[must_use]
75    pub fn normalized(&self) -> Self {
76        *self.clone().normalize()
77    }
78
79    /// Returns the dot product of `self` and `b`
80    pub fn dot(&self, b: Vec3) -> f32 {
81        self.x * b.x + self.y * b.y + self.z * b.z
82    }
83
84    /// Returns the cross product of `self` and `b`
85    #[must_use]
86    pub fn cross(&self, b: Vec3) -> Vec3 {
87        Vec3 {
88            x: self.y * b.z - self.z * b.y,
89            y: self.z * b.x - self.x * b.z,
90            z: self.x * b.y - self.y * b.x,
91        }
92    }
93
94    pub fn extend(&self, w: f32) -> Vec4 {
95        Vec4 {
96            x: self.x,
97            y: self.y,
98            z: self.z,
99            w,
100        }
101    }
102
103    swizzle!(x, x);
104    swizzle!(x, y);
105    swizzle!(x, z);
106    swizzle!(y, x);
107    swizzle!(y, y);
108    swizzle!(y, z);
109    swizzle!(z, x);
110    swizzle!(z, y);
111    swizzle!(z, z);
112
113    swizzle!(x, x, x);
114    swizzle!(x, x, y);
115    swizzle!(x, x, z);
116    swizzle!(x, y, x);
117    swizzle!(x, y, y);
118    swizzle!(x, y, z);
119    swizzle!(x, z, x);
120    swizzle!(x, z, y);
121    swizzle!(x, z, z);
122    swizzle!(y, x, x);
123    swizzle!(y, x, y);
124    swizzle!(y, x, z);
125    swizzle!(y, y, x);
126    swizzle!(y, y, y);
127    swizzle!(y, y, z);
128    swizzle!(y, z, x);
129    swizzle!(y, z, y);
130    swizzle!(y, z, z);
131    swizzle!(z, x, x);
132    swizzle!(z, x, y);
133    swizzle!(z, x, z);
134    swizzle!(z, y, x);
135    swizzle!(z, y, y);
136    swizzle!(z, y, z);
137    swizzle!(z, z, x);
138    swizzle!(z, z, y);
139    swizzle!(z, z, z);
140
141    swizzle!(x, x, x, x);
142    swizzle!(x, x, x, y);
143    swizzle!(x, x, x, z);
144    swizzle!(x, x, y, x);
145    swizzle!(x, x, y, y);
146    swizzle!(x, x, y, z);
147    swizzle!(x, x, z, x);
148    swizzle!(x, x, z, y);
149    swizzle!(x, x, z, z);
150    swizzle!(x, y, x, x);
151    swizzle!(x, y, x, y);
152    swizzle!(x, y, x, z);
153    swizzle!(x, y, y, x);
154    swizzle!(x, y, y, y);
155    swizzle!(x, y, y, z);
156    swizzle!(x, y, z, x);
157    swizzle!(x, y, z, y);
158    swizzle!(x, y, z, z);
159    swizzle!(x, z, x, x);
160    swizzle!(x, z, x, y);
161    swizzle!(x, z, x, z);
162    swizzle!(x, z, y, x);
163    swizzle!(x, z, y, y);
164    swizzle!(x, z, y, z);
165    swizzle!(x, z, z, x);
166    swizzle!(x, z, z, y);
167    swizzle!(x, z, z, z);
168    swizzle!(y, x, x, x);
169    swizzle!(y, x, x, y);
170    swizzle!(y, x, x, z);
171    swizzle!(y, x, y, x);
172    swizzle!(y, x, y, y);
173    swizzle!(y, x, y, z);
174    swizzle!(y, x, z, x);
175    swizzle!(y, x, z, y);
176    swizzle!(y, x, z, z);
177    swizzle!(y, y, x, x);
178    swizzle!(y, y, x, y);
179    swizzle!(y, y, x, z);
180    swizzle!(y, y, y, x);
181    swizzle!(y, y, y, y);
182    swizzle!(y, y, y, z);
183    swizzle!(y, y, z, x);
184    swizzle!(y, y, z, y);
185    swizzle!(y, y, z, z);
186    swizzle!(y, z, x, x);
187    swizzle!(y, z, x, y);
188    swizzle!(y, z, x, z);
189    swizzle!(y, z, y, x);
190    swizzle!(y, z, y, y);
191    swizzle!(y, z, y, z);
192    swizzle!(y, z, z, x);
193    swizzle!(y, z, z, y);
194    swizzle!(y, z, z, z);
195    swizzle!(z, x, x, x);
196    swizzle!(z, x, x, y);
197    swizzle!(z, x, x, z);
198    swizzle!(z, x, y, x);
199    swizzle!(z, x, y, y);
200    swizzle!(z, x, y, z);
201    swizzle!(z, x, z, x);
202    swizzle!(z, x, z, y);
203    swizzle!(z, x, z, z);
204    swizzle!(z, y, x, x);
205    swizzle!(z, y, x, y);
206    swizzle!(z, y, x, z);
207    swizzle!(z, y, y, x);
208    swizzle!(z, y, y, y);
209    swizzle!(z, y, y, z);
210    swizzle!(z, y, z, x);
211    swizzle!(z, y, z, y);
212    swizzle!(z, y, z, z);
213    swizzle!(z, z, x, x);
214    swizzle!(z, z, x, y);
215    swizzle!(z, z, x, z);
216    swizzle!(z, z, y, x);
217    swizzle!(z, z, y, y);
218    swizzle!(z, z, y, z);
219    swizzle!(z, z, z, x);
220    swizzle!(z, z, z, y);
221    swizzle!(z, z, z, z);
222}
223
224impl_op_ex!(+= |a: &mut Vec3, b: &Vec3| { a.x += b.x; a.y += b.y; a.z += b.z; });
225impl_op_ex!(-= |a: &mut Vec3, b: &Vec3| { a.x -= b.x; a.y -= b.y; a.z -= b.z; });
226impl_op_ex!(*= |a: &mut Vec3, b: &Vec3| { a.x *= b.x; a.y *= b.y; a.z *= b.z; });
227impl_op_ex!(/= |a: &mut Vec3, b: &Vec3| { a.x /= b.x; a.y /= b.y; a.z /= b.z; });
228
229impl_op_ex!(*= |a: &mut Vec3, b: &f32| { a.x *= b; a.y *= b; a.z *= b; });
230impl_op_ex!(/= |a: &mut Vec3, b: &f32| { a.x /= b; a.y /= b; a.z /= b; });
231
232impl_op_ex!(+ |a: &Vec3, b: &Vec3| -> Vec3 { Vec3{x: a.x + b.x, y: a.y + b.y, z: a.z + b.z } });
233impl_op_ex!(-|a: &Vec3, b: &Vec3| -> Vec3 {
234    Vec3 {
235        x: a.x - b.x,
236        y: a.y - b.y,
237        z: a.z - b.z,
238    }
239});
240impl_op_ex!(*|a: &Vec3, b: &Vec3| -> Vec3 {
241    Vec3 {
242        x: a.x * b.x,
243        y: a.y * b.y,
244        z: a.z * b.z,
245    }
246});
247impl_op_ex!(/ |a: &Vec3, b: &Vec3| -> Vec3 { Vec3{x: a.x / b.x, y: a.y / b.y, z: a.z / b.z } });
248
249impl_op_ex_commutative!(*|a: &Vec3, b: &f32| -> Vec3 {
250    Vec3 {
251        x: a.x * b,
252        y: a.y * b,
253        z: a.z * b,
254    }
255});
256impl_op_ex!(/ |a: &Vec3, b: &f32| -> Vec3 { Vec3{x: a.x / b, y: a.y / b, z: a.z / b } });
257impl_op_ex!(/ |a: &f32, b: &Vec3| -> Vec3 { Vec3{x: a / b.x, y: a / b.y, z: a / b.z } });
258
259impl Neg for Vec3 {
260    type Output = Vec3;
261    fn neg(self) -> Self::Output {
262        Vec3 {
263            x: -self.x,
264            y: -self.y,
265            z: -self.z,
266        }
267    }
268}
269
270impl From<[f32; 3]> for Vec3 {
271    fn from(d: [f32; 3]) -> Self {
272        Self {
273            x: d[0],
274            y: d[1],
275            z: d[2],
276        }
277    }
278}
279
280#[cfg(test)]
281mod tests {
282    use super::*;
283
284    #[test]
285    fn operators() {
286        let a = Vec3::new(1.0, 2.0, 3.0);
287        let b = Vec3::new(3.0, 4.0, 5.0);
288
289        assert_eq!(
290            -a,
291            Vec3 {
292                x: -1.0,
293                y: -2.0,
294                z: -3.0
295            }
296        );
297
298        assert_eq!(a.sqr_magnitude(), 14.0);
299        assert_eq!(a.magnitude(), 14.0f32.sqrt());
300
301        assert_eq!(a.dot(b), 26.0);
302
303        assert_eq!(
304            a + b,
305            Vec3 {
306                x: 4.0,
307                y: 6.0,
308                z: 8.0
309            }
310        );
311        assert_eq!(
312            a - b,
313            Vec3 {
314                x: -2.0,
315                y: -2.0,
316                z: -2.0
317            }
318        );
319        assert_eq!(
320            a * b,
321            Vec3 {
322                x: 3.0,
323                y: 8.0,
324                z: 15.0
325            }
326        );
327        assert_eq!(
328            a / b,
329            Vec3 {
330                x: 1.0 / 3.0,
331                y: 0.5,
332                z: 3.0 / 5.0
333            }
334        );
335
336        assert_eq!(
337            a * 2.0,
338            Vec3 {
339                x: 2.0,
340                y: 4.0,
341                z: 6.0
342            }
343        );
344        assert_eq!(
345            2.0 * a,
346            Vec3 {
347                x: 2.0,
348                y: 4.0,
349                z: 6.0
350            }
351        );
352
353        assert_eq!(
354            a / 2.0,
355            Vec3 {
356                x: 0.5,
357                y: 1.0,
358                z: 1.5
359            }
360        );
361        assert_eq!(
362            2.0 / a,
363            Vec3 {
364                x: 2.0,
365                y: 1.0,
366                z: 2.0 / 3.0
367            }
368        );
369
370        let mut c = a;
371
372        assert_eq!(c.normalized(), a / a.magnitude());
373
374        c.normalize();
375        assert_eq!(c, a / a.magnitude());
376
377        c = a;
378        c += b;
379        assert_eq!(c, a + b);
380
381        c = a;
382        c -= b;
383        assert_eq!(c, a - b);
384
385        c = a;
386        c *= b;
387        assert_eq!(c, a * b);
388
389        c = a;
390        c /= b;
391        assert_eq!(c, a / b);
392
393        c = a;
394        c *= 2.0;
395        assert_eq!(c, a * 2.0);
396
397        c = a;
398        c /= 2.0;
399        assert_eq!(c, a / 2.0);
400    }
401}