Skip to main content

molgfx_math/types/
vector.rs

1//! Project-owned vectors lowered to glam operations.
2
3use std::iter::Sum;
4use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
5
6use bytemuck::{Pod, Zeroable};
7use serde::{Deserialize, Serialize};
8
9macro_rules! component_ops {
10    ($name:ident { $($field:ident),+ }) => {
11        impl Add for $name {
12            type Output = Self;
13            #[inline] fn add(self, rhs: Self) -> Self { Self { $($field: self.$field + rhs.$field),+ } }
14        }
15        impl Sub for $name {
16            type Output = Self;
17            #[inline] fn sub(self, rhs: Self) -> Self { Self { $($field: self.$field - rhs.$field),+ } }
18        }
19        impl Mul for $name {
20            type Output = Self;
21            #[inline] fn mul(self, rhs: Self) -> Self { Self { $($field: self.$field * rhs.$field),+ } }
22        }
23        impl Div for $name {
24            type Output = Self;
25            #[inline] fn div(self, rhs: Self) -> Self { Self { $($field: self.$field / rhs.$field),+ } }
26        }
27        impl Mul<f32> for $name {
28            type Output = Self;
29            #[inline] fn mul(self, rhs: f32) -> Self { Self { $($field: self.$field * rhs),+ } }
30        }
31        impl Div<f32> for $name {
32            type Output = Self;
33            #[inline] fn div(self, rhs: f32) -> Self { Self { $($field: self.$field / rhs),+ } }
34        }
35        impl Neg for $name {
36            type Output = Self;
37            #[inline] fn neg(self) -> Self { Self { $($field: -self.$field),+ } }
38        }
39        impl AddAssign for $name { #[inline] fn add_assign(&mut self, rhs: Self) { *self = *self + rhs; } }
40        impl SubAssign for $name { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = *self - rhs; } }
41        impl MulAssign<f32> for $name { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = *self * rhs; } }
42        impl DivAssign<f32> for $name { #[inline] fn div_assign(&mut self, rhs: f32) { *self = *self / rhs; } }
43    };
44}
45
46/// A two-component single-precision vector.
47#[repr(C)]
48#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
49#[serde(from = "[f32; 2]", into = "[f32; 2]")]
50pub struct Vec2 {
51    /// X component.
52    pub x: f32,
53    /// Y component.
54    pub y: f32,
55}
56
57impl Vec2 {
58    /// Zero vector.
59    pub const ZERO: Self = Self::splat(0.0);
60    /// Builds a vector.
61    #[must_use]
62    #[inline]
63    pub const fn new(x: f32, y: f32) -> Self {
64        Self { x, y }
65    }
66    /// Builds a vector with equal components.
67    #[must_use]
68    #[inline]
69    pub const fn splat(value: f32) -> Self {
70        Self::new(value, value)
71    }
72    /// Returns components.
73    #[must_use]
74    #[inline]
75    pub const fn to_array(self) -> [f32; 2] {
76        [self.x, self.y]
77    }
78}
79
80impl From<[f32; 2]> for Vec2 {
81    #[inline]
82    fn from(value: [f32; 2]) -> Self {
83        Self::new(value[0], value[1])
84    }
85}
86impl From<Vec2> for [f32; 2] {
87    #[inline]
88    fn from(value: Vec2) -> Self {
89        value.to_array()
90    }
91}
92impl From<glam::Vec2> for Vec2 {
93    #[inline]
94    fn from(value: glam::Vec2) -> Self {
95        value.to_array().into()
96    }
97}
98impl From<Vec2> for glam::Vec2 {
99    #[inline]
100    fn from(value: Vec2) -> Self {
101        Self::from_array(value.to_array())
102    }
103}
104component_ops!(Vec2 { x, y });
105
106/// A three-component single-precision vector.
107#[repr(C)]
108#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
109#[serde(from = "[f32; 3]", into = "[f32; 3]")]
110pub struct Vec3 {
111    /// X component.
112    pub x: f32,
113    /// Y component.
114    pub y: f32,
115    /// Z component.
116    pub z: f32,
117}
118
119impl Vec3 {
120    /// Zero vector.
121    pub const ZERO: Self = Self::splat(0.0);
122    /// One on every axis.
123    pub const ONE: Self = Self::splat(1.0);
124    /// Positive X axis.
125    pub const X: Self = Self::new(1.0, 0.0, 0.0);
126    /// Positive Y axis.
127    pub const Y: Self = Self::new(0.0, 1.0, 0.0);
128    /// Positive Z axis.
129    pub const Z: Self = Self::new(0.0, 0.0, 1.0);
130    /// NaN on every axis.
131    pub const NAN: Self = Self::splat(f32::NAN);
132    /// Builds a vector.
133    #[must_use]
134    #[inline]
135    pub const fn new(x: f32, y: f32, z: f32) -> Self {
136        Self { x, y, z }
137    }
138    /// Builds a vector with equal components.
139    #[must_use]
140    #[inline]
141    pub const fn splat(value: f32) -> Self {
142        Self::new(value, value, value)
143    }
144    /// Builds from an array.
145    #[must_use]
146    #[inline]
147    pub const fn from_array(value: [f32; 3]) -> Self {
148        Self::new(value[0], value[1], value[2])
149    }
150    /// Builds from the first three slice entries.
151    #[must_use]
152    #[inline]
153    pub fn from_slice(value: &[f32]) -> Self {
154        Self::from(glam::Vec3::from_slice(value))
155    }
156    /// Returns components.
157    #[must_use]
158    #[inline]
159    pub const fn to_array(&self) -> [f32; 3] {
160        [self.x, self.y, self.z]
161    }
162    /// Returns whether every component is finite.
163    #[must_use]
164    #[inline]
165    pub fn is_finite(self) -> bool {
166        glam::Vec3::from(self).is_finite()
167    }
168    /// Returns whether the length is approximately one.
169    #[must_use]
170    #[inline]
171    pub fn is_normalized(self) -> bool {
172        glam::Vec3::from(self).is_normalized()
173    }
174    /// Dot product.
175    #[must_use]
176    #[inline]
177    pub fn dot(self, rhs: Self) -> f32 {
178        glam::Vec3::from(self).dot(rhs.into())
179    }
180    /// Cross product.
181    #[must_use]
182    #[inline]
183    pub fn cross(self, rhs: Self) -> Self {
184        glam::Vec3::from(self).cross(rhs.into()).into()
185    }
186    /// Squared length.
187    #[must_use]
188    #[inline]
189    pub fn length_squared(self) -> f32 {
190        glam::Vec3::from(self).length_squared()
191    }
192    /// Length.
193    #[must_use]
194    #[inline]
195    pub fn length(self) -> f32 {
196        glam::Vec3::from(self).length()
197    }
198    /// Squared point distance.
199    #[must_use]
200    #[inline]
201    pub fn distance_squared(self, rhs: Self) -> f32 {
202        glam::Vec3::from(self).distance_squared(rhs.into())
203    }
204    /// Point distance.
205    #[must_use]
206    #[inline]
207    pub fn distance(self, rhs: Self) -> f32 {
208        glam::Vec3::from(self).distance(rhs.into())
209    }
210    /// Normalized vector.
211    #[must_use]
212    #[inline]
213    pub fn normalize(self) -> Self {
214        glam::Vec3::from(self).normalize().into()
215    }
216    /// Normalized vector, or zero when degenerate.
217    #[must_use]
218    #[inline]
219    pub fn normalize_or_zero(self) -> Self {
220        glam::Vec3::from(self).normalize_or_zero().into()
221    }
222    /// Attempts normalization.
223    #[must_use]
224    #[inline]
225    pub fn try_normalize(self) -> Option<Self> {
226        glam::Vec3::from(self).try_normalize().map(Into::into)
227    }
228    /// Componentwise absolute value.
229    #[must_use]
230    #[inline]
231    pub fn abs(self) -> Self {
232        glam::Vec3::from(self).abs().into()
233    }
234    /// Componentwise square root.
235    #[must_use]
236    #[inline]
237    pub fn sqrt(self) -> Self {
238        glam::Vec3::from(self).sqrt().into()
239    }
240    /// Componentwise reciprocal.
241    #[must_use]
242    #[inline]
243    pub fn recip(self) -> Self {
244        glam::Vec3::from(self).recip().into()
245    }
246    /// Componentwise minimum.
247    #[must_use]
248    #[inline]
249    pub fn min(self, rhs: Self) -> Self {
250        glam::Vec3::from(self).min(rhs.into()).into()
251    }
252    /// Componentwise maximum.
253    #[must_use]
254    #[inline]
255    pub fn max(self, rhs: Self) -> Self {
256        glam::Vec3::from(self).max(rhs.into()).into()
257    }
258    /// Componentwise clamp.
259    #[must_use]
260    #[inline]
261    pub fn clamp(self, min: Self, max: Self) -> Self {
262        glam::Vec3::from(self).clamp(min.into(), max.into()).into()
263    }
264    /// Smallest component.
265    #[must_use]
266    #[inline]
267    pub fn min_element(self) -> f32 {
268        glam::Vec3::from(self).min_element()
269    }
270    /// Largest component.
271    #[must_use]
272    #[inline]
273    pub fn max_element(self) -> f32 {
274        glam::Vec3::from(self).max_element()
275    }
276    /// Linear interpolation.
277    #[must_use]
278    #[inline]
279    pub fn lerp(self, rhs: Self, amount: f32) -> Self {
280        glam::Vec3::from(self).lerp(rhs.into(), amount).into()
281    }
282    /// Rejects this vector from a normalized direction.
283    #[must_use]
284    #[inline]
285    pub fn reject_from_normalized(self, normal: Self) -> Self {
286        glam::Vec3::from(self)
287            .reject_from_normalized(normal.into())
288            .into()
289    }
290    /// Returns a deterministic orthonormal vector.
291    #[must_use]
292    #[inline]
293    pub fn any_orthonormal_vector(self) -> Self {
294        glam::Vec3::from(self).any_orthonormal_vector().into()
295    }
296    /// Appends a W component.
297    #[must_use]
298    #[inline]
299    pub const fn extend(self, w: f32) -> Vec4 {
300        Vec4::new(self.x, self.y, self.z, w)
301    }
302}
303
304impl From<[f32; 3]> for Vec3 {
305    #[inline]
306    fn from(value: [f32; 3]) -> Self {
307        Self::from_array(value)
308    }
309}
310impl From<Vec3> for [f32; 3] {
311    #[inline]
312    fn from(value: Vec3) -> Self {
313        value.to_array()
314    }
315}
316impl From<glam::Vec3> for Vec3 {
317    #[inline]
318    fn from(value: glam::Vec3) -> Self {
319        value.to_array().into()
320    }
321}
322impl From<Vec3> for glam::Vec3 {
323    #[inline]
324    fn from(value: Vec3) -> Self {
325        Self::from_array(value.to_array())
326    }
327}
328impl From<&[f32; 3]> for Vec3 {
329    #[inline]
330    fn from(value: &[f32; 3]) -> Self {
331        Self::from_array(*value)
332    }
333}
334component_ops!(Vec3 { x, y, z });
335impl Mul<Vec3> for f32 {
336    type Output = Vec3;
337    #[inline]
338    fn mul(self, rhs: Vec3) -> Vec3 {
339        rhs * self
340    }
341}
342impl Sum for Vec3 {
343    #[inline]
344    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
345        iter.fold(Self::ZERO, Add::add)
346    }
347}
348
349/// A four-component SIMD-aligned single-precision vector.
350#[repr(C, align(16))]
351#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
352#[serde(from = "[f32; 4]", into = "[f32; 4]")]
353pub struct Vec4 {
354    /// X component.
355    pub x: f32,
356    /// Y component.
357    pub y: f32,
358    /// Z component.
359    pub z: f32,
360    /// W component.
361    pub w: f32,
362}
363
364impl Vec4 {
365    /// Zero vector.
366    pub const ZERO: Self = Self::splat(0.0);
367    /// Builds a vector.
368    #[must_use]
369    #[inline]
370    pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
371        Self { x, y, z, w }
372    }
373    /// Builds a vector with equal components.
374    #[must_use]
375    #[inline]
376    pub const fn splat(value: f32) -> Self {
377        Self::new(value, value, value, value)
378    }
379    /// Returns components.
380    #[must_use]
381    #[inline]
382    pub const fn to_array(self) -> [f32; 4] {
383        [self.x, self.y, self.z, self.w]
384    }
385    /// Returns XYZ.
386    #[must_use]
387    #[inline]
388    pub const fn truncate(self) -> Vec3 {
389        Vec3::new(self.x, self.y, self.z)
390    }
391    /// Vector length.
392    #[must_use]
393    #[inline]
394    pub fn length(self) -> f32 {
395        glam::Vec4::from(self).length()
396    }
397    /// Returns whether every component is finite.
398    #[must_use]
399    #[inline]
400    pub fn is_finite(self) -> bool {
401        glam::Vec4::from(self).is_finite()
402    }
403}
404
405impl From<[f32; 4]> for Vec4 {
406    #[inline]
407    fn from(value: [f32; 4]) -> Self {
408        Self::new(value[0], value[1], value[2], value[3])
409    }
410}
411impl From<Vec4> for [f32; 4] {
412    #[inline]
413    fn from(value: Vec4) -> Self {
414        value.to_array()
415    }
416}
417impl From<glam::Vec4> for Vec4 {
418    #[inline]
419    fn from(value: glam::Vec4) -> Self {
420        value.to_array().into()
421    }
422}
423impl From<Vec4> for glam::Vec4 {
424    #[inline]
425    fn from(value: Vec4) -> Self {
426        Self::from_array(value.to_array())
427    }
428}
429component_ops!(Vec4 { x, y, z, w });