avian3d/physics_transform/
transform.rs

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