bevy_math/
common_traits.rs

1//! This module contains abstract mathematical traits shared by types used in `bevy_math`.
2
3use crate::{ops, Dir2, Dir3, Dir3A, Quat, Rot2, Vec2, Vec3, Vec3A, Vec4};
4use core::{
5    fmt::Debug,
6    ops::{Add, Div, Mul, Neg, Sub},
7};
8use variadics_please::all_tuples_enumerated;
9
10/// A type that supports the mathematical operations of a real vector space, irrespective of dimension.
11/// In particular, this means that the implementing type supports:
12/// - Scalar multiplication and division on the right by elements of `f32`
13/// - Negation
14/// - Addition and subtraction
15/// - Zero
16///
17/// Within the limitations of floating point arithmetic, all the following are required to hold:
18/// - (Associativity of addition) For all `u, v, w: Self`, `(u + v) + w == u + (v + w)`.
19/// - (Commutativity of addition) For all `u, v: Self`, `u + v == v + u`.
20/// - (Additive identity) For all `v: Self`, `v + Self::ZERO == v`.
21/// - (Additive inverse) For all `v: Self`, `v - v == v + (-v) == Self::ZERO`.
22/// - (Compatibility of multiplication) For all `a, b: f32`, `v: Self`, `v * (a * b) == (v * a) * b`.
23/// - (Multiplicative identity) For all `v: Self`, `v * 1.0 == v`.
24/// - (Distributivity for vector addition) For all `a: f32`, `u, v: Self`, `(u + v) * a == u * a + v * a`.
25/// - (Distributivity for scalar addition) For all `a, b: f32`, `v: Self`, `v * (a + b) == v * a + v * b`.
26///
27/// Note that, because implementing types use floating point arithmetic, they are not required to actually
28/// implement `PartialEq` or `Eq`.
29pub trait VectorSpace:
30    Mul<f32, Output = Self>
31    + Div<f32, Output = Self>
32    + Add<Self, Output = Self>
33    + Sub<Self, Output = Self>
34    + Neg<Output = Self>
35    + Default
36    + Debug
37    + Clone
38    + Copy
39{
40    /// The zero vector, which is the identity of addition for the vector space type.
41    const ZERO: Self;
42
43    /// Perform vector space linear interpolation between this element and another, based
44    /// on the parameter `t`. When `t` is `0`, `self` is recovered. When `t` is `1`, `rhs`
45    /// is recovered.
46    ///
47    /// Note that the value of `t` is not clamped by this function, so extrapolating outside
48    /// of the interval `[0,1]` is allowed.
49    #[inline]
50    fn lerp(self, rhs: Self, t: f32) -> Self {
51        self * (1. - t) + rhs * t
52    }
53}
54
55impl VectorSpace for Vec4 {
56    const ZERO: Self = Vec4::ZERO;
57}
58
59impl VectorSpace for Vec3 {
60    const ZERO: Self = Vec3::ZERO;
61}
62
63impl VectorSpace for Vec3A {
64    const ZERO: Self = Vec3A::ZERO;
65}
66
67impl VectorSpace for Vec2 {
68    const ZERO: Self = Vec2::ZERO;
69}
70
71impl VectorSpace for f32 {
72    const ZERO: Self = 0.0;
73}
74
75/// A type consisting of formal sums of elements from `V` and `W`. That is,
76/// each value `Sum(v, w)` is thought of as `v + w`, with no available
77/// simplification. In particular, if `V` and `W` are [vector spaces], then
78/// `Sum<V, W>` is a vector space whose dimension is the sum of those of `V`
79/// and `W`, and the field accessors `.0` and `.1` are vector space projections.
80///
81/// [vector spaces]: VectorSpace
82#[derive(Debug, Clone, Copy)]
83#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
84#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
85pub struct Sum<V, W>(pub V, pub W);
86
87impl<V, W> Mul<f32> for Sum<V, W>
88where
89    V: VectorSpace,
90    W: VectorSpace,
91{
92    type Output = Self;
93    fn mul(self, rhs: f32) -> Self::Output {
94        Sum(self.0 * rhs, self.1 * rhs)
95    }
96}
97
98impl<V, W> Div<f32> for Sum<V, W>
99where
100    V: VectorSpace,
101    W: VectorSpace,
102{
103    type Output = Self;
104    fn div(self, rhs: f32) -> Self::Output {
105        Sum(self.0 / rhs, self.1 / rhs)
106    }
107}
108
109impl<V, W> Add<Self> for Sum<V, W>
110where
111    V: VectorSpace,
112    W: VectorSpace,
113{
114    type Output = Self;
115    fn add(self, other: Self) -> Self::Output {
116        Sum(self.0 + other.0, self.1 + other.1)
117    }
118}
119
120impl<V, W> Sub<Self> for Sum<V, W>
121where
122    V: VectorSpace,
123    W: VectorSpace,
124{
125    type Output = Self;
126    fn sub(self, other: Self) -> Self::Output {
127        Sum(self.0 - other.0, self.1 - other.1)
128    }
129}
130
131impl<V, W> Neg for Sum<V, W>
132where
133    V: VectorSpace,
134    W: VectorSpace,
135{
136    type Output = Self;
137    fn neg(self) -> Self::Output {
138        Sum(-self.0, -self.1)
139    }
140}
141
142impl<V, W> Default for Sum<V, W>
143where
144    V: VectorSpace,
145    W: VectorSpace,
146{
147    fn default() -> Self {
148        Sum(V::default(), W::default())
149    }
150}
151
152impl<V, W> VectorSpace for Sum<V, W>
153where
154    V: VectorSpace,
155    W: VectorSpace,
156{
157    const ZERO: Self = Sum(V::ZERO, W::ZERO);
158}
159
160/// A type that supports the operations of a normed vector space; i.e. a norm operation in addition
161/// to those of [`VectorSpace`]. Specifically, the implementor must guarantee that the following
162/// relationships hold, within the limitations of floating point arithmetic:
163/// - (Nonnegativity) For all `v: Self`, `v.norm() >= 0.0`.
164/// - (Positive definiteness) For all `v: Self`, `v.norm() == 0.0` implies `v == Self::ZERO`.
165/// - (Absolute homogeneity) For all `c: f32`, `v: Self`, `(v * c).norm() == v.norm() * c.abs()`.
166/// - (Triangle inequality) For all `v, w: Self`, `(v + w).norm() <= v.norm() + w.norm()`.
167///
168/// Note that, because implementing types use floating point arithmetic, they are not required to actually
169/// implement `PartialEq` or `Eq`.
170pub trait NormedVectorSpace: VectorSpace {
171    /// The size of this element. The return value should always be nonnegative.
172    fn norm(self) -> f32;
173
174    /// The squared norm of this element. Computing this is often faster than computing
175    /// [`NormedVectorSpace::norm`].
176    #[inline]
177    fn norm_squared(self) -> f32 {
178        self.norm() * self.norm()
179    }
180
181    /// The distance between this element and another, as determined by the norm.
182    #[inline]
183    fn distance(self, rhs: Self) -> f32 {
184        (rhs - self).norm()
185    }
186
187    /// The squared distance between this element and another, as determined by the norm. Note that
188    /// this is often faster to compute in practice than [`NormedVectorSpace::distance`].
189    #[inline]
190    fn distance_squared(self, rhs: Self) -> f32 {
191        (rhs - self).norm_squared()
192    }
193}
194
195impl NormedVectorSpace for Vec4 {
196    #[inline]
197    fn norm(self) -> f32 {
198        self.length()
199    }
200
201    #[inline]
202    fn norm_squared(self) -> f32 {
203        self.length_squared()
204    }
205}
206
207impl NormedVectorSpace for Vec3 {
208    #[inline]
209    fn norm(self) -> f32 {
210        self.length()
211    }
212
213    #[inline]
214    fn norm_squared(self) -> f32 {
215        self.length_squared()
216    }
217}
218
219impl NormedVectorSpace for Vec3A {
220    #[inline]
221    fn norm(self) -> f32 {
222        self.length()
223    }
224
225    #[inline]
226    fn norm_squared(self) -> f32 {
227        self.length_squared()
228    }
229}
230
231impl NormedVectorSpace for Vec2 {
232    #[inline]
233    fn norm(self) -> f32 {
234        self.length()
235    }
236
237    #[inline]
238    fn norm_squared(self) -> f32 {
239        self.length_squared()
240    }
241}
242
243impl NormedVectorSpace for f32 {
244    #[inline]
245    fn norm(self) -> f32 {
246        ops::abs(self)
247    }
248
249    #[inline]
250    fn norm_squared(self) -> f32 {
251        self * self
252    }
253}
254
255/// A type with a natural interpolation that provides strong subdivision guarantees.
256///
257/// Although the only required method is `interpolate_stable`, many things are expected of it:
258///
259/// 1. The notion of interpolation should follow naturally from the semantics of the type, so
260///    that inferring the interpolation mode from the type alone is sensible.
261///
262/// 2. The interpolation recovers something equivalent to the starting value at `t = 0.0`
263///    and likewise with the ending value at `t = 1.0`. They do not have to be data-identical, but
264///    they should be semantically identical. For example, [`Quat::slerp`] doesn't always yield its
265///    second rotation input exactly at `t = 1.0`, but it always returns an equivalent rotation.
266///
267/// 3. Importantly, the interpolation must be *subdivision-stable*: for any interpolation curve
268///    between two (unnamed) values and any parameter-value pairs `(t0, p)` and `(t1, q)`, the
269///    interpolation curve between `p` and `q` must be the *linear* reparameterization of the original
270///    interpolation curve restricted to the interval `[t0, t1]`.
271///
272/// The last of these conditions is very strong and indicates something like constant speed. It
273/// is called "subdivision stability" because it guarantees that breaking up the interpolation
274/// into segments and joining them back together has no effect.
275///
276/// Here is a diagram depicting it:
277/// ```text
278/// top curve = u.interpolate_stable(v, t)
279///
280///              t0 => p   t1 => q    
281///   |-------------|---------|-------------|
282/// 0 => u         /           \          1 => v
283///              /               \
284///            /                   \
285///          /        linear         \
286///        /     reparameterization    \
287///      /   t = t0 * (1 - s) + t1 * s   \
288///    /                                   \
289///   |-------------------------------------|
290/// 0 => p                                1 => q
291///
292/// bottom curve = p.interpolate_stable(q, s)
293/// ```
294///
295/// Note that some common forms of interpolation do not satisfy this criterion. For example,
296/// [`Quat::lerp`] and [`Rot2::nlerp`] are not subdivision-stable.
297///
298/// Furthermore, this is not to be used as a general trait for abstract interpolation.
299/// Consumers rely on the strong guarantees in order for behavior based on this trait to be
300/// well-behaved.
301///
302/// [`Quat::slerp`]: crate::Quat::slerp
303/// [`Quat::lerp`]: crate::Quat::lerp
304/// [`Rot2::nlerp`]: crate::Rot2::nlerp
305pub trait StableInterpolate: Clone {
306    /// Interpolate between this value and the `other` given value using the parameter `t`. At
307    /// `t = 0.0`, a value equivalent to `self` is recovered, while `t = 1.0` recovers a value
308    /// equivalent to `other`, with intermediate values interpolating between the two.
309    /// See the [trait-level documentation] for details.
310    ///
311    /// [trait-level documentation]: StableInterpolate
312    fn interpolate_stable(&self, other: &Self, t: f32) -> Self;
313
314    /// A version of [`interpolate_stable`] that assigns the result to `self` for convenience.
315    ///
316    /// [`interpolate_stable`]: StableInterpolate::interpolate_stable
317    fn interpolate_stable_assign(&mut self, other: &Self, t: f32) {
318        *self = self.interpolate_stable(other, t);
319    }
320
321    /// Smoothly nudge this value towards the `target` at a given decay rate. The `decay_rate`
322    /// parameter controls how fast the distance between `self` and `target` decays relative to
323    /// the units of `delta`; the intended usage is for `decay_rate` to generally remain fixed,
324    /// while `delta` is something like `delta_time` from an updating system. This produces a
325    /// smooth following of the target that is independent of framerate.
326    ///
327    /// More specifically, when this is called repeatedly, the result is that the distance between
328    /// `self` and a fixed `target` attenuates exponentially, with the rate of this exponential
329    /// decay given by `decay_rate`.
330    ///
331    /// For example, at `decay_rate = 0.0`, this has no effect.
332    /// At `decay_rate = f32::INFINITY`, `self` immediately snaps to `target`.
333    /// In general, higher rates mean that `self` moves more quickly towards `target`.
334    ///
335    /// # Example
336    /// ```
337    /// # use bevy_math::{Vec3, StableInterpolate};
338    /// # let delta_time: f32 = 1.0 / 60.0;
339    /// let mut object_position: Vec3 = Vec3::ZERO;
340    /// let target_position: Vec3 = Vec3::new(2.0, 3.0, 5.0);
341    /// // Decay rate of ln(10) => after 1 second, remaining distance is 1/10th
342    /// let decay_rate = f32::ln(10.0);
343    /// // Calling this repeatedly will move `object_position` towards `target_position`:
344    /// object_position.smooth_nudge(&target_position, decay_rate, delta_time);
345    /// ```
346    fn smooth_nudge(&mut self, target: &Self, decay_rate: f32, delta: f32) {
347        self.interpolate_stable_assign(target, 1.0 - ops::exp(-decay_rate * delta));
348    }
349}
350
351// Conservatively, we presently only apply this for normed vector spaces, where the notion
352// of being constant-speed is literally true. The technical axioms are satisfied for any
353// VectorSpace type, but the "natural from the semantics" part is less clear in general.
354impl<V> StableInterpolate for V
355where
356    V: NormedVectorSpace,
357{
358    #[inline]
359    fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
360        self.lerp(*other, t)
361    }
362}
363
364impl StableInterpolate for Rot2 {
365    #[inline]
366    fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
367        self.slerp(*other, t)
368    }
369}
370
371impl StableInterpolate for Quat {
372    #[inline]
373    fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
374        self.slerp(*other, t)
375    }
376}
377
378impl StableInterpolate for Dir2 {
379    #[inline]
380    fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
381        self.slerp(*other, t)
382    }
383}
384
385impl StableInterpolate for Dir3 {
386    #[inline]
387    fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
388        self.slerp(*other, t)
389    }
390}
391
392impl StableInterpolate for Dir3A {
393    #[inline]
394    fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
395        self.slerp(*other, t)
396    }
397}
398
399macro_rules! impl_stable_interpolate_tuple {
400    ($(#[$meta:meta])* $(($n:tt, $T:ident)),*) => {
401        $(#[$meta])*
402        impl<$($T: StableInterpolate),*> StableInterpolate for ($($T,)*) {
403            fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
404                (
405                    $(
406                        <$T as StableInterpolate>::interpolate_stable(&self.$n, &other.$n, t),
407                    )*
408                )
409            }
410        }
411    };
412}
413
414all_tuples_enumerated!(
415    #[doc(fake_variadic)]
416    impl_stable_interpolate_tuple,
417    1,
418    11,
419    T
420);
421
422/// A type that has tangents.
423pub trait HasTangent {
424    /// The tangent type.
425    type Tangent: VectorSpace;
426}
427
428/// A value with its derivative.
429#[derive(Debug, Clone, Copy)]
430#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
431#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
432pub struct WithDerivative<T>
433where
434    T: HasTangent,
435{
436    /// The underlying value.
437    pub value: T,
438
439    /// The derivative at `value`.
440    pub derivative: T::Tangent,
441}
442
443/// A value together with its first and second derivatives.
444#[derive(Debug, Clone, Copy)]
445#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
446#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
447pub struct WithTwoDerivatives<T>
448where
449    T: HasTangent,
450{
451    /// The underlying value.
452    pub value: T,
453
454    /// The derivative at `value`.
455    pub derivative: T::Tangent,
456
457    /// The second derivative at `value`.
458    pub second_derivative: <T::Tangent as HasTangent>::Tangent,
459}
460
461impl<V: VectorSpace> HasTangent for V {
462    type Tangent = V;
463}
464
465impl<M, N> HasTangent for (M, N)
466where
467    M: HasTangent,
468    N: HasTangent,
469{
470    type Tangent = Sum<M::Tangent, N::Tangent>;
471}