Skip to main content

macaw/
vec3_ext.rs

1use super::Vec3;
2use super::prelude::*;
3use super::vec3;
4
5use glam::Vec3A;
6use glam::vec3a;
7#[cfg(target_arch = "spirv")]
8use num_traits::Float;
9
10/// Extensions to [`Vec3`]
11///
12/// Adds additional functionality to [`Vec3`] that [`glam`] doesn't have.
13pub trait Vec3Ext {
14    /// For element `i` of `self`, return `v[i].trunc()`
15    #[must_use]
16    fn trunc(self) -> Self;
17
18    /// For element `i` of the return value, returns 0.0 if `value[i] < self[i]` and 1.0 otherwise.
19    ///
20    /// Similar to glsl's step(edge, x), which translates into edge.step(x)
21    #[must_use]
22    fn step(self, value: Self) -> Self;
23
24    /// Selects between `true` and `false` based on the result of `value[i] < self[i]`
25    #[must_use]
26    fn step_select(self, value: Self, tru: Self, fals: Self) -> Self;
27
28    /// Return only the fractional parts of each component.
29    #[must_use]
30    fn fract(self) -> Self;
31
32    /// Clamp all components of `self` to the range `[0.0, 1.0]`
33    #[must_use]
34    fn saturate(self) -> Self;
35
36    /// Square root of all three components.
37    #[must_use]
38    fn sqrt(self) -> Self;
39
40    /// Natural logarithm of all three components.
41    #[must_use]
42    fn ln(self) -> Self;
43
44    /// The reflection of a incident vector and surface normal.
45    #[must_use]
46    fn reflect(self, normal: Self) -> Self;
47
48    /// Get the mean value of all three components
49    #[must_use]
50    fn mean(self) -> f32;
51
52    /// Returns true if all components of the vector is the same within an absolute difference of `max_abs_diff`
53    #[must_use]
54    fn has_equal_components(self, max_abs_diff: f32) -> bool;
55
56    /// Performs a an exponential interpolation between `self` and `other` using `a` to weight between them.
57    /// The return value is computed as `self.powf(1−a) * other.powf(a)`.
58    ///
59    /// This means that the interpolation is linear in the log domain, so it is useful when interpolating
60    /// values that will be multiplied, such as scaling factors.
61    #[must_use]
62    fn eerp(self, other: Self, a: f32) -> Self;
63}
64
65impl Vec3Ext for Vec3 {
66    /// For element `i` of `self`, return `v[i].trunc()`
67    #[inline]
68    fn trunc(self) -> Self {
69        vec3(self.x.trunc(), self.y.trunc(), self.z.trunc())
70    }
71
72    #[inline]
73    fn step(self, value: Self) -> Self {
74        vec3(
75            self.x.step(value.x),
76            self.y.step(value.y),
77            self.z.step(value.z),
78        )
79    }
80
81    #[inline]
82    fn step_select(self, value: Self, less: Self, greater_or_equal: Self) -> Self {
83        vec3(
84            self.x.step_select(value.x, less.x, greater_or_equal.x),
85            self.y.step_select(value.y, less.y, greater_or_equal.y),
86            self.z.step_select(value.z, less.z, greater_or_equal.z),
87        )
88    }
89
90    #[inline]
91    fn fract(self) -> Self {
92        vec3(self.x.fract(), self.y.fract(), self.z.fract())
93    }
94
95    #[inline]
96    fn saturate(self) -> Self {
97        vec3(self.x.saturate(), self.y.saturate(), self.z.saturate())
98    }
99
100    #[inline]
101    fn sqrt(self) -> Self {
102        vec3(self.x.sqrt(), self.y.sqrt(), self.z.sqrt())
103    }
104
105    #[inline]
106    fn ln(self) -> Self {
107        vec3(self.x.ln(), self.y.ln(), self.z.ln())
108    }
109
110    #[inline]
111    fn reflect(self, normal: Self) -> Self {
112        self - 2.0 * normal * self.dot(normal)
113    }
114
115    #[inline]
116    fn mean(self) -> f32 {
117        (self.x + self.y + self.z) / 3.0
118    }
119
120    #[inline]
121    fn has_equal_components(self, max_abs_diff: f32) -> bool {
122        (self.x - self.y).abs() < max_abs_diff
123            && (self.y - self.z).abs() < max_abs_diff
124            && (self.x - self.z).abs() < max_abs_diff
125    }
126
127    #[inline(always)]
128    fn eerp(self, other: Self, a: f32) -> Self {
129        Self::new(
130            self.x.eerp(other.x, a),
131            self.y.eerp(other.y, a),
132            self.z.eerp(other.z, a),
133        )
134    }
135}
136
137impl Vec3Ext for Vec3A {
138    /// For element `i` of `self`, return `v[i].trunc()`
139    #[inline]
140    fn trunc(self) -> Self {
141        vec3a(self.x.trunc(), self.y.trunc(), self.z.trunc())
142    }
143
144    #[inline]
145    fn step(self, value: Self) -> Self {
146        vec3a(
147            self.x.step(value.x),
148            self.y.step(value.y),
149            self.z.step(value.z),
150        )
151    }
152
153    #[inline]
154    fn step_select(self, value: Self, less: Self, greater_or_equal: Self) -> Self {
155        vec3a(
156            self.x.step_select(value.x, less.x, greater_or_equal.x),
157            self.y.step_select(value.y, less.y, greater_or_equal.y),
158            self.z.step_select(value.z, less.z, greater_or_equal.z),
159        )
160    }
161
162    #[inline]
163    fn fract(self) -> Self {
164        vec3a(self.x.fract(), self.y.fract(), self.z.fract())
165    }
166
167    #[inline]
168    fn saturate(self) -> Self {
169        vec3a(self.x.saturate(), self.y.saturate(), self.z.saturate())
170    }
171
172    #[inline]
173    fn sqrt(self) -> Self {
174        vec3a(self.x.sqrt(), self.y.sqrt(), self.z.sqrt())
175    }
176
177    #[inline]
178    fn ln(self) -> Self {
179        vec3a(self.x.ln(), self.y.ln(), self.z.ln())
180    }
181
182    #[inline]
183    fn reflect(self, normal: Self) -> Self {
184        self - 2.0 * normal * self.dot(normal)
185    }
186
187    #[inline]
188    fn mean(self) -> f32 {
189        (self.x + self.y + self.z) / 3.0
190    }
191
192    #[inline]
193    fn has_equal_components(self, max_abs_diff: f32) -> bool {
194        (self.x - self.y).abs() < max_abs_diff
195            && (self.y - self.z).abs() < max_abs_diff
196            && (self.x - self.z).abs() < max_abs_diff
197    }
198
199    #[inline(always)]
200    fn eerp(self, other: Self, a: f32) -> Self {
201        Self::new(
202            self.x.eerp(other.x, a),
203            self.y.eerp(other.y, a),
204            self.z.eerp(other.z, a),
205        )
206    }
207}
208
209/// Coordinate system extension to [`Vec3`]
210///
211/// This crate is opinionated  with what coordinate system it uses and this adds
212/// additional functions to access the coordinate system axis
213///
214/// The exact coordinate system we use is right-handed with +X = right, +Y = up, -Z = forward, +Z = back
215pub trait CoordinateSystem {
216    /// A unit length vector pointing in the canonical up direction.
217    fn up() -> Self;
218
219    /// A unit length vector pointing in the canonical down direction.
220    fn down() -> Self;
221
222    /// A unit length vector pointing in the canonical right direction.
223    ///
224    /// This is the right hand side of a first person character.
225    fn right() -> Self;
226
227    /// A unit length vector pointing in the canonical left direction.
228    fn left() -> Self;
229
230    /// A unit length vector pointing in the canonical forward direction.
231    ///
232    /// This is the direction a character faces, or a car drives towards.
233    fn forward() -> Self;
234
235    /// A unit length vector pointing in the canonical back direction.
236    fn back() -> Self;
237}
238
239impl CoordinateSystem for Vec3 {
240    fn up() -> Self {
241        Self::new(0.0, 1.0, 0.0)
242    }
243
244    fn down() -> Self {
245        Self::new(0.0, -1.0, 0.0)
246    }
247
248    fn right() -> Self {
249        Self::new(1.0, 0.0, 0.0)
250    }
251
252    fn left() -> Self {
253        Self::new(-1.0, 0.0, 0.0)
254    }
255
256    fn forward() -> Self {
257        Self::new(0.0, 0.0, -1.0)
258    }
259
260    fn back() -> Self {
261        Self::new(0.0, 0.0, 1.0)
262    }
263}
264
265#[cfg(test)]
266mod test {
267    use super::*;
268
269    #[test]
270    fn test_mean() {
271        assert!((Vec3::ONE.mean() - 1.0).abs() < 0.0001);
272    }
273
274    #[test]
275    fn test_mean_2() {
276        assert!((vec3(1.0, 2.0, 3.0).mean() - 2.0).abs() < 0.0001);
277    }
278
279    #[test]
280    fn test_has_equal_components() {
281        assert!(Vec3::ONE.has_equal_components(0.001));
282    }
283
284    #[test]
285    fn test_has_equal_components_2() {
286        assert!(vec3(0.0, 0.00001, -0.00001).has_equal_components(0.001));
287    }
288
289    #[test]
290    fn test_has_equal_components_3() {
291        assert!(!vec3(1.0, 0.0, 0.0).has_equal_components(0.0001));
292    }
293}