bevy_math/
common_traits.rs

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