ferravex_math/
vector.rs

1use std::ops::{
2    Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
3};
4
5macro_rules! vector {
6    ($name:ident, $mask:ident, $n:expr, $($field:ident : $index:tt),+) => {
7        #[repr(C)]
8        #[derive(Clone, Copy, Debug, Default, PartialEq)]
9        pub struct $name { $(pub $field: f32),+ }
10
11        #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
12        pub struct $mask { $(pub $field: bool),+ }
13        impl $mask {
14            pub const fn all(self) -> bool { true $(&& self.$field)+ }
15            pub const fn any(self) -> bool { false $(|| self.$field)+ }
16            pub const fn to_array(self) -> [bool; $n] { [$(self.$field),+] }
17        }
18        impl $name {
19            pub const ZERO: Self = Self::splat(0.0);
20            pub const ONE: Self = Self::splat(1.0);
21            pub const NEG_ONE: Self = Self::splat(-1.0);
22            pub const NAN: Self = Self::splat(f32::NAN);
23            pub const INFINITY: Self = Self::splat(f32::INFINITY);
24            pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
25            pub const fn new($($field: f32),+) -> Self { Self {$($field),+} }
26            pub const fn splat(value: f32) -> Self { Self {$($field: value),+} }
27            pub const fn from_array(values: [f32; $n]) -> Self { Self {$($field: values[$index]),+} }
28            pub const fn to_array(self) -> [f32; $n] { [$(self.$field),+] }
29            pub fn from_slice(values: &[f32]) -> Self { Self {$($field: values[$index]),+} }
30            pub fn write_to_slice(self, values: &mut [f32]) { $(values[$index] = self.$field;)+ }
31            pub fn is_finite(self) -> bool { true $(&& self.$field.is_finite())+ }
32            pub fn is_nan(self) -> bool { false $(|| self.$field.is_nan())+ }
33            pub fn dot(self, rhs: Self) -> f32 { 0.0 $(+ self.$field * rhs.$field)+ }
34            pub fn length_squared(self) -> f32 { self.dot(self) }
35            /// Uses wider intermediates so finite small vectors do not underflow.
36            pub fn length(self) -> f32 { (0.0_f64 $(+ f64::from(self.$field).powi(2))+).sqrt() as f32 }
37            pub fn length_recip(self) -> f32 { self.length().recip() }
38            pub fn distance(self, other: Self) -> f32 { (self-other).length() }
39            pub fn distance_squared(self, other: Self) -> f32 { (self-other).length_squared() }
40            /// Normalizes every finite nonzero vector, including subnormal inputs.
41            pub fn try_normalize(self) -> Option<Self> {
42                let length = (0.0_f64 $(+ f64::from(self.$field).powi(2))+).sqrt();
43                if length > 0.0 && length.is_finite() {
44                    Some(Self {$($field: (f64::from(self.$field) / length) as f32),+})
45                } else { None }
46            }
47            pub fn normalize(self) -> Self { self.try_normalize().unwrap_or(Self::NAN) }
48            pub fn normalize_or_zero(self) -> Self { self.try_normalize().unwrap_or(Self::ZERO) }
49            pub fn normalize_or(self, fallback: Self) -> Self { self.try_normalize().unwrap_or(fallback) }
50            pub fn is_normalized(self) -> bool { (self.length_squared()-1.0).abs() <= 1.0e-5 }
51            pub fn min(self, rhs: Self) -> Self { Self {$($field: self.$field.min(rhs.$field)),+} }
52            pub fn max(self, rhs: Self) -> Self { Self {$($field: self.$field.max(rhs.$field)),+} }
53            pub fn min_element(self) -> f32 { self.to_array().into_iter().fold(f32::INFINITY, f32::min) }
54            pub fn max_element(self) -> f32 { self.to_array().into_iter().fold(f32::NEG_INFINITY, f32::max) }
55            pub fn element_sum(self) -> f32 { 0.0 $(+ self.$field)+ }
56            pub fn element_product(self) -> f32 { 1.0 $(* self.$field)+ }
57            pub fn abs(self) -> Self { Self {$($field: self.$field.abs()),+} }
58            pub fn signum(self) -> Self { Self {$($field: self.$field.signum()),+} }
59            pub fn floor(self) -> Self { Self {$($field: self.$field.floor()),+} }
60            pub fn ceil(self) -> Self { Self {$($field: self.$field.ceil()),+} }
61            pub fn round(self) -> Self { Self {$($field: self.$field.round()),+} }
62            pub fn trunc(self) -> Self { Self {$($field: self.$field.trunc()),+} }
63            pub fn fract(self) -> Self { self-self.floor() }
64            pub fn recip(self) -> Self { Self {$($field: self.$field.recip()),+} }
65            pub fn sqrt(self) -> Self { Self {$($field: self.$field.sqrt()),+} }
66            pub fn powf(self, exponent: f32) -> Self { Self {$($field: self.$field.powf(exponent)),+} }
67            pub fn exp(self) -> Self { Self {$($field: self.$field.exp()),+} }
68            pub fn clamp(self, min: Self, max: Self) -> Self { Self {$($field: self.$field.clamp(min.$field, max.$field)),+} }
69            pub fn clamp_length(self, min: f32, max: f32) -> Self {
70                assert!(min.is_finite() && max.is_finite() && min >= 0.0 && min <= max);
71                let length = self.length();
72                if length > max { self.normalize_or_zero()*max }
73                else if length < min { self.normalize_or_zero()*min }
74                else { self }
75            }
76            pub fn clamp_length_max(self, max: f32) -> Self {
77                assert!(max.is_finite() && max >= 0.0);
78                if self.length() > max { self.normalize_or_zero()*max } else { self }
79            }
80            pub fn clamp_length_min(self, min: f32) -> Self {
81                assert!(min.is_finite() && min >= 0.0);
82                if self.length() < min { self.normalize_or_zero()*min } else { self }
83            }
84            pub fn lerp(self, rhs: Self, t: f32) -> Self { self * (1.0-t) + rhs*t }
85            pub fn mul_add(self, multiplier: Self, add: Self) -> Self { Self {$($field: self.$field.mul_add(multiplier.$field, add.$field)),+} }
86            pub fn abs_diff_eq(self, rhs: Self, tolerance: f32) -> bool { (self-rhs).abs().cmple(Self::splat(tolerance)).all() }
87            pub fn cmpeq(self, rhs: Self) -> $mask { $mask {$($field: self.$field == rhs.$field),+} }
88            pub fn cmpne(self, rhs: Self) -> $mask { $mask {$($field: self.$field != rhs.$field),+} }
89            pub fn cmplt(self, rhs: Self) -> $mask { $mask {$($field: self.$field < rhs.$field),+} }
90            pub fn cmple(self, rhs: Self) -> $mask { $mask {$($field: self.$field <= rhs.$field),+} }
91            pub fn cmpgt(self, rhs: Self) -> $mask { $mask {$($field: self.$field > rhs.$field),+} }
92            pub fn cmpge(self, rhs: Self) -> $mask { $mask {$($field: self.$field >= rhs.$field),+} }
93            pub fn select(mask: $mask, if_true: Self, if_false: Self) -> Self { Self {$($field: if mask.$field {if_true.$field} else {if_false.$field}),+} }
94            pub fn project_onto(self, other: Self) -> Self { other * (self.dot(other)/other.length_squared()) }
95            pub fn reject_from(self, other: Self) -> Self { self-self.project_onto(other) }
96            pub fn project_onto_normalized(self, normal: Self) -> Self { normal*self.dot(normal) }
97            pub fn reject_from_normalized(self, normal: Self) -> Self { self-self.project_onto_normalized(normal) }
98            /// Reflects an incident vector about a unit surface normal.
99            pub fn reflect(self, normal: Self) -> Self { self-2.0*self.dot(normal)*normal }
100            pub fn move_towards(self, rhs: Self, max_distance: f32) -> Self {
101                assert!(max_distance.is_finite() && max_distance >= 0.0);
102                let difference=rhs-self;
103                if difference.length() <= max_distance {rhs} else {self+difference.normalize_or_zero()*max_distance}
104            }
105        }
106        impl From<[f32; $n]> for $name { fn from(v: [f32; $n]) -> Self { Self::from_array(v) } }
107        impl From<$name> for [f32; $n] { fn from(v: $name) -> Self { v.to_array() } }
108        impl Index<usize> for $name { type Output=f32; fn index(&self,index:usize)->&f32 { match index {$($index=>&self.$field,)+ _=>panic!("vector index {index} is out of range")} } }
109        impl IndexMut<usize> for $name { fn index_mut(&mut self,index:usize)->&mut f32 { match index {$($index=>&mut self.$field,)+ _=>panic!("vector index {index} is out of range")} } }
110        impl Neg for $name { type Output=Self; fn neg(self)->Self { Self {$($field:-self.$field),+} } }
111        impl Add for $name { type Output=Self; fn add(self,rhs:Self)->Self { Self {$($field:self.$field+rhs.$field),+} } }
112        impl Sub for $name { type Output=Self; fn sub(self,rhs:Self)->Self { Self {$($field:self.$field-rhs.$field),+} } }
113        impl Mul for $name { type Output=Self; fn mul(self,rhs:Self)->Self { Self {$($field:self.$field*rhs.$field),+} } }
114        impl Div for $name { type Output=Self; fn div(self,rhs:Self)->Self { Self {$($field:self.$field/rhs.$field),+} } }
115        impl Add<f32> for $name { type Output=Self; fn add(self,rhs:f32)->Self { self+Self::splat(rhs) } }
116        impl Sub<f32> for $name { type Output=Self; fn sub(self,rhs:f32)->Self { self-Self::splat(rhs) } }
117        impl Mul<f32> for $name { type Output=Self; fn mul(self,rhs:f32)->Self { Self {$($field:self.$field*rhs),+} } }
118        impl Div<f32> for $name { type Output=Self; fn div(self,rhs:f32)->Self { Self {$($field:self.$field/rhs),+} } }
119        impl Add<$name> for f32 { type Output=$name; fn add(self,rhs:$name)->$name { $name::splat(self)+rhs } }
120        impl Sub<$name> for f32 { type Output=$name; fn sub(self,rhs:$name)->$name { $name::splat(self)-rhs } }
121        impl Mul<$name> for f32 { type Output=$name; fn mul(self,rhs:$name)->$name { rhs*self } }
122        impl Div<$name> for f32 { type Output=$name; fn div(self,rhs:$name)->$name { $name::splat(self)/rhs } }
123        impl AddAssign for $name { fn add_assign(&mut self,rhs:Self) { *self=*self+rhs; } }
124        impl SubAssign for $name { fn sub_assign(&mut self,rhs:Self) { *self=*self-rhs; } }
125        impl MulAssign for $name { fn mul_assign(&mut self,rhs:Self) { *self=*self*rhs; } }
126        impl DivAssign for $name { fn div_assign(&mut self,rhs:Self) { *self=*self/rhs; } }
127        impl AddAssign<f32> for $name { fn add_assign(&mut self,rhs:f32) { *self=*self+rhs; } }
128        impl SubAssign<f32> for $name { fn sub_assign(&mut self,rhs:f32) { *self=*self-rhs; } }
129        impl MulAssign<f32> for $name { fn mul_assign(&mut self,rhs:f32) { *self=*self*rhs; } }
130        impl DivAssign<f32> for $name { fn div_assign(&mut self,rhs:f32) { *self=*self/rhs; } }
131        impl std::iter::Sum for $name { fn sum<I:Iterator<Item=Self>>(iter:I)->Self { iter.fold(Self::ZERO, |a,b|a+b) } }
132        impl std::iter::Product for $name { fn product<I:Iterator<Item=Self>>(iter:I)->Self { iter.fold(Self::ONE, |a,b|a*b) } }
133    }
134}
135vector!(Vec2, BVec2, 2, x:0,y:1);
136vector!(Vec3, BVec3, 3, x:0,y:1,z:2);
137vector!(Vec4, BVec4, 4, x:0,y:1,z:2,w:3);
138
139pub const fn vec2(x: f32, y: f32) -> Vec2 {
140    Vec2::new(x, y)
141}
142pub const fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
143    Vec3::new(x, y, z)
144}
145pub const fn vec4(x: f32, y: f32, z: f32, w: f32) -> Vec4 {
146    Vec4::new(x, y, z, w)
147}
148impl From<(f32, f32)> for Vec2 {
149    fn from(v: (f32, f32)) -> Self {
150        Self::new(v.0, v.1)
151    }
152}
153impl From<Vec2> for (f32, f32) {
154    fn from(v: Vec2) -> Self {
155        (v.x, v.y)
156    }
157}
158impl From<(f32, f32, f32)> for Vec3 {
159    fn from(v: (f32, f32, f32)) -> Self {
160        Self::new(v.0, v.1, v.2)
161    }
162}
163impl From<(f32, f32, f32, f32)> for Vec4 {
164    fn from(v: (f32, f32, f32, f32)) -> Self {
165        Self::new(v.0, v.1, v.2, v.3)
166    }
167}
168impl Vec2 {
169    pub const X: Self = Self::new(1.0, 0.0);
170    pub const Y: Self = Self::new(0.0, 1.0);
171    pub const NEG_X: Self = Self::new(-1.0, 0.0);
172    pub const NEG_Y: Self = Self::new(0.0, -1.0);
173    pub const AXES: [Self; 2] = [Self::X, Self::Y];
174    pub const fn extend(self, z: f32) -> Vec3 {
175        vec3(self.x, self.y, z)
176    }
177    pub const fn perp(self) -> Self {
178        vec2(-self.y, self.x)
179    }
180    pub fn perp_dot(self, rhs: Self) -> f32 {
181        self.x * rhs.y - self.y * rhs.x
182    }
183    pub fn from_angle(angle: f32) -> Self {
184        let (s, c) = angle.sin_cos();
185        vec2(c, s)
186    }
187    pub fn to_angle(self) -> f32 {
188        self.y.atan2(self.x)
189    }
190    /// Signed shortest angle from this direction to `rhs` in [-pi, pi].
191    pub fn angle_between(self, rhs: Self) -> f32 {
192        let a = self.normalize();
193        let b = rhs.normalize();
194        a.perp_dot(b).atan2(a.dot(b))
195    }
196    /// Complex multiplication, useful for applying a unit 2D rotation.
197    pub fn rotate(self, rhs: Self) -> Self {
198        vec2(
199            self.x * rhs.x - self.y * rhs.y,
200            self.y * rhs.x + self.x * rhs.y,
201        )
202    }
203    pub const fn yx(self) -> Self {
204        vec2(self.y, self.x)
205    }
206    pub const fn xx(self) -> Self {
207        Self::splat(self.x)
208    }
209    pub const fn yy(self) -> Self {
210        Self::splat(self.y)
211    }
212}
213impl Vec3 {
214    pub const X: Self = Self::new(1.0, 0.0, 0.0);
215    pub const Y: Self = Self::new(0.0, 1.0, 0.0);
216    pub const Z: Self = Self::new(0.0, 0.0, 1.0);
217    pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0);
218    pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0);
219    pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0);
220    pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z];
221    pub const fn extend(self, w: f32) -> Vec4 {
222        vec4(self.x, self.y, self.z, w)
223    }
224    pub const fn truncate(self) -> Vec2 {
225        vec2(self.x, self.y)
226    }
227    pub fn cross(self, rhs: Self) -> Self {
228        vec3(
229            self.y * rhs.z - self.z * rhs.y,
230            self.z * rhs.x - self.x * rhs.z,
231            self.x * rhs.y - self.y * rhs.x,
232        )
233    }
234    pub fn angle_between(self, rhs: Self) -> f32 {
235        self.normalize()
236            .dot(rhs.normalize())
237            .clamp(-1.0, 1.0)
238            .acos()
239    }
240    pub fn any_orthogonal_vector(self) -> Self {
241        if self.x.abs() < self.y.abs() {
242            self.cross(Self::X)
243        } else {
244            self.cross(Self::Y)
245        }
246    }
247    pub fn any_orthonormal_vector(self) -> Self {
248        self.any_orthogonal_vector().normalize()
249    }
250    pub const fn xy(self) -> Vec2 {
251        vec2(self.x, self.y)
252    }
253    pub const fn xz(self) -> Vec2 {
254        vec2(self.x, self.z)
255    }
256    pub const fn yz(self) -> Vec2 {
257        vec2(self.y, self.z)
258    }
259    pub const fn yx(self) -> Vec2 {
260        vec2(self.y, self.x)
261    }
262    pub const fn zx(self) -> Vec2 {
263        vec2(self.z, self.x)
264    }
265    pub const fn zy(self) -> Vec2 {
266        vec2(self.z, self.y)
267    }
268    pub const fn xyz(self) -> Self {
269        self
270    }
271    pub const fn xzy(self) -> Self {
272        vec3(self.x, self.z, self.y)
273    }
274    pub const fn yxz(self) -> Self {
275        vec3(self.y, self.x, self.z)
276    }
277    pub const fn yzx(self) -> Self {
278        vec3(self.y, self.z, self.x)
279    }
280    pub const fn zxy(self) -> Self {
281        vec3(self.z, self.x, self.y)
282    }
283    pub const fn zyx(self) -> Self {
284        vec3(self.z, self.y, self.x)
285    }
286}
287impl Vec4 {
288    pub const X: Self = Self::new(1.0, 0.0, 0.0, 0.0);
289    pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0);
290    pub const Z: Self = Self::new(0.0, 0.0, 1.0, 0.0);
291    pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0);
292    pub const AXES: [Self; 4] = [Self::X, Self::Y, Self::Z, Self::W];
293    pub const fn truncate(self) -> Vec3 {
294        vec3(self.x, self.y, self.z)
295    }
296    pub const fn xyz(self) -> Vec3 {
297        self.truncate()
298    }
299    pub const fn xy(self) -> Vec2 {
300        vec2(self.x, self.y)
301    }
302    pub const fn xz(self) -> Vec2 {
303        vec2(self.x, self.z)
304    }
305    pub const fn zw(self) -> Vec2 {
306        vec2(self.z, self.w)
307    }
308    pub const fn xyzw(self) -> Self {
309        self
310    }
311    pub const fn wzyx(self) -> Self {
312        vec4(self.w, self.z, self.y, self.x)
313    }
314}
315
316/// Compatibility imports: common swizzles are inherent methods.
317pub trait Vec2Swizzles {}
318pub trait Vec3Swizzles {}
319pub trait Vec4Swizzles {}
320impl Vec2Swizzles for Vec2 {}
321impl Vec3Swizzles for Vec3 {}
322impl Vec4Swizzles for Vec4 {}