macaw/
vec4_ext.rs

1use super::UVec4;
2use super::Vec4;
3use super::prelude::*;
4use super::uvec4;
5use super::vec4;
6
7#[cfg(target_arch = "spirv")]
8use num_traits::Float;
9
10/// Extensions to [`Vec4`]
11///
12/// Adds additional functionality to [`Vec4`] that [`glam`] doesn't have.
13pub trait Vec4Ext {
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    /// Return only the sine of each component.
33    #[must_use]
34    fn sin(self) -> Self;
35
36    /// Return the square root of each component.
37    #[must_use]
38    fn sqrt(self) -> Self;
39
40    /// Raw transmute each component to u32.
41    #[must_use]
42    fn to_bits(self) -> UVec4;
43
44    /// Get the mean value of all four components
45    #[must_use]
46    fn mean(self) -> f32;
47
48    /// Returns true if all components of the vector is the same within an absolute difference of `max_abs_diff`
49    #[must_use]
50    fn has_equal_components(self, max_abs_diff: f32) -> bool;
51}
52
53impl Vec4Ext for Vec4 {
54    #[inline]
55    fn trunc(self) -> Self {
56        vec4(
57            self.x.trunc(),
58            self.y.trunc(),
59            self.z.trunc(),
60            self.w.trunc(),
61        )
62    }
63
64    fn step(self, value: Self) -> Self {
65        vec4(
66            self.x.step(value.x),
67            self.y.step(value.y),
68            self.z.step(value.z),
69            self.w.step(value.z),
70        )
71    }
72
73    fn step_select(self, value: Self, less: Self, greater_or_equal: Self) -> Self {
74        vec4(
75            self.x.step_select(value.x, less.x, greater_or_equal.x),
76            self.y.step_select(value.y, less.y, greater_or_equal.y),
77            self.z.step_select(value.z, less.z, greater_or_equal.z),
78            self.w.step_select(value.w, less.w, greater_or_equal.w),
79        )
80    }
81
82    #[inline]
83    fn fract(self) -> Self {
84        vec4(
85            self.x.fract(),
86            self.y.fract(),
87            self.z.fract(),
88            self.w.fract(),
89        )
90    }
91
92    #[inline]
93    fn sin(self) -> Self {
94        vec4(self.x.sin(), self.y.sin(), self.z.sin(), self.w.sin())
95    }
96
97    fn sqrt(self) -> Self {
98        vec4(self.x.sqrt(), self.y.sqrt(), self.z.sqrt(), self.w.sqrt())
99    }
100
101    fn to_bits(self) -> UVec4 {
102        uvec4(
103            self.x.to_bits(),
104            self.y.to_bits(),
105            self.z.to_bits(),
106            self.w.to_bits(),
107        )
108    }
109
110    fn mean(self) -> f32 {
111        (self.x + self.y + self.z + self.w) / 4.0
112    }
113
114    fn has_equal_components(self, max_abs_diff: f32) -> bool {
115        (self.x - self.y).abs() < max_abs_diff
116            && (self.y - self.z).abs() < max_abs_diff
117            && (self.x - self.z).abs() < max_abs_diff
118            && (self.w - self.x).abs() < max_abs_diff
119            && (self.w - self.y).abs() < max_abs_diff
120            && (self.w - self.z).abs() < max_abs_diff
121    }
122}
123
124#[cfg(test)]
125mod test {
126    use super::*;
127
128    #[test]
129    fn test_mean() {
130        assert!((Vec4::ONE.mean() - 1.0).abs() < 0.0001);
131    }
132
133    #[test]
134    fn test_mean_2() {
135        assert!((vec4(1.0, 2.0, 3.0, 4.0).mean() - 2.5).abs() < 0.0001);
136    }
137
138    #[test]
139    fn test_has_equal_components() {
140        assert!(Vec4::ONE.has_equal_components(0.001));
141    }
142
143    #[test]
144    fn test_has_equal_components_2() {
145        assert!(vec4(0.0, 0.00001, -0.00001, 0.0).has_equal_components(0.001));
146    }
147
148    #[test]
149    fn test_has_equal_components_3() {
150        assert!(!vec4(1.0, 0.0, 0.0, 0.0).has_equal_components(0.0001));
151    }
152}