Skip to main content

avian3d/physics_transform/
transform.rs

1//! Components for physics positions and rotations.
2
3#![allow(clippy::unnecessary_cast)]
4
5use crate::{math::Real, physics_transform::PhysicsTransformConfig, prelude::*};
6use bevy::{
7    ecs::{lifecycle::HookContext, world::DeferredWorld},
8    prelude::*,
9};
10use bevy_curve::{Curve, Ease, FunctionCurve, Interval};
11use derive_more::From;
12
13/// The global position of a [rigid body](RigidBody) or a [collider](Collider).
14///
15/// # Relation to `Transform` and `GlobalTransform`
16///
17/// [`Position`] is used for physics internally and kept in sync with [`Transform`]
18/// by the [`PhysicsTransformPlugin`]. It rarely needs to be used directly in your own code, as [`Transform`] can still
19/// be used for almost everything. Using [`Position`] should only be required for managing positions
20/// in systems running in the [`SubstepSchedule`]. However, if you prefer, you can also use [`Position`]
21/// for everything.
22///
23/// The reasons why the engine uses a separate [`Position`] component can be found
24/// [here](crate#why-are-there-separate-position-and-rotation-components).
25///
26/// # Example
27///
28/// ```
29#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
30#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
31/// use bevy::prelude::*;
32///
33/// fn setup(mut commands: Commands) {
34///     commands.spawn((
35///         RigidBody::Dynamic,
36#[cfg_attr(feature = "2d", doc = "         Position::from_xy(0.0, 20.0),")]
37#[cfg_attr(feature = "3d", doc = "         Position::from_xyz(0.0, 2.0, 0.0),")]
38///     ));
39/// }
40/// ```
41#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
42#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
43#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
44#[reflect(Debug, Component, Default, PartialEq)]
45pub struct Position(pub RVector);
46
47impl Position {
48    /// A placeholder position. This is an invalid position and should *not*
49    /// be used to an actually position entities in the world, but can be used
50    /// to indicate that a position has not yet been initialized.
51    pub const PLACEHOLDER: Self = Self(RVector::MAX);
52
53    /// Creates a [`Position`] component with the given global `position`.
54    pub fn new(position: RVector) -> Self {
55        Self(position)
56    }
57
58    /// Creates a [`Position`] component with the global position `(x, y)`.
59    #[cfg(feature = "2d")]
60    pub fn from_xy(x: Real, y: Real) -> Self {
61        Self(RVector::new(x, y))
62    }
63
64    /// Creates a [`Position`] component with the global position `(x, y, z)`.
65    #[cfg(feature = "3d")]
66    pub fn from_xyz(x: Real, y: Real, z: Real) -> Self {
67        Self(RVector::new(x, y, z))
68    }
69}
70
71impl From<GlobalTransform> for Position {
72    #[cfg(feature = "2d")]
73    fn from(value: GlobalTransform) -> Self {
74        Self::from_xy(value.translation().x.real(), value.translation().y.real())
75    }
76
77    #[cfg(feature = "3d")]
78    fn from(value: GlobalTransform) -> Self {
79        Self::from_xyz(
80            value.translation().x.real(),
81            value.translation().y.real(),
82            value.translation().z.real(),
83        )
84    }
85}
86
87impl From<&GlobalTransform> for Position {
88    #[cfg(feature = "2d")]
89    fn from(value: &GlobalTransform) -> Self {
90        Self::from_xy(value.translation().x.real(), value.translation().y.real())
91    }
92
93    #[cfg(feature = "3d")]
94    fn from(value: &GlobalTransform) -> Self {
95        Self::from_xyz(
96            value.translation().x.real(),
97            value.translation().y.real(),
98            value.translation().z.real(),
99        )
100    }
101}
102
103impl Ease for Position {
104    fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
105        FunctionCurve::new(Interval::UNIT, move |t| {
106            Position(RVector::lerp(start.0, end.0, t as Real))
107        })
108    }
109}
110
111/// The translation accumulated before the XPBD position solve.
112#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
113#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
114#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
115#[reflect(Debug, Component, Default, PartialEq)]
116pub struct PreSolveDeltaPosition(pub Vector);
117
118/// The rotation accumulated before the XPBD position solve.
119#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
120#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
121#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
122#[reflect(Debug, Component, Default, PartialEq)]
123pub struct PreSolveDeltaRotation(pub Rot);
124
125/// The global counterclockwise physics rotation of a [rigid body](RigidBody)
126/// or a [collider](Collider) in radians.
127///
128/// The rotation angle is wrapped to be within the `(-pi, pi]` range.
129///
130/// # Relation to `Transform` and `GlobalTransform`
131///
132/// [`Rotation`] is used for physics internally and kept in sync with `[Transform`]
133/// by the [`PhysicsTransformPlugin`]. It rarely needs to be used directly in your own code, as `[Transform`] can still
134/// be used for almost everything. Using [`Rotation`] should only be required for managing rotations
135/// in systems running in the [`SubstepSchedule`], but if you prefer, you can also use [`Rotation`]
136/// for everything.
137///
138/// The reasons why the engine uses a separate [`Rotation`] component can be found
139/// [here](crate#why-are-there-separate-position-and-rotation-components).
140///
141/// # Example
142///
143/// ```
144/// use avian2d::prelude::*;
145/// use bevy::prelude::*;
146///
147/// fn setup(mut commands: Commands) {
148///     // Spawn a dynamic rigid body rotated by 90 degrees
149///     commands.spawn((RigidBody::Dynamic, Rotation::degrees(90.0)));
150/// }
151/// ```
152#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq)]
153#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
154#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
155#[reflect(Debug, Component, PartialEq)]
156#[cfg(feature = "2d")]
157pub struct Rotation {
158    /// The cosine of the rotation angle in radians.
159    ///
160    /// This is the real part of the unit complex number representing the rotation.
161    pub cos: f32,
162    /// The sine of the rotation angle in radians.
163    ///
164    /// This is the imaginary part of the unit complex number representing the rotation.
165    pub sin: f32,
166}
167
168#[cfg(feature = "2d")]
169impl Default for Rotation {
170    fn default() -> Self {
171        Self::IDENTITY
172    }
173}
174
175#[cfg(feature = "2d")]
176impl Rotation {
177    /// A placeholder rotation. This is an invalid rotation and should *not*
178    /// be used to an actually rotate entities in the world, but can be used
179    /// to indicate that a rotation has not yet been initialized.
180    pub const PLACEHOLDER: Self = Self {
181        cos: f32::MAX,
182        sin: f32::MAX,
183    };
184
185    /// No rotation.
186    pub const IDENTITY: Self = Self { cos: 1.0, sin: 0.0 };
187
188    /// A rotation of π radians.
189    pub const PI: Self = Self {
190        cos: -1.0,
191        sin: 0.0,
192    };
193
194    /// A counterclockwise rotation of π/2 radians.
195    pub const FRAC_PI_2: Self = Self { cos: 0.0, sin: 1.0 };
196
197    /// A counterclockwise rotation of π/3 radians.
198    pub const FRAC_PI_3: Self = Self {
199        cos: 0.5,
200        sin: 0.866_025_4,
201    };
202
203    /// A counterclockwise rotation of π/4 radians.
204    pub const FRAC_PI_4: Self = Self {
205        cos: core::f32::consts::FRAC_1_SQRT_2,
206        sin: core::f32::consts::FRAC_1_SQRT_2,
207    };
208
209    /// A counterclockwise rotation of π/6 radians.
210    pub const FRAC_PI_6: Self = Self {
211        cos: 0.866_025_4,
212        sin: 0.5,
213    };
214
215    /// A counterclockwise rotation of π/8 radians.
216    pub const FRAC_PI_8: Self = Self {
217        cos: 0.923_879_5,
218        sin: 0.382_683_43,
219    };
220
221    /// Creates a [`Rotation`] from a counterclockwise angle in radians.
222    #[inline]
223    pub fn radians(radians: f32) -> Self {
224        #[cfg(feature = "enhanced-determinism")]
225        let (sin, cos) = (libm::sinf(radians), libm::cosf(radians));
226        #[cfg(not(feature = "enhanced-determinism"))]
227        let (sin, cos) = radians.sin_cos();
228
229        Self::from_sin_cos(sin, cos)
230    }
231
232    /// Creates a [`Rotation`] from a counterclockwise angle in degrees.
233    #[inline]
234    pub fn degrees(degrees: f32) -> Self {
235        Self::radians(degrees.to_radians())
236    }
237
238    /// Creates a [`Rotation`] from radians.
239    #[deprecated(note = "renamed to just `radians` to match Bevy")]
240    pub fn from_radians(radians: f32) -> Self {
241        Self::radians(radians)
242    }
243
244    /// Creates a [`Rotation`] from degrees.
245    #[deprecated(note = "renamed to just `degrees` to match Bevy")]
246    pub fn from_degrees(degrees: f32) -> Self {
247        Self::degrees(degrees)
248    }
249
250    /// Creates a [`Rotation`] from the sine and cosine of an angle in radians.
251    ///
252    /// The rotation is only valid if `sin * sin + cos * cos == 1.0`.
253    ///
254    /// # Panics
255    ///
256    /// Panics if `sin * sin + cos * cos != 1.0` when `debug_assertions` are enabled.
257    #[inline]
258    pub fn from_sin_cos(sin: f32, cos: f32) -> Self {
259        let rotation = Self { sin, cos };
260        debug_assert!(
261            rotation.is_normalized(),
262            "the given sine and cosine produce an invalid rotation: {rotation:?}"
263        );
264        rotation
265    }
266
267    /// Returns the rotation in radians in the `(-pi, pi]` range.
268    #[inline]
269    pub fn as_radians(self) -> f32 {
270        #[cfg(feature = "enhanced-determinism")]
271        {
272            libm::atan2f(self.sin, self.cos)
273        }
274        #[cfg(not(feature = "enhanced-determinism"))]
275        {
276            f32::atan2(self.sin, self.cos)
277        }
278    }
279
280    /// Returns the rotation in degrees in the `(-180, 180]` range.
281    #[inline]
282    pub fn as_degrees(self) -> f32 {
283        self.as_radians().to_degrees()
284    }
285
286    /// Returns the sine and cosine of the rotation angle in radians.
287    #[inline]
288    pub const fn sin_cos(self) -> (f32, f32) {
289        (self.sin, self.cos)
290    }
291
292    /// Computes the length or norm of the complex number used to represent the rotation.
293    ///
294    /// The length is typically expected to be `1.0`. Unexpectedly denormalized rotations
295    /// can be a result of incorrect construction or floating point error caused by
296    /// successive operations.
297    #[inline]
298    #[doc(alias = "norm")]
299    pub fn length(self) -> f32 {
300        Vec2::new(self.sin, self.cos).length()
301    }
302
303    /// Computes the squared length or norm of the complex number used to represent the rotation.
304    ///
305    /// This is generally faster than [`Rotation::length()`], as it avoids a square
306    /// root operation.
307    ///
308    /// The length is typically expected to be `1.0`. Unexpectedly denormalized rotations
309    /// can be a result of incorrect construction or floating point error caused by
310    /// successive operations.
311    #[inline]
312    #[doc(alias = "norm2")]
313    pub fn length_squared(self) -> f32 {
314        Vec2::new(self.sin, self.cos).length_squared()
315    }
316
317    /// Computes `1.0 / self.length()`.
318    ///
319    /// For valid results, `self` must _not_ have a length of zero.
320    #[inline]
321    pub fn length_recip(self) -> f32 {
322        Vec2::new(self.sin, self.cos).length_recip()
323    }
324
325    /// Computes the chord length of the rotation, which is the straight-line
326    /// distance between the start and end points of the rotation on a unit circle.
327    #[inline]
328    pub fn chord_length(self) -> f32 {
329        // The chord length traveled by a point rotated by `θ` on a unit circle
330        // is `2 * sin(θ / 2)`.
331        //
332        // In 2D, `2 * sin(θ / 2) = sqrt(2 * (1 - cos(θ)))`, using the stored cosine.
333        //
334        // TODO: A "2D quaternion" that stores cos(theta / 2) and sin(theta / 2)
335        //       could avoid the sqrt and be more accurate in some places.
336        (2.0 * (1.0 - self.cos)).max(0.0).sqrt()
337    }
338
339    /// Returns `self` with a length of `1.0` if possible, and `None` otherwise.
340    ///
341    /// `None` will be returned if the sine and cosine of `self` are both zero (or very close to zero),
342    /// or if either of them is NaN or infinite.
343    ///
344    /// Note that [`Rotation`] should typically already be normalized by design.
345    /// Manual normalization is only needed when successive operations result in
346    /// accumulated floating point error, or if the rotation was constructed
347    /// with invalid values.
348    #[inline]
349    #[must_use]
350    pub fn try_normalize(self) -> Option<Self> {
351        let recip = self.length_recip();
352        if recip.is_finite() && recip > 0.0 {
353            Some(Self::from_sin_cos(self.sin * recip, self.cos * recip))
354        } else {
355            None
356        }
357    }
358
359    /// Returns `self` with a length of `1.0`.
360    ///
361    /// Note that [`Rotation`] should typically already be normalized by design.
362    /// Manual normalization is only needed when successive operations result in
363    /// accumulated floating point error, or if the rotation was constructed
364    /// with invalid values.
365    ///
366    /// # Panics
367    ///
368    /// Panics if `self` has a length of zero, NaN, or infinity when debug assertions are enabled.
369    #[inline]
370    #[must_use]
371    pub fn normalize(self) -> Self {
372        let length_recip = self.length_recip();
373        Self::from_sin_cos(self.sin * length_recip, self.cos * length_recip)
374    }
375
376    /// Returns `self` after an approximate normalization,
377    /// assuming the value is already nearly normalized.
378    /// Useful for preventing numerical error accumulation.
379    #[inline]
380    #[must_use]
381    pub fn fast_renormalize(self) -> Self {
382        // First-order Tayor approximation
383        // 1/L = (L^2)^(-1/2) ≈ 1 - (L^2 - 1) / 2 = (3 - L^2) / 2
384        let length_squared = self.length_squared();
385        let approx_inv_length = 0.5 * (3.0 - length_squared);
386        Self::from_sin_cos(self.sin * approx_inv_length, self.cos * approx_inv_length)
387    }
388
389    /// Returns `true` if the rotation is neither infinite nor NaN.
390    #[inline]
391    pub fn is_finite(self) -> bool {
392        self.sin.is_finite() && self.cos.is_finite()
393    }
394
395    /// Returns `true` if the rotation is NaN.
396    #[inline]
397    pub fn is_nan(self) -> bool {
398        self.sin.is_nan() || self.cos.is_nan()
399    }
400
401    /// Returns whether `self` has a length of `1.0` or not.
402    ///
403    /// Uses a precision threshold of approximately `1e-4`.
404    #[inline]
405    pub fn is_normalized(self) -> bool {
406        // The allowed length is 1 +/- 1e-4, so the largest allowed
407        // squared length is (1 + 1e-4)^2 = 1.00020001, which makes
408        // the threshold for the squared length approximately 2e-4.
409        (self.length_squared() - 1.0).abs() <= 2e-4
410    }
411
412    /// Returns `true` if the rotation is near [`Rotation::IDENTITY`].
413    #[inline]
414    pub fn is_near_identity(self) -> bool {
415        // Same as `Quat::is_near_identity`, but using sine and cosine
416        let threshold_angle_sin = 0.000_049_692_047; // let threshold_angle = 0.002_847_144_6;
417        self.cos > 0.0 && self.sin.abs() < threshold_angle_sin
418    }
419
420    /// Returns the angle in radians needed to make `self` and `other` coincide.
421    #[inline]
422    pub fn angle_between(self, other: Self) -> f32 {
423        (other * self.inverse()).as_radians()
424    }
425
426    /// Returns the inverse of the rotation. This is also the conjugate
427    /// of the unit complex number representing the rotation.
428    #[inline]
429    #[must_use]
430    #[doc(alias = "conjugate")]
431    pub fn inverse(self) -> Self {
432        Self {
433            cos: self.cos,
434            sin: -self.sin,
435        }
436    }
437
438    #[inline]
439    #[must_use]
440    /// Adds the given counterclockiwise angle in radians to the [`Rotation`].
441    /// Uses small-angle approximation
442    pub fn add_angle_fast(&self, radians: f32) -> Self {
443        let (sin, cos) = (self.sin + radians * self.cos, self.cos - radians * self.sin);
444        let magnitude_squared = sin * sin + cos * cos;
445        let magnitude_recip = if magnitude_squared > 0.0 {
446            magnitude_squared.sqrt().recip()
447        } else {
448            0.0
449        };
450        Rotation::from_sin_cos(sin * magnitude_recip, cos * magnitude_recip)
451    }
452
453    /// Performs a linear interpolation between `self` and `rhs` based on
454    /// the value `s`, and normalizes the rotation afterwards.
455    ///
456    /// When `s == 0.0`, the result will be equal to `self`.
457    /// When `s == 1.0`, the result will be equal to `rhs`.
458    ///
459    /// This is slightly more efficient than [`slerp`](Self::slerp), and produces a similar result
460    /// when the difference between the two rotations is small. At larger differences,
461    /// the result resembles a kind of ease-in-out effect.
462    ///
463    /// If you would like the angular velocity to remain constant, consider using [`slerp`](Self::slerp) instead.
464    ///
465    /// # Details
466    ///
467    /// `nlerp` corresponds to computing an angle for a point at position `s` on a line drawn
468    /// between the endpoints of the arc formed by `self` and `rhs` on a unit circle,
469    /// and normalizing the result afterwards.
470    ///
471    /// Note that if the angles are opposite like 0 and π, the line will pass through the origin,
472    /// and the resulting angle will always be either `self` or `rhs` depending on `s`.
473    /// If `s` happens to be `0.5` in this case, a valid rotation cannot be computed, and `self`
474    /// will be returned as a fallback.
475    ///
476    /// # Example
477    ///
478    /// ```
479    /// # use approx::assert_relative_eq;
480    /// # use avian2d::prelude::Rotation;
481    /// #
482    /// let rot1 = Rotation::IDENTITY;
483    /// let rot2 = Rotation::degrees(135.0);
484    ///
485    /// let result1 = rot1.nlerp(rot2, 1.0 / 3.0);
486    /// assert_relative_eq!(result1.as_degrees(), 28.675055, epsilon = 0.0001);
487    ///
488    /// let result2 = rot1.nlerp(rot2, 0.5);
489    /// assert_relative_eq!(result2.as_degrees(), 67.5);
490    /// ```
491    #[inline]
492    pub fn nlerp(self, end: Self, s: f32) -> Self {
493        Self {
494            sin: self.sin.lerp(end.sin, s),
495            cos: self.cos.lerp(end.cos, s),
496        }
497        .try_normalize()
498        // Fall back to the start rotation.
499        // This can happen when `self` and `end` are opposite angles and `s == 0.5`,
500        // because the resulting rotation would be zero, which cannot be normalized.
501        .unwrap_or(self)
502    }
503
504    /// Performs a spherical linear interpolation between `self` and `end`
505    /// based on the value `s`.
506    ///
507    /// This corresponds to interpolating between the two angles at a constant angular velocity.
508    ///
509    /// When `s == 0.0`, the result will be equal to `self`.
510    /// When `s == 1.0`, the result will be equal to `rhs`.
511    ///
512    /// If you would like the rotation to have a kind of ease-in-out effect, consider
513    /// using the slightly more efficient [`nlerp`](Self::nlerp) instead.
514    ///
515    /// # Example
516    ///
517    /// ```
518    /// # use avian2d::prelude::Rotation;
519    /// #
520    /// let rot1 = Rotation::IDENTITY;
521    /// let rot2 = Rotation::degrees(135.0);
522    ///
523    /// let result1 = rot1.slerp(rot2, 1.0 / 3.0);
524    /// assert_eq!(result1.as_degrees(), 45.0);
525    ///
526    /// let result2 = rot1.slerp(rot2, 0.5);
527    /// assert_eq!(result2.as_degrees(), 67.5);
528    /// ```
529    #[inline]
530    pub fn slerp(self, end: Self, s: f32) -> Self {
531        self * Self::radians(self.angle_between(end) * s)
532    }
533}
534
535#[cfg(feature = "2d")]
536impl From<f32> for Rotation {
537    /// Creates a [`Rotation`] from a counterclockwise angle in radians.
538    fn from(rotation: f32) -> Self {
539        Self::radians(rotation)
540    }
541}
542
543#[cfg(feature = "2d")]
544impl From<Rotation> for Mat2 {
545    /// Creates a [`Mat2`] rotation matrix from a [`Rotation`].
546    fn from(rot: Rotation) -> Self {
547        Mat2::from_cols_array(&[rot.cos, rot.sin, -rot.sin, rot.cos])
548    }
549}
550
551#[cfg(feature = "2d")]
552impl From<Mat2> for Rotation {
553    /// Creates a [`Rotation`] from a [`Mat2`].
554    fn from(mat: Mat2) -> Self {
555        let cos = mat.x_axis.x;
556        let sin = mat.x_axis.y;
557        Self::from_sin_cos(sin, cos)
558    }
559}
560
561#[cfg(feature = "2d")]
562impl From<Rot2> for Rotation {
563    /// Creates a [`Rotation`] from a [`Rot2`].
564    fn from(rot: Rot2) -> Self {
565        Self::from_sin_cos(rot.sin, rot.cos)
566    }
567}
568
569#[cfg(feature = "2d")]
570impl From<Rotation> for Rot2 {
571    /// Creates a [`Rot2`] from a [`Rotation`].
572    fn from(rot: Rotation) -> Self {
573        Self::from_sin_cos(rot.sin, rot.cos)
574    }
575}
576
577#[cfg(feature = "2d")]
578impl core::ops::Mul for Rotation {
579    type Output = Self;
580
581    fn mul(self, rhs: Self) -> Self::Output {
582        Self {
583            cos: self.cos * rhs.cos - self.sin * rhs.sin,
584            sin: self.sin * rhs.cos + self.cos * rhs.sin,
585        }
586    }
587}
588
589#[cfg(feature = "2d")]
590impl core::ops::MulAssign for Rotation {
591    fn mul_assign(&mut self, rhs: Self) {
592        *self = *self * rhs;
593    }
594}
595
596#[cfg(feature = "2d")]
597impl core::ops::Mul<Vec2> for Rotation {
598    type Output = Vec2;
599
600    /// Rotates a [`Vec2`] by a [`Rotation`].
601    fn mul(self, rhs: Vec2) -> Self::Output {
602        Vec2::new(
603            rhs.x * self.cos - rhs.y * self.sin,
604            rhs.x * self.sin + rhs.y * self.cos,
605        )
606    }
607}
608
609#[cfg(feature = "2d")]
610impl core::ops::Mul<Vec3> for Rotation {
611    type Output = Vec3;
612
613    fn mul(self, rhs: Vec3) -> Self::Output {
614        Vec3::new(
615            rhs.x * self.cos - rhs.y * self.sin,
616            rhs.x * self.sin + rhs.y * self.cos,
617            rhs.z,
618        )
619    }
620}
621
622#[cfg(feature = "2d")]
623impl core::ops::Mul<&Vec3> for Rotation {
624    type Output = Vec3;
625
626    fn mul(self, rhs: &Vec3) -> Self::Output {
627        self * *rhs
628    }
629}
630
631#[cfg(feature = "2d")]
632impl core::ops::Mul<&mut Vec3> for Rotation {
633    type Output = Vec3;
634
635    fn mul(self, rhs: &mut Vec3) -> Self::Output {
636        self * *rhs
637    }
638}
639
640#[cfg(feature = "2d")]
641impl core::ops::Mul<Vec3> for &Rotation {
642    type Output = Vec3;
643
644    fn mul(self, rhs: Vec3) -> Self::Output {
645        *self * rhs
646    }
647}
648
649#[cfg(feature = "2d")]
650impl core::ops::Mul<&Vec3> for &Rotation {
651    type Output = Vec3;
652
653    fn mul(self, rhs: &Vec3) -> Self::Output {
654        *self * *rhs
655    }
656}
657
658#[cfg(feature = "2d")]
659impl core::ops::Mul<&mut Vec3> for &Rotation {
660    type Output = Vec3;
661
662    fn mul(self, rhs: &mut Vec3) -> Self::Output {
663        *self * *rhs
664    }
665}
666
667#[cfg(feature = "2d")]
668impl core::ops::Mul<Vec3> for &mut Rotation {
669    type Output = Vec3;
670
671    fn mul(self, rhs: Vec3) -> Self::Output {
672        *self * rhs
673    }
674}
675
676#[cfg(feature = "2d")]
677impl core::ops::Mul<&Vec3> for &mut Rotation {
678    type Output = Vec3;
679
680    fn mul(self, rhs: &Vec3) -> Self::Output {
681        *self * *rhs
682    }
683}
684
685#[cfg(feature = "2d")]
686impl core::ops::Mul<&mut Vec3> for &mut Rotation {
687    type Output = Vec3;
688
689    fn mul(self, rhs: &mut Vec3) -> Self::Output {
690        *self * *rhs
691    }
692}
693
694impl Ease for Rotation {
695    fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
696        FunctionCurve::new(Interval::UNIT, move |t| Rotation::slerp(start, end, t))
697    }
698}
699
700/// The global physics rotation of a [rigid body](RigidBody) or a [collider](Collider).
701///
702/// # Relation to `Transform` and `GlobalTransform`
703///
704/// [`Rotation`] is used for physics internally and kept in sync with [`Transform`]
705/// by the [`PhysicsTransformPlugin`]. It rarely needs to be used directly in your own code, as [`Transform`] can still
706/// be used for almost everything. Using [`Rotation`] should only be required for managing rotations
707/// in systems running in the [`SubstepSchedule`], but if you prefer, you can also use [`Rotation`]
708/// for everything.
709///
710/// The reasons why the engine uses a separate [`Rotation`] component can be found
711/// [here](crate#why-are-there-separate-position-and-rotation-components).
712///
713/// # Example
714///
715/// ```
716/// use avian3d::prelude::*;
717/// use bevy::prelude::*;
718///
719/// fn setup(mut commands: Commands) {
720///     // Spawn a dynamic rigid body rotated by 1.5 radians around the x axis
721///     commands.spawn((RigidBody::Dynamic, Rotation(Quat::from_rotation_x(1.5))));
722/// }
723/// ```
724#[cfg(feature = "3d")]
725#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq)]
726#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
727#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
728#[reflect(Debug, Component, Default, PartialEq)]
729pub struct Rotation(pub Quat);
730
731#[cfg(feature = "3d")]
732impl Rotation {
733    /// A placeholder rotation. This is an invalid rotation and should *not*
734    /// be used to an actually rotate entities in the world, but can be used
735    /// to indicate that a rotation has not yet been initialized.
736    pub const PLACEHOLDER: Self = Self(Quat::from_xyzw(f32::MAX, f32::MAX, f32::MAX, f32::MAX));
737
738    /// No rotation.
739    pub const IDENTITY: Self = Self(Quat::IDENTITY);
740
741    /// Computes the chord length of the rotation, which is the straight-line
742    /// distance between the start and end points of the rotation on a unit sphere.
743    #[inline]
744    pub fn chord_length(self) -> f32 {
745        // The chord length traveled by a point rotated by `θ` on a unit sphere
746        // is `2 * sin(θ / 2)`.
747        //
748        // In 3D, the vector part of the quaternion has length `sin(θ / 2)`,
749        // so doubling it gives the chord length `2 * sin(θ / 2)` directly.
750        2.0 * self.xyz().length()
751    }
752
753    /// Returns the angle (in radians) for the minimal rotation for transforming this rotation into another.
754    #[inline]
755    pub fn angle_between(self, other: Self) -> f32 {
756        self.0.angle_between(other.0)
757    }
758
759    /// Inverts the rotation.
760    #[inline]
761    #[must_use]
762    pub fn inverse(&self) -> Self {
763        Self(self.0.inverse())
764    }
765
766    /// Performs a linear interpolation between `self` and `end` based on
767    /// the value `s`, and normalizes the rotation afterwards.
768    ///
769    /// When `s == 0.0`, the result will be equal to `self`.
770    /// When `s == 1.0`, the result will be equal to `end`.
771    ///
772    /// This is slightly more efficient than [`slerp`](Self::slerp), and produces a similar result
773    /// when the difference between the two rotations is small. At larger differences,
774    /// the result resembles a kind of ease-in-out effect.
775    ///
776    /// If you would like the angular velocity to remain constant, consider using [`slerp`](Self::slerp) instead.
777    #[inline]
778    pub fn nlerp(self, end: Self, t: f32) -> Self {
779        Self(self.0.lerp(end.0, t))
780    }
781
782    /// Performs a spherical linear interpolation between `self` and `end`
783    /// based on the value `s`.
784    ///
785    /// This corresponds to interpolating between the two angles at a constant angular velocity.
786    ///
787    /// When `s == 0.0`, the result will be equal to `self`.
788    /// When `s == 1.0`, the result will be equal to `end`.
789    ///
790    /// If you would like the rotation to have a kind of ease-in-out effect, consider
791    /// using the slightly more efficient [`nlerp`](Self::nlerp) instead.
792    #[inline]
793    pub fn slerp(self, end: Self, t: f32) -> Self {
794        Self(self.0.slerp(end.0, t))
795    }
796
797    /// Returns `self` after an approximate normalization,
798    /// assuming the value is already nearly normalized.
799    /// Useful for preventing numerical error accumulation.
800    #[inline]
801    #[must_use]
802    pub fn fast_renormalize(self) -> Self {
803        // First-order Tayor approximation
804        // 1/L = (L^2)^(-1/2) ≈ 1 - (L^2 - 1) / 2 = (3 - L^2) / 2
805        let length_squared = self.length_squared();
806        let approx_inv_length = 0.5 * (3.0 - length_squared);
807        Self(self.0 * approx_inv_length)
808    }
809}
810
811#[cfg(feature = "3d")]
812impl core::ops::Mul<Vec3> for Rotation {
813    type Output = Vec3;
814
815    fn mul(self, vector: Vec3) -> Self::Output {
816        self.0 * vector
817    }
818}
819
820#[cfg(feature = "3d")]
821impl core::ops::Mul for Rotation {
822    type Output = Rotation;
823
824    fn mul(self, rhs: Self) -> Self::Output {
825        Self(self.0 * rhs.0)
826    }
827}
828
829#[cfg(feature = "3d")]
830impl core::ops::MulAssign for Rotation {
831    fn mul_assign(&mut self, rhs: Self) {
832        self.0 *= rhs.0;
833    }
834}
835
836#[cfg(feature = "3d")]
837impl core::ops::Mul<Quat> for Rotation {
838    type Output = Quat;
839
840    fn mul(self, quaternion: Quat) -> Self::Output {
841        self.0 * quaternion
842    }
843}
844
845#[cfg(feature = "3d")]
846impl core::ops::Mul<Quat> for &Rotation {
847    type Output = Quat;
848
849    fn mul(self, quaternion: Quat) -> Self::Output {
850        self.0 * quaternion
851    }
852}
853
854#[cfg(feature = "3d")]
855impl core::ops::Mul<Quat> for &mut Rotation {
856    type Output = Quat;
857
858    fn mul(self, quaternion: Quat) -> Self::Output {
859        self.0 * quaternion
860    }
861}
862
863#[cfg(feature = "3d")]
864impl core::ops::Mul<Rotation> for Quat {
865    type Output = Rotation;
866
867    fn mul(self, rotation: Rotation) -> Self::Output {
868        Rotation(self * rotation.0)
869    }
870}
871
872#[cfg(feature = "3d")]
873impl core::ops::Mul<Rotation> for &Quat {
874    type Output = Rotation;
875
876    fn mul(self, rotation: Rotation) -> Self::Output {
877        Rotation(self * rotation.0)
878    }
879}
880
881#[cfg(feature = "3d")]
882impl core::ops::Mul<Rotation> for &mut Quat {
883    type Output = Rotation;
884
885    fn mul(self, rotation: Rotation) -> Self::Output {
886        Rotation(*self * rotation.0)
887    }
888}
889
890impl core::ops::Mul<Dir> for Rotation {
891    type Output = Dir;
892
893    fn mul(self, direction: Dir) -> Self::Output {
894        Dir::new_unchecked(self * *direction)
895    }
896}
897
898impl core::ops::Mul<Vector> for &Rotation {
899    type Output = Vector;
900
901    fn mul(self, vector: Vector) -> Self::Output {
902        *self * vector
903    }
904}
905
906impl core::ops::Mul<Dir> for &Rotation {
907    type Output = Dir;
908
909    fn mul(self, direction: Dir) -> Self::Output {
910        Dir::new_unchecked(self * *direction)
911    }
912}
913
914impl core::ops::Mul<Vector> for &mut Rotation {
915    type Output = Vector;
916
917    fn mul(self, vector: Vector) -> Self::Output {
918        *self * vector
919    }
920}
921
922impl core::ops::Mul<Dir> for &mut Rotation {
923    type Output = Dir;
924
925    fn mul(self, direction: Dir) -> Self::Output {
926        Dir::new_unchecked(self * *direction)
927    }
928}
929
930impl core::ops::Mul<&Vector> for Rotation {
931    type Output = Vector;
932
933    fn mul(self, vector: &Vector) -> Self::Output {
934        self * *vector
935    }
936}
937
938impl core::ops::Mul<&Dir> for Rotation {
939    type Output = Dir;
940
941    fn mul(self, direction: &Dir) -> Self::Output {
942        Dir::new_unchecked(self * **direction)
943    }
944}
945
946impl core::ops::Mul<&mut Vector> for Rotation {
947    type Output = Vector;
948
949    fn mul(self, vector: &mut Vector) -> Self::Output {
950        self * *vector
951    }
952}
953
954impl core::ops::Mul<&mut Dir> for Rotation {
955    type Output = Dir;
956
957    fn mul(self, direction: &mut Dir) -> Self::Output {
958        Dir::new_unchecked(self * **direction)
959    }
960}
961
962impl core::ops::Mul<&Vector> for &Rotation {
963    type Output = Vector;
964
965    fn mul(self, vector: &Vector) -> Self::Output {
966        *self * *vector
967    }
968}
969
970impl core::ops::Mul<&Dir> for &Rotation {
971    type Output = Dir;
972
973    fn mul(self, direction: &Dir) -> Self::Output {
974        Dir::new_unchecked(self * **direction)
975    }
976}
977
978impl core::ops::Mul<&Vector> for &mut Rotation {
979    type Output = Vector;
980
981    fn mul(self, vector: &Vector) -> Self::Output {
982        *self * *vector
983    }
984}
985
986impl core::ops::Mul<&Dir> for &mut Rotation {
987    type Output = Dir;
988
989    fn mul(self, direction: &Dir) -> Self::Output {
990        Dir::new_unchecked(self * **direction)
991    }
992}
993
994impl core::ops::Mul<&mut Vector> for &Rotation {
995    type Output = Vector;
996
997    fn mul(self, vector: &mut Vector) -> Self::Output {
998        *self * *vector
999    }
1000}
1001
1002impl core::ops::Mul<&mut Dir> for &Rotation {
1003    type Output = Dir;
1004
1005    fn mul(self, direction: &mut Dir) -> Self::Output {
1006        Dir::new_unchecked(self * **direction)
1007    }
1008}
1009
1010impl core::ops::Mul<&mut Vector> for &mut Rotation {
1011    type Output = Vector;
1012
1013    fn mul(self, vector: &mut Vector) -> Self::Output {
1014        *self * *vector
1015    }
1016}
1017
1018impl core::ops::Mul<&mut Dir> for &mut Rotation {
1019    type Output = Dir;
1020
1021    fn mul(self, direction: &mut Dir) -> Self::Output {
1022        Dir::new_unchecked(self * **direction)
1023    }
1024}
1025
1026#[cfg(feature = "2d")]
1027impl From<Rotation> for f32 {
1028    fn from(rot: Rotation) -> Self {
1029        rot.as_radians()
1030    }
1031}
1032
1033#[cfg(feature = "2d")]
1034impl From<Rotation> for Quat {
1035    fn from(rot: Rotation) -> Self {
1036        let z = rot.sin.signum() * ((1.0 - rot.cos) / 2.0).abs().sqrt();
1037        let w = ((1.0 + rot.cos) / 2.0).abs().sqrt();
1038        Quat::from_xyzw(0.0, 0.0, z, w)
1039    }
1040}
1041
1042#[cfg(feature = "3d")]
1043impl From<Rotation> for Quat {
1044    fn from(rot: Rotation) -> Self {
1045        rot.0
1046    }
1047}
1048
1049impl From<Transform> for Rotation {
1050    fn from(value: Transform) -> Self {
1051        Self::from(value.rotation)
1052    }
1053}
1054
1055impl From<GlobalTransform> for Rotation {
1056    fn from(value: GlobalTransform) -> Self {
1057        Self::from(value.compute_transform().rotation)
1058    }
1059}
1060
1061impl From<&GlobalTransform> for Rotation {
1062    fn from(value: &GlobalTransform) -> Self {
1063        Self::from(value.compute_transform().rotation)
1064    }
1065}
1066
1067#[cfg(feature = "2d")]
1068impl From<Quat> for Rotation {
1069    fn from(quat: Quat) -> Self {
1070        let angle = quat.to_euler(EulerRot::XYZ).2;
1071        Self::radians(angle)
1072    }
1073}
1074
1075#[cfg(feature = "3d")]
1076impl From<Quat> for Rotation {
1077    fn from(quat: Quat) -> Self {
1078        Self(Quat::from_xyzw(quat.x, quat.y, quat.z, quat.w))
1079    }
1080}
1081
1082pub(crate) fn init_physics_transform(world: &mut DeferredWorld, ctx: &HookContext) {
1083    let entity_ref = world.entity(ctx.entity);
1084
1085    // Get the global `Position` and `Rotation`.
1086    let (mut position, is_pos_placeholder) = entity_ref
1087        .get::<Position>()
1088        .map_or((default(), true), |p| (*p, *p == Position::PLACEHOLDER));
1089    let (mut rotation, is_rot_placeholder) = entity_ref
1090        .get::<Rotation>()
1091        .map_or((default(), true), |r| (*r, *r == Rotation::PLACEHOLDER));
1092
1093    if is_pos_placeholder {
1094        position.0 = RVector::ZERO;
1095    }
1096    if is_rot_placeholder {
1097        rotation = Rotation::IDENTITY;
1098    }
1099
1100    // If either `Position` or `Rotation` was set manually, we want to set `Transform` to match later.
1101    let is_not_placeholder = !is_pos_placeholder || !is_rot_placeholder;
1102
1103    let config = world
1104        .get_resource::<PhysicsTransformConfig>()
1105        .cloned()
1106        .unwrap_or_default();
1107
1108    let mut parent_global_transform = GlobalTransform::default();
1109
1110    // Compute the global transform by traversing up the hierarchy.
1111    let mut curr_parent = world.get::<ChildOf>(ctx.entity);
1112    while let Some(parent) = curr_parent {
1113        if let Some(parent_transform) = world.get::<Transform>(parent.0) {
1114            parent_global_transform = *parent_transform * parent_global_transform;
1115        }
1116        curr_parent = world.get::<ChildOf>(parent.0);
1117    }
1118
1119    let transform = world.get::<Transform>(ctx.entity).copied();
1120    let global_transform = transform.map(|transform| {
1121        let global_transform = parent_global_transform * GlobalTransform::from(transform);
1122        // Update the global transform.
1123        *world.get_mut::<GlobalTransform>(ctx.entity).unwrap() = global_transform;
1124        global_transform
1125    });
1126
1127    // If either `Position` or `Rotation` was not a placeholder,
1128    // we need to update the `Transform` to match the current values.
1129    if is_not_placeholder && config.position_to_transform {
1130        // Get the parent's global transform if it exists.
1131        if parent_global_transform != GlobalTransform::default() {
1132            #[cfg(feature = "2d")]
1133            let Some(transform) = transform else {
1134                return;
1135            };
1136
1137            // The new local transform of the child body, computed from the its global transform
1138            // and its parents global transform.
1139            #[cfg(feature = "2d")]
1140            let new_transform =
1141                {
1142                    let (parent_translation, parent_scale) = (
1143                        parent_global_transform.translation(),
1144                        parent_global_transform.scale(),
1145                    );
1146                    GlobalTransform::from(
1147                        Transform::from_translation(position.f32().extend(
1148                            parent_translation.z + transform.translation.z * parent_scale.z,
1149                        ))
1150                        .with_rotation(Quat::from(rotation)),
1151                    )
1152                    .reparented_to(&parent_global_transform)
1153                };
1154            #[cfg(feature = "3d")]
1155            let new_transform = GlobalTransform::from(
1156                Transform::from_translation(position.f32()).with_rotation(rotation.0),
1157            )
1158            .reparented_to(&parent_global_transform);
1159
1160            // Update the `Transform` of the entity with the new local transform.
1161            if let Some(mut transform) = world.get_mut::<Transform>(ctx.entity) {
1162                transform.translation = new_transform.translation;
1163                transform.rotation = new_transform.rotation;
1164            }
1165        } else if let Some(mut transform) = world.get_mut::<Transform>(ctx.entity) {
1166            // If the entity has no parent, we can set the transform directly.
1167            #[cfg(feature = "2d")]
1168            {
1169                if !is_pos_placeholder {
1170                    transform.translation = position.f32().extend(transform.translation.z);
1171                }
1172                if !is_rot_placeholder {
1173                    transform.rotation = Quat::from(rotation);
1174                }
1175            }
1176            #[cfg(feature = "3d")]
1177            {
1178                if !is_pos_placeholder {
1179                    transform.translation = position.f32();
1180                }
1181                if !is_rot_placeholder {
1182                    transform.rotation = rotation.0;
1183                }
1184            }
1185        }
1186    }
1187
1188    if !config.transform_to_position {
1189        if is_pos_placeholder && let Some(mut position) = world.get_mut::<Position>(ctx.entity) {
1190            position.0 = RVector::ZERO;
1191        }
1192        if is_rot_placeholder && let Some(mut rotation) = world.get_mut::<Rotation>(ctx.entity) {
1193            *rotation = Rotation::IDENTITY;
1194        }
1195    } else if is_pos_placeholder || is_rot_placeholder {
1196        // If either `Position` or `Rotation` is a placeholder, we need to compute the global transform
1197        // from the hierarchy and set the `Position` and/or `Rotation` to the computed values.
1198
1199        if let Some(global_transform) = global_transform {
1200            // Set the computed `position` and `rotation` based on the global transform.
1201            let (_, global_rotation, global_translation) =
1202                global_transform.to_scale_rotation_translation();
1203            #[cfg(feature = "2d")]
1204            {
1205                position.0 = global_translation.truncate().real();
1206                rotation = Rotation::from(global_rotation);
1207            }
1208            #[cfg(feature = "3d")]
1209            {
1210                position.0 = global_translation.real();
1211                rotation.0 = global_rotation;
1212            }
1213        } else {
1214            // No transform was set. Set the computed `position` and `rotation` to default values.
1215            if is_pos_placeholder {
1216                position.0 = RVector::ZERO;
1217            }
1218            if is_rot_placeholder {
1219                rotation = Rotation::IDENTITY;
1220            }
1221        }
1222
1223        // Now we update the actual component values based on the computed global transform.
1224        let mut entity_mut = world.entity_mut(ctx.entity);
1225
1226        // Set the position unless it was already set.
1227        if let Some(mut pos) = entity_mut
1228            .get_mut::<Position>()
1229            .filter(|pos| **pos == Position::PLACEHOLDER)
1230        {
1231            *pos = position;
1232        }
1233        // Set the rotation to the global transform unless it was already set.
1234        if let Some(mut rot) = entity_mut
1235            .get_mut::<Rotation>()
1236            .filter(|rot| **rot == Rotation::PLACEHOLDER)
1237        {
1238            *rot = rotation;
1239        }
1240    }
1241}