avian3d/dynamics/rigid_body/forces/
query_data.rs

1use crate::{dynamics::integrator::VelocityIntegrationData, prelude::*};
2use bevy::ecs::{
3    query::{Has, QueryData},
4    system::lifetimeless::{Read, Write},
5};
6
7use super::AccumulatedLocalAcceleration;
8
9/// A helper [`QueryData`] for applying forces, impulses, and accelerations to dynamic [rigid bodies](RigidBody).
10///
11/// For constant forces that persist across time steps, consider using components like [`ConstantForce`] instead.
12///
13/// See the [module-level documentation](crate::dynamics::rigid_body::forces) for more general information about forces in Avian.
14///
15/// # Usage
16///
17/// To use [`Forces`], add it to a [`Query`](bevy::prelude::Query) (without `&` or `&mut`),
18/// and use the associated methods to apply forces, impulses, and accelerations to the rigid bodies.
19///
20/// ```
21#[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
22#[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
23/// # use bevy::prelude::*;
24/// #
25/// # #[cfg(feature = "f32")]
26/// fn apply_forces(mut query: Query<Forces>) {
27///     for mut forces in &mut query {
28///         // Apply a force of 10 N in the positive Y direction to the entity.
29#[cfg_attr(
30    feature = "2d",
31    doc = "        forces.apply_force(Vec2::new(0.0, 10.0));"
32)]
33#[cfg_attr(
34    feature = "3d",
35    doc = "        forces.apply_force(Vec3::new(0.0, 10.0, 0.0));"
36)]
37///     }
38/// }
39/// ```
40///
41/// The force is applied continuously during the physics step, and cleared automatically after the step is complete.
42///
43/// By default, applying forces to [sleeping](Sleeping) bodies will wake them up. If this is not desired,
44/// the [`non_waking`](ForcesItem::non_waking) method can be used to fetch a [`NonWakingForcesItem`]
45/// that allows applying forces to a body without waking it up.
46///
47/// ```
48#[cfg_attr(feature = "2d", doc = "# use avian2d::{math::Vector, prelude::*};")]
49#[cfg_attr(feature = "3d", doc = "# use avian3d::{math::Vector, prelude::*};")]
50/// # use bevy::prelude::*;
51/// #
52/// # fn apply_impulses(mut query: Query<Forces>) {
53/// #     for mut forces in &mut query {
54/// #         let force = Vector::default();
55/// // Apply a force without waking up the body if it is sleeping.
56/// forces.non_waking().apply_force(force);
57/// #     }
58/// # }
59/// ```
60///
61/// [`Forces`] can also apply forces and impulses at a specific point in the world. If the point is not aligned
62/// with the [center of mass](CenterOfMass), it will apply a torque to the body.
63///
64/// ```
65#[cfg_attr(feature = "2d", doc = "# use avian2d::{math::Vector, prelude::*};")]
66#[cfg_attr(feature = "3d", doc = "# use avian3d::{math::Vector, prelude::*};")]
67/// # use bevy::prelude::*;
68/// #
69/// # fn apply_impulses(mut query: Query<Forces>) {
70/// #     for mut forces in &mut query {
71/// #         let force = Vector::default();
72/// #         let point = Vector::default();
73/// // Apply an impulse at a specific point in the world.
74/// // Unlike forces, impulses are applied immediately to the velocity.
75/// forces.apply_linear_impulse_at_point(force, point);
76/// #     }
77/// # }
78/// ```
79///
80/// As an example, you could implement radial gravity that pulls rigid bodies towards the world origin
81/// with a system like the following:
82///
83/// ```
84#[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
85#[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
86/// # use bevy::prelude::*;
87/// #
88/// # #[cfg(feature = "f32")]
89/// fn radial_gravity(mut query: Query<(Forces, &GlobalTransform)>) {
90///     for (mut forces, global_transform) in &mut query {
91///         // Compute the direction towards the center of the world.
92///         let direction = -global_transform.translation().normalize_or_zero();
93///         // Apply a linear acceleration of 9.81 m/s² towards the center of the world.
94#[cfg_attr(
95    feature = "2d",
96    doc = "        forces.apply_linear_acceleration(direction.truncate() * 9.81);"
97)]
98#[cfg_attr(
99    feature = "3d",
100    doc = "        forces.apply_linear_acceleration(direction * 9.81);"
101)]
102///     }
103/// }
104/// ```
105#[derive(QueryData)]
106#[query_data(mutable)]
107pub struct Forces {
108    position: Read<Position>,
109    rotation: Read<Rotation>,
110    linear_velocity: Write<LinearVelocity>,
111    angular_velocity: Write<AngularVelocity>,
112    mass: Read<ComputedMass>,
113    angular_inertia: Read<ComputedAngularInertia>,
114    center_of_mass: Read<ComputedCenterOfMass>,
115    locked_axes: Option<Read<LockedAxes>>,
116    integration: Write<VelocityIntegrationData>,
117    accumulated_local_acceleration: Write<AccumulatedLocalAcceleration>,
118    sleep_timer: Option<Write<SleepTimer>>,
119    is_sleeping: Has<Sleeping>,
120}
121
122/// A [`ForcesItem`] that does not wake up the body when applying forces, torques, impulses, or accelerations.
123/// Returned by [`ForcesItem::non_waking`].
124///
125/// See the documentation of [`Forces`] for more information on how to apply forces in Avian.
126pub struct NonWakingForcesItem<'w, 's>(pub ForcesItem<'w, 's>);
127
128impl ForcesItem<'_, '_> {
129    /// Reborrows `self` as a new instance of [`ForcesItem`].
130    #[inline]
131    #[must_use]
132    pub fn reborrow(&mut self) -> ForcesItem<'_, '_> {
133        ForcesItem {
134            position: self.position,
135            rotation: self.rotation,
136            linear_velocity: self.linear_velocity.reborrow(),
137            angular_velocity: self.angular_velocity.reborrow(),
138            mass: self.mass,
139            angular_inertia: self.angular_inertia,
140            center_of_mass: self.center_of_mass,
141            locked_axes: self.locked_axes,
142            integration: self.integration.reborrow(),
143            accumulated_local_acceleration: self.accumulated_local_acceleration.reborrow(),
144            sleep_timer: self.sleep_timer.as_mut().map(|s| s.reborrow()),
145            is_sleeping: self.is_sleeping,
146        }
147    }
148
149    /// Returns a [`NonWakingForcesItem`] that allows applying forces, impulses, and accelerations
150    /// without waking up the body if it is sleeping.
151    #[inline]
152    #[must_use]
153    pub fn non_waking(&mut self) -> NonWakingForcesItem<'_, '_> {
154        NonWakingForcesItem(self.reborrow())
155    }
156}
157
158impl<'w, 's> NonWakingForcesItem<'w, 's> {
159    /// Returns a [`ForcesItem`] that will wake up the body when applying forces, impulses, or accelerations.
160    #[inline]
161    #[must_use]
162    pub fn waking(self) -> ForcesItem<'w, 's> {
163        self.0
164    }
165}
166
167impl RigidBodyForces for ForcesItem<'_, '_> {}
168impl RigidBodyForces for NonWakingForcesItem<'_, '_> {}
169
170/// A trait for applying forces, impulses, and accelerations to a dynamic [rigid body](RigidBody).
171///
172/// This is implemented as a shared interface for the [`ForcesItem`] and [`NonWakingForcesItem`]
173/// returned by [`Forces`].
174///
175/// See the documentation of [`Forces`] for more information on how to apply forces in Avian.
176#[expect(
177    private_bounds,
178    reason = "The `data` method should not be publicly accessible."
179)]
180pub trait RigidBodyForces: RigidBodyForcesInternal {
181    /// Applies a force at the center of mass in world space. The unit is typically N or kg⋅m/s².
182    ///
183    /// The force is applied continuously over the physics step and cleared afterwards.
184    ///
185    /// By default, a non-zero force will wake up the body if it is sleeping. This can be prevented
186    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
187    #[inline]
188    fn apply_force(&mut self, force: Vector) {
189        if force != Vector::ZERO && self.try_wake_up() {
190            let acceleration = self.inverse_mass() * force;
191            self.integration_data_mut()
192                .apply_linear_acceleration(acceleration);
193        }
194    }
195
196    /// Applies a force at the given point in world space. The unit is typically N or kg⋅m/s².
197    ///
198    /// If the point is not at the center of mass, the force will also generate a torque.
199    ///
200    /// The force is applied continuously over the physics step and cleared afterwards.
201    ///
202    /// By default, a non-zero force will wake up the body if it is sleeping. This can be prevented
203    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
204    ///
205    /// # Note
206    ///
207    /// If the [`Transform`] of the body is modified before applying the force,
208    /// the torque will be computed using an outdated global center of mass.
209    /// This may cause problems when applying a force right after teleporting
210    /// an entity, as the torque could grow very large if the distance between the point
211    /// and old center of mass is large.
212    ///
213    /// In case this is causing problems, consider using the [`PhysicsTransformHelper`]
214    /// to update the global physics transform after modifying [`Transform`].
215    ///
216    /// [`Transform`]: bevy::transform::components::Transform
217    #[inline]
218    fn apply_force_at_point(&mut self, force: Vector, world_point: Vector) {
219        // Note: This does not consider the rotation of the body during substeps,
220        //       so the torque may not be accurate if the body is rotating quickly.
221        self.apply_force(force);
222        self.apply_torque(cross(world_point - self.global_center_of_mass(), force));
223    }
224
225    /// Applies a force at the center of mass in local space. The unit is typically N or kg⋅m/s².
226    ///
227    /// The force is applied continuously over the physics step and cleared afterwards.
228    ///
229    /// By default, a non-zero force will wake up the body if it is sleeping. This can be prevented
230    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
231    #[inline]
232    fn apply_local_force(&mut self, force: Vector) {
233        if force != Vector::ZERO && self.try_wake_up() {
234            let acceleration = self.inverse_mass() * force;
235            self.accumulated_local_acceleration_mut().linear += acceleration;
236        }
237    }
238
239    /// Applies a torque in world space. The unit is typically N⋅m or kg⋅m²/s².
240    ///
241    /// The torque is applied continuously over the physics step and cleared afterwards.
242    ///
243    /// By default, a non-zero torque will wake up the body if it is sleeping. This can be prevented
244    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
245    #[inline]
246    fn apply_torque(&mut self, torque: AngularVector) {
247        if torque != AngularVector::ZERO && self.try_wake_up() {
248            let acceleration = self.global_inverse_angular_inertia() * torque;
249            self.integration_data_mut()
250                .apply_angular_acceleration(acceleration);
251        }
252    }
253
254    /// Applies a torque in local space. The unit is typically N⋅m or kg⋅m²/s².
255    ///
256    /// The torque is applied continuously over the physics step and cleared afterwards.
257    ///
258    /// By default, a non-zero torque will wake up the body if it is sleeping. This can be prevented
259    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
260    #[cfg(feature = "3d")]
261    #[inline]
262    fn apply_local_torque(&mut self, torque: AngularVector) {
263        if torque != AngularVector::ZERO && self.try_wake_up() {
264            let acceleration = self.inverse_angular_inertia() * torque;
265            self.accumulated_local_acceleration_mut().angular += acceleration;
266        }
267    }
268
269    /// Applies a linear impulse at the center of mass in world space. The unit is typically N⋅s or kg⋅m/s.
270    ///
271    /// The impulse modifies the [`LinearVelocity`] of the body immediately.
272    ///
273    /// By default, a non-zero impulse will wake up the body if it is sleeping. This can be prevented
274    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
275    #[inline]
276    fn apply_linear_impulse(&mut self, impulse: Vector) {
277        if impulse != Vector::ZERO && self.try_wake_up() {
278            let effective_inverse_mass = self
279                .locked_axes()
280                .apply_to_vec(Vector::splat(self.inverse_mass()));
281            let delta_vel = effective_inverse_mass * impulse;
282            *self.linear_velocity_mut() += delta_vel;
283        }
284    }
285
286    /// Applies a linear impulse at the given point in world space. The unit is typically N⋅s or kg⋅m/s.
287    ///
288    /// If the point is not at the center of mass, the impulse will also generate an angular impulse.
289    ///
290    /// The impulse modifies the [`LinearVelocity`] and [`AngularVelocity`] of the body immediately.
291    ///
292    /// By default, a non-zero impulse will wake up the body if it is sleeping. This can be prevented
293    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
294    ///
295    /// # Note
296    ///
297    /// If the [`Transform`] of the body is modified before applying the impulse,
298    /// the torque will be computed using an outdated global center of mass.
299    /// This may cause problems when applying a impulse right after teleporting
300    /// an entity, as the torque could grow very large if the distance between the point
301    /// and old center of mass is large.
302    ///
303    /// In case this is causing problems, consider using the [`PhysicsTransformHelper`]
304    /// to update the global physics transform after modifying [`Transform`].
305    ///
306    /// [`Transform`]: bevy::transform::components::Transform
307    #[inline]
308    fn apply_linear_impulse_at_point(&mut self, impulse: Vector, world_point: Vector) {
309        self.apply_linear_impulse(impulse);
310        self.apply_angular_impulse(cross(world_point - self.global_center_of_mass(), impulse));
311    }
312
313    /// Applies a linear impulse in local space. The unit is typically N⋅s or kg⋅m/s.
314    ///
315    /// The impulse modifies the [`LinearVelocity`] of the body immediately.
316    ///
317    /// By default, a non-zero impulse will wake up the body if it is sleeping. This can be prevented
318    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
319    #[inline]
320    fn apply_local_linear_impulse(&mut self, impulse: Vector) {
321        if impulse != Vector::ZERO && self.try_wake_up() {
322            let world_impulse = self.rot() * impulse;
323            let effective_inverse_mass = self
324                .locked_axes()
325                .apply_to_vec(Vector::splat(self.inverse_mass()));
326            let delta_vel = effective_inverse_mass * world_impulse;
327            *self.linear_velocity_mut() += delta_vel;
328        }
329    }
330
331    /// Applies an angular impulse in world space. The unit is typically N⋅m⋅s or kg⋅m²/s.
332    ///
333    /// The impulse modifies the [`AngularVelocity`] of the body immediately.
334    ///
335    /// By default, a non-zero impulse will wake up the body if it is sleeping. This can be prevented
336    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
337    #[inline]
338    fn apply_angular_impulse(&mut self, impulse: AngularVector) {
339        if impulse != AngularVector::ZERO && self.try_wake_up() {
340            let effective_inverse_angular_inertia = self
341                .locked_axes()
342                .apply_to_angular_inertia(self.global_inverse_angular_inertia());
343            let delta_vel = effective_inverse_angular_inertia * impulse;
344            *self.angular_velocity_mut() += delta_vel;
345        }
346    }
347
348    /// Applies an angular impulse in local space. The unit is typically N⋅m⋅s or kg⋅m²/s.
349    ///
350    /// The impulse modifies the [`AngularVelocity`] of the body immediately.
351    ///
352    /// By default, a non-zero impulse will wake up the body if it is sleeping. This can be prevented
353    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
354    #[cfg(feature = "3d")]
355    #[inline]
356    fn apply_local_angular_impulse(&mut self, impulse: AngularVector) {
357        if impulse != AngularVector::ZERO && self.try_wake_up() {
358            let world_impulse = self.rot() * impulse;
359            let effective_inverse_angular_inertia = self
360                .locked_axes()
361                .apply_to_angular_inertia(self.global_inverse_angular_inertia());
362            let delta_vel = effective_inverse_angular_inertia * world_impulse;
363            *self.angular_velocity_mut() += delta_vel;
364        }
365    }
366
367    /// Applies a linear acceleration, ignoring mass. The unit is typically m/s².
368    ///
369    /// The acceleration is applied continuously over the physics step and cleared afterwards.
370    ///
371    /// By default, a non-zero acceleration will wake up the body if it is sleeping. This can be prevented
372    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
373    #[inline]
374    fn apply_linear_acceleration(&mut self, acceleration: Vector) {
375        if acceleration != Vector::ZERO && self.try_wake_up() {
376            self.integration_data_mut()
377                .apply_linear_acceleration(acceleration);
378        }
379    }
380
381    /// Applies a linear acceleration at the given point in world space. The unit is typically m/s².
382    ///
383    /// If the point is not at the center of mass, the acceleration will also generate an angular acceleration.
384    ///
385    /// The acceleration is applied continuously over the physics step and cleared afterwards.
386    ///
387    /// By default, a non-zero acceleration will wake up the body if it is sleeping. This can be prevented
388    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
389    ///
390    /// # Note
391    ///
392    /// If the [`Transform`] of the body is modified before applying the acceleration,
393    /// the angular acceleration will be computed using an outdated global center of mass.
394    /// This may cause problems when applying a acceleration right after teleporting
395    /// an entity, as the angular acceleration could grow very large if the distance between the point
396    /// and old center of mass is large.
397    ///
398    /// In case this is causing problems, consider using the [`PhysicsTransformHelper`]
399    /// to update the global physics transform after modifying [`Transform`].
400    ///
401    /// [`Transform`]: bevy::transform::components::Transform
402    #[inline]
403    fn apply_linear_acceleration_at_point(&mut self, acceleration: Vector, world_point: Vector) {
404        self.apply_linear_acceleration(acceleration);
405        self.apply_angular_acceleration(cross(
406            world_point - self.global_center_of_mass(),
407            acceleration,
408        ));
409    }
410
411    /// Applies a linear acceleration in local space, ignoring mass. The unit is typically m/s².
412    ///
413    /// The acceleration is applied continuously over the physics step and cleared afterwards.
414    ///
415    /// By default, a non-zero acceleration will wake up the body if it is sleeping. This can be prevented
416    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
417    #[inline]
418    fn apply_local_linear_acceleration(&mut self, acceleration: Vector) {
419        if acceleration != Vector::ZERO && self.try_wake_up() {
420            self.accumulated_local_acceleration_mut().linear += acceleration;
421        }
422    }
423
424    /// Applies an angular acceleration, ignoring angular inertia. The unit is rad/s².
425    ///
426    /// The acceleration is applied continuously over the physics step and cleared afterwards.
427    ///
428    /// By default, a non-zero acceleration will wake up the body if it is sleeping. This can be prevented
429    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
430    #[inline]
431    fn apply_angular_acceleration(&mut self, acceleration: AngularVector) {
432        if acceleration != AngularVector::ZERO && self.try_wake_up() {
433            self.integration_data_mut()
434                .apply_angular_acceleration(acceleration);
435        }
436    }
437
438    /// Applies an angular acceleration in local space, ignoring angular inertia. The unit is rad/s².
439    ///
440    /// The acceleration is applied continuously over the physics step and cleared afterwards.
441    ///
442    /// By default, a non-zero acceleration will wake up the body if it is sleeping. This can be prevented
443    /// by first calling [`ForcesItem::non_waking`] to get a [`NonWakingForcesItem`].
444    #[cfg(feature = "3d")]
445    #[inline]
446    fn apply_local_angular_acceleration(&mut self, acceleration: AngularVector) {
447        if acceleration != AngularVector::ZERO && self.try_wake_up() {
448            self.accumulated_local_acceleration_mut().angular += acceleration;
449        }
450    }
451
452    /// Returns the linear acceleration that the body has accumulated
453    /// before the physics step in world space, including acceleration
454    /// caused by forces.
455    ///
456    /// This does not include gravity, contact forces, or joint forces.
457    /// Only forces and accelerations applied through [`Forces`] are included.
458    #[inline]
459    fn accumulated_linear_acceleration(&self) -> Vector {
460        // The linear increment is treated as linear acceleration until the integration step.
461        let world_linear_acceleration = self.integration_data().linear_increment;
462        let local_linear_acceleration = self.accumulated_local_acceleration().linear;
463
464        // Return the total world-space linear acceleration.
465        self.locked_axes()
466            .apply_to_vec(world_linear_acceleration + self.rot() * local_linear_acceleration)
467    }
468
469    /// Returns the angular acceleration that the body has accumulated
470    /// before the physics step in world space, including acceleration
471    /// caused by torques.
472    ///
473    /// This does not include gravity, contact forces, or joint forces.
474    /// Only torques and accelerations applied through [`Forces`] are included.
475    #[cfg(feature = "2d")]
476    #[inline]
477    fn accumulated_angular_acceleration(&self) -> AngularVector {
478        // The angular increment is treated as angular acceleration until the integration step.
479        self.locked_axes()
480            .apply_to_angular_velocity(self.integration_data().angular_increment)
481    }
482
483    /// Returns the angular acceleration that the body has accumulated
484    /// before the physics step in world space, including acceleration
485    /// caused by torques.
486    ///
487    /// This does not include gravity, contact forces, or joint forces.
488    /// Only torques and accelerations applied through [`Forces`] are included.
489    #[cfg(feature = "3d")]
490    #[inline]
491    fn accumulated_angular_acceleration(&self) -> AngularVector {
492        // The angular increment is treated as angular acceleration until the integration step.
493        let world_angular_acceleration = self.integration_data().angular_increment;
494        let local_angular_acceleration = self.accumulated_local_acceleration().angular;
495
496        // Return the total world-space angular acceleration.
497        self.locked_axes().apply_to_angular_velocity(
498            world_angular_acceleration + self.rot() * local_angular_acceleration,
499        )
500    }
501
502    /// Resets the accumulated linear acceleration to zero.
503    #[inline]
504    fn reset_accumulated_linear_acceleration(&mut self) {
505        self.integration_data_mut().linear_increment = Vector::ZERO;
506        self.accumulated_local_acceleration_mut().linear = Vector::ZERO;
507    }
508
509    /// Resets the accumulated angular acceleration to zero.
510    #[inline]
511    fn reset_accumulated_angular_acceleration(&mut self) {
512        self.integration_data_mut().angular_increment = AngularVector::ZERO;
513        #[cfg(feature = "3d")]
514        {
515            self.accumulated_local_acceleration_mut().angular = AngularVector::ZERO;
516        }
517    }
518
519    /// Returns the [`Position`] of the body.
520    #[inline]
521    fn position(&self) -> &Position {
522        self.pos()
523    }
524
525    /// Returns the [`Rotation`] of the body.
526    #[inline]
527    fn rotation(&self) -> &Rotation {
528        self.rot()
529    }
530
531    /// Returns the [`LinearVelocity`] of the body in world space.
532    #[inline]
533    fn linear_velocity(&self) -> Vector {
534        self.lin_vel()
535    }
536
537    /// Returns a mutable reference to the [`LinearVelocity`] of the body in world space.
538    #[inline]
539    fn linear_velocity_mut(&mut self) -> &mut Vector {
540        self.lin_vel_mut()
541    }
542
543    /// Returns the [`AngularVelocity`] of the body in world space.
544    #[inline]
545    fn angular_velocity(&self) -> AngularVector {
546        self.ang_vel()
547    }
548
549    /// Returns a mutable reference to the [`AngularVelocity`] of the body in world space.
550    #[inline]
551    fn angular_velocity_mut(&mut self) -> &mut AngularVector {
552        self.ang_vel_mut()
553    }
554
555    /// Returns the velocity of a point in world space on the body.
556    #[inline]
557    #[doc(alias = "linear_velocity_at_point")]
558    fn velocity_at_point(&self, world_point: Vector) -> Vector {
559        let offset = world_point - self.global_center_of_mass();
560        #[cfg(feature = "2d")]
561        {
562            self.linear_velocity() + self.angular_velocity() * offset.perp()
563        }
564        #[cfg(feature = "3d")]
565        {
566            self.linear_velocity() + self.angular_velocity().cross(offset)
567        }
568    }
569}
570
571/// A trait to provide internal getters and helpers for [`RigidBodyForces`].
572trait RigidBodyForcesInternal {
573    fn pos(&self) -> &Position;
574    fn rot(&self) -> &Rotation;
575    fn lin_vel(&self) -> Vector;
576    fn lin_vel_mut(&mut self) -> &mut Vector;
577    fn ang_vel(&self) -> AngularVector;
578    fn ang_vel_mut(&mut self) -> &mut AngularVector;
579    fn inverse_mass(&self) -> Scalar;
580    #[cfg(feature = "3d")]
581    fn inverse_angular_inertia(&self) -> SymmetricTensor;
582    fn global_inverse_angular_inertia(&self) -> SymmetricTensor;
583    fn global_center_of_mass(&self) -> Vector;
584    fn locked_axes(&self) -> LockedAxes;
585    fn integration_data(&self) -> &VelocityIntegrationData;
586    fn integration_data_mut(&mut self) -> &mut VelocityIntegrationData;
587    fn accumulated_local_acceleration(&self) -> &AccumulatedLocalAcceleration;
588    fn accumulated_local_acceleration_mut(&mut self) -> &mut AccumulatedLocalAcceleration;
589    fn try_wake_up(&mut self) -> bool;
590}
591
592impl RigidBodyForcesInternal for ForcesItem<'_, '_> {
593    #[inline]
594    fn pos(&self) -> &Position {
595        self.position
596    }
597    #[inline]
598    fn rot(&self) -> &Rotation {
599        self.rotation
600    }
601    #[inline]
602    fn lin_vel(&self) -> Vector {
603        self.linear_velocity.0
604    }
605    #[inline]
606    fn lin_vel_mut(&mut self) -> &mut Vector {
607        &mut self.linear_velocity.0
608    }
609    #[inline]
610    fn ang_vel(&self) -> AngularVector {
611        self.angular_velocity.0
612    }
613    #[inline]
614    fn ang_vel_mut(&mut self) -> &mut AngularVector {
615        &mut self.angular_velocity.0
616    }
617    #[inline]
618    fn inverse_mass(&self) -> Scalar {
619        self.mass.inverse()
620    }
621    #[inline]
622    #[cfg(feature = "3d")]
623    fn inverse_angular_inertia(&self) -> SymmetricTensor {
624        self.angular_inertia.inverse()
625    }
626    #[inline]
627    fn global_inverse_angular_inertia(&self) -> SymmetricTensor {
628        #[cfg(feature = "2d")]
629        let global_angular_inertia = *self.angular_inertia;
630        #[cfg(feature = "3d")]
631        let global_angular_inertia = self.angular_inertia.rotated(self.rotation.0);
632        self.locked_axes()
633            .apply_to_angular_inertia(global_angular_inertia)
634            .inverse()
635    }
636    #[inline]
637    fn global_center_of_mass(&self) -> Vector {
638        self.position.0 + self.rotation * self.center_of_mass.0
639    }
640    #[inline]
641    fn locked_axes(&self) -> LockedAxes {
642        self.locked_axes.copied().unwrap_or_default()
643    }
644    #[inline]
645    fn integration_data(&self) -> &VelocityIntegrationData {
646        &self.integration
647    }
648    #[inline]
649    fn integration_data_mut(&mut self) -> &mut VelocityIntegrationData {
650        &mut self.integration
651    }
652    #[inline]
653    fn accumulated_local_acceleration(&self) -> &AccumulatedLocalAcceleration {
654        &self.accumulated_local_acceleration
655    }
656    #[inline]
657    fn accumulated_local_acceleration_mut(&mut self) -> &mut AccumulatedLocalAcceleration {
658        &mut self.accumulated_local_acceleration
659    }
660    #[inline]
661    fn try_wake_up(&mut self) -> bool {
662        // Wake up the body. Return `true` to indicate that the body is awake.
663        if let Some(sleep_timer) = &mut self.sleep_timer {
664            sleep_timer.0 = 0.0;
665        }
666        true
667    }
668}
669
670impl RigidBodyForcesInternal for NonWakingForcesItem<'_, '_> {
671    #[inline]
672    fn pos(&self) -> &Position {
673        self.0.position()
674    }
675    #[inline]
676    fn rot(&self) -> &Rotation {
677        self.0.rot()
678    }
679    #[inline]
680    fn lin_vel(&self) -> Vector {
681        self.0.lin_vel()
682    }
683    #[inline]
684    fn lin_vel_mut(&mut self) -> &mut Vector {
685        self.0.lin_vel_mut()
686    }
687    #[inline]
688    fn ang_vel(&self) -> AngularVector {
689        self.0.ang_vel()
690    }
691    #[inline]
692    fn ang_vel_mut(&mut self) -> &mut AngularVector {
693        self.0.ang_vel_mut()
694    }
695    #[inline]
696    fn inverse_mass(&self) -> Scalar {
697        self.0.inverse_mass()
698    }
699    #[inline]
700    #[cfg(feature = "3d")]
701    fn inverse_angular_inertia(&self) -> SymmetricTensor {
702        self.0.inverse_angular_inertia()
703    }
704    #[inline]
705    fn global_inverse_angular_inertia(&self) -> SymmetricTensor {
706        self.0.global_inverse_angular_inertia()
707    }
708    #[inline]
709    fn global_center_of_mass(&self) -> Vector {
710        self.0.global_center_of_mass()
711    }
712    #[inline]
713    fn locked_axes(&self) -> LockedAxes {
714        self.0.locked_axes()
715    }
716    #[inline]
717    fn integration_data(&self) -> &VelocityIntegrationData {
718        self.0.integration_data()
719    }
720    #[inline]
721    fn integration_data_mut(&mut self) -> &mut VelocityIntegrationData {
722        self.0.integration_data_mut()
723    }
724    #[inline]
725    fn accumulated_local_acceleration(&self) -> &AccumulatedLocalAcceleration {
726        self.0.accumulated_local_acceleration()
727    }
728    #[inline]
729    fn accumulated_local_acceleration_mut(&mut self) -> &mut AccumulatedLocalAcceleration {
730        self.0.accumulated_local_acceleration_mut()
731    }
732    #[inline]
733    fn try_wake_up(&mut self) -> bool {
734        // Don't wake up the body.
735        // Return `true` if the body is already awake and forces should be applied.
736        !self.0.is_sleeping
737    }
738}