avian3d/dynamics/rigid_body/
forces.rs

1//! Forces, torques, linear impulses, and angular impulses
2//! that can be applied to dynamic rigid bodies.
3
4use crate::prelude::*;
5use bevy::prelude::*;
6use core::ops::{Deref, DerefMut};
7use derive_more::From;
8
9#[cfg(feature = "2d")]
10pub(crate) type Torque = Scalar;
11
12#[cfg(feature = "3d")]
13pub(crate) type Torque = Vector;
14
15#[cfg(feature = "2d")]
16pub(crate) trait FloatZero {
17    const ZERO: Self;
18}
19
20#[cfg(feature = "2d")]
21impl FloatZero for Scalar {
22    const ZERO: Self = 0.0;
23}
24
25/// An external force applied continuously to a dynamic [rigid body](RigidBody).
26///
27/// The force is stored in world space. If you want to apply forces in local space, you need to
28/// use the body's rotation to [transform the local force into world space](#local-forces).
29///
30/// By default, the force persists across frames. You can clear the force manually using
31/// [`clear`](Self::clear) or set `persistent` to false.
32///
33/// # Example
34///
35/// ```
36/// # #[cfg(feature = "2d")]
37/// # use avian2d::prelude::*;
38/// # #[cfg(feature = "3d")]
39/// use avian3d::prelude::*;
40/// use bevy::prelude::*;
41///
42/// # #[cfg(all(feature = "3d", feature = "f32"))]
43/// fn setup(mut commands: Commands) {
44///     // Apply a force in world space every physics frame.
45///     commands.spawn((RigidBody::Dynamic, ExternalForce::new(Vec3::Y)));
46///
47///     // Apply an initial force and automatically clear it every physics frame.
48///     commands.spawn((
49///         RigidBody::Dynamic,
50///         ExternalForce::new(Vec3::Y).with_persistence(false),
51///     ));
52///
53///     // Apply multiple forces.
54///     let mut force = ExternalForce::default();
55///     force.apply_force(Vec3::Y).apply_force(Vec3::X);
56///     commands.spawn((RigidBody::Dynamic, force));
57///
58///     // Apply a force at a specific point relative to the given center of mass, also applying a torque.
59///     // In this case, the torque would cause the body to rotate counterclockwise.
60///     let mut force = ExternalForce::default();
61///     force.apply_force_at_point(Vec3::Y, Vec3::X, Vec3::ZERO);
62///     commands.spawn((RigidBody::Dynamic, force));
63/// }
64/// ```
65///
66/// # Local Forces
67///
68/// The force stored in `ExternalForce` is in world space.
69///
70/// If you want to apply a force in some direction relative to the body's frame of reference,
71/// you need to rotate the force using the body's `Transform` or [`Rotation`].
72///
73/// ```
74/// # #[cfg(feature = "2d")]
75/// # use avian2d::prelude::*;
76/// # #[cfg(feature = "3d")]
77/// use avian3d::prelude::*;
78/// use bevy::prelude::*;
79///
80/// # #[cfg(all(feature = "3d", feature = "f32"))]
81/// fn setup(mut commands: Commands) {
82///     // Spawn a rotated body and apply a force in the local up direction.
83///     let transform = Transform::from_rotation(Quat::from_rotation_z(0.2));
84///     commands.spawn((
85///         RigidBody::Dynamic,
86///         ExternalForce::new(transform.rotation * Vec3::Y),
87///         transform,
88///     ));
89/// }
90/// ```
91///
92/// Note that the actual force stored in `ExternalForce` is still in world space.
93/// If you want to apply a force in the same local direction every frame,
94/// consider setting `persistent` to `false` and running [`apply_force`](Self::apply_force) in a system.
95#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq, From)]
96#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
97#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
98#[reflect(Debug, Component, PartialEq)]
99pub struct ExternalForce {
100    /// The total external force that will be applied.
101    force: Vector,
102    /// True if the force persists across frames, and false if the force is automatically cleared every physics frame.
103    ///
104    /// If you clear the force manually, use the [`clear`](Self::clear) method. This will clear the force and
105    /// the torque that is applied when the force is not applied at the center of mass.
106    pub persistent: bool,
107    /// The torque caused by forces applied at certain points using [`apply_force_at_point`](Self::apply_force_at_point).
108    torque: Torque,
109}
110
111impl Deref for ExternalForce {
112    type Target = Vector;
113
114    fn deref(&self) -> &Self::Target {
115        &self.force
116    }
117}
118
119impl DerefMut for ExternalForce {
120    fn deref_mut(&mut self) -> &mut Self::Target {
121        &mut self.force
122    }
123}
124
125impl Default for ExternalForce {
126    fn default() -> Self {
127        Self {
128            force: Vector::ZERO,
129            persistent: true,
130            torque: Torque::ZERO,
131        }
132    }
133}
134
135impl ExternalForce {
136    /// Zero external force.
137    pub const ZERO: Self = Self {
138        force: Vector::ZERO,
139        persistent: true,
140        torque: Torque::ZERO,
141    };
142
143    /// Creates a new [`ExternalForce`] component with a given world-space `force`.
144    pub fn new(force: Vector) -> Self {
145        Self { force, ..default() }
146    }
147
148    /// Sets the world-space force. Note that the torque caused by any forces will not be reset.
149    pub fn set_force(&mut self, force: Vector) -> &mut Self {
150        **self = force;
151        self
152    }
153
154    /// Adds the given world-space `force` to the force that will be applied.
155    pub fn apply_force(&mut self, force: Vector) -> &mut Self {
156        **self += force;
157        self
158    }
159
160    /// Applies the given `force` at the specified `point`, which will also cause torque to be applied.
161    ///
162    /// The force, point, and center of mass must be given in world space.
163    pub fn apply_force_at_point(
164        &mut self,
165        force: Vector,
166        point: Vector,
167        center_of_mass: Vector,
168    ) -> &mut Self {
169        **self += force;
170        #[cfg(feature = "2d")]
171        {
172            self.torque += (point - center_of_mass).perp_dot(force);
173        }
174        #[cfg(feature = "3d")]
175        {
176            self.torque += (point - center_of_mass).cross(force);
177        }
178        self
179    }
180
181    /// Returns the force in world space.
182    pub fn force(&self) -> Vector {
183        self.force
184    }
185
186    /// Returns the torque caused by forces applied at certain points using
187    /// [`apply_force_at_point`](Self::apply_force_at_point).
188    pub fn torque(&self) -> Torque {
189        self.torque
190    }
191
192    /// Determines if the force is persistent or if it should be automatically cleared every physics frame.
193    #[doc(alias = "clear_automatically")]
194    pub fn with_persistence(mut self, is_persistent: bool) -> Self {
195        self.persistent = is_persistent;
196        self
197    }
198
199    /// Sets the force and the potential torque caused by the force to zero.
200    pub fn clear(&mut self) {
201        self.force = Vector::ZERO;
202        self.torque = Torque::ZERO;
203    }
204}
205
206/// An external torque applied continuously to a dynamic [rigid body](RigidBody).
207///
208/// By default, the torque persists across frames. You can clear the torque manually using
209/// [`clear`](Self::clear) or set `persistent` to false.
210///
211/// # Example
212///
213/// ```
214/// # #[cfg(feature = "2d")]
215/// # use avian2d::prelude::*;
216/// # #[cfg(feature = "3d")]
217/// use avian3d::prelude::*;
218/// use bevy::prelude::*;
219///
220/// # #[cfg(all(feature = "3d", feature = "f32"))]
221/// fn setup(mut commands: Commands) {
222///     // Apply a torque every physics frame.
223///     commands.spawn((RigidBody::Dynamic, ExternalTorque::new(Vec3::Y)));
224///
225///     // Apply an initial torque and automatically clear it every physics frame.
226///     commands.spawn((
227///         RigidBody::Dynamic,
228///         ExternalTorque::new(Vec3::Y).with_persistence(false),
229///     ));
230///
231///     // Apply multiple torques.
232///     let mut torque = ExternalTorque::default();
233///     torque.apply_torque(Vec3::Y).apply_torque(Vec3::X);
234///     commands.spawn((RigidBody::Dynamic, torque));
235/// }
236/// ```
237#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq, From)]
238#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
239#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
240#[reflect(Debug, Component, PartialEq)]
241pub struct ExternalTorque {
242    /// The total external torque that will be applied.
243    torque: Torque,
244    /// True if the torque persists across frames, and false if the torque is automatically cleared every physics frame.
245    pub persistent: bool,
246}
247
248impl Deref for ExternalTorque {
249    type Target = Torque;
250
251    fn deref(&self) -> &Self::Target {
252        &self.torque
253    }
254}
255
256impl DerefMut for ExternalTorque {
257    fn deref_mut(&mut self) -> &mut Self::Target {
258        &mut self.torque
259    }
260}
261
262impl Default for ExternalTorque {
263    fn default() -> Self {
264        Self {
265            torque: Torque::ZERO,
266            persistent: true,
267        }
268    }
269}
270
271impl ExternalTorque {
272    /// Zero external torque.
273    pub const ZERO: Self = Self {
274        torque: Torque::ZERO,
275        persistent: true,
276    };
277
278    /// Creates a new [`ExternalTorque`] component with a given `torque`.
279    pub fn new(torque: Torque) -> Self {
280        Self {
281            torque,
282            ..default()
283        }
284    }
285
286    /// Sets the torque.
287    pub fn set_torque(&mut self, torque: Torque) -> &mut Self {
288        **self = torque;
289        self
290    }
291
292    /// Adds the given `torque` to the torque that will be applied.
293    pub fn apply_torque(&mut self, torque: Torque) -> &mut Self {
294        **self += torque;
295        self
296    }
297
298    /// Determines if the torque is persistent or if it should be automatically cleared every physics frame.
299    #[doc(alias = "clear_automatically")]
300    pub fn with_persistence(mut self, is_persistent: bool) -> Self {
301        self.persistent = is_persistent;
302        self
303    }
304
305    /// Returns the torque.
306    pub fn torque(&self) -> Torque {
307        self.torque
308    }
309
310    /// Sets the torque to zero.
311    pub fn clear(&mut self) {
312        self.torque = Torque::ZERO;
313    }
314}
315
316/// An external impulse applied instantly to a dynamic [rigid body](RigidBody).
317///
318/// The impulse is stored in world space. If you want to apply impulses in local space, you need to
319/// use the body's rotation to [transform the local impulse into world space](#local-impulses).
320///
321/// By default, the impulse is cleared every frame. You can set `persistent` to true in order to persist
322/// the impulse across frames.
323///
324/// # Example
325///
326/// ```
327/// # #[cfg(feature = "2d")]
328/// # use avian2d::prelude::*;
329/// # #[cfg(feature = "3d")]
330/// use avian3d::prelude::*;
331/// use bevy::prelude::*;
332///
333/// # #[cfg(all(feature = "3d", feature = "f32"))]
334/// fn setup(mut commands: Commands) {
335///     // Apply an impulse in world space.
336///     commands.spawn((RigidBody::Dynamic, ExternalImpulse::new(Vec3::Y)));
337///
338///     // Apply an impulse every physics frame.
339///     commands.spawn((
340///         RigidBody::Dynamic,
341///         ExternalImpulse::new(Vec3::Y).with_persistence(true),
342///     ));
343///
344///     // Apply multiple impulses.
345///     let mut impulse = ExternalImpulse::default();
346///     impulse.apply_impulse(Vec3::Y).apply_impulse(Vec3::X);
347///     commands.spawn((RigidBody::Dynamic, impulse));
348///
349///     // Apply an impulse at a specific point relative to the given center of mass, also applying an angular impulse.
350///     // In this case, the angular impulse would cause the body to rotate counterclockwise.
351///     let mut impulse = ExternalImpulse::default();
352///     impulse.apply_impulse_at_point(Vec3::Y, Vec3::X, Vec3::ZERO);
353///     commands.spawn((RigidBody::Dynamic, impulse));
354/// }
355/// ```
356///
357/// # Local Impulses
358///
359/// The impulse stored in `ExternalImpulse` is in world space.
360///
361/// If you want to apply an impulse in some direction relative to the body's frame of reference,
362/// you need to rotate the impulse using the body's `Transform` or [`Rotation`].
363///
364/// ```
365/// # #[cfg(feature = "2d")]
366/// # use avian2d::prelude::*;
367/// # #[cfg(feature = "3d")]
368/// use avian3d::prelude::*;
369/// use bevy::prelude::*;
370///
371/// # #[cfg(all(feature = "3d", feature = "f32"))]
372/// fn setup(mut commands: Commands) {
373///     // Spawn a rotated body and apply an impulse in the local up direction.
374///     let transform = Transform::from_rotation(Quat::from_rotation_z(0.2));
375///     commands.spawn((
376///         RigidBody::Dynamic,
377///         ExternalImpulse::new(transform.rotation * Vec3::Y),
378///         transform,
379///     ));
380/// }
381/// ```
382#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq, From)]
383#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
384#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
385#[reflect(Debug, Component, PartialEq)]
386pub struct ExternalImpulse {
387    /// The total external impulse that will be applied.
388    impulse: Vector,
389    /// True if the impulse persists across frames, and false if the impulse is automatically cleared every physics frame.
390    ///
391    /// If you clear the impulse manually, use the [`clear`](Self::clear) method. This will clear the impulse and
392    /// the angular impulse that is applied when the impulse is not applied at the center of mass.
393    pub persistent: bool,
394    /// The angular impulse caused by impulses applied at certain points using [`apply_impulse_at_point`](Self::apply_impulse_at_point).
395    angular_impulse: Torque,
396}
397
398impl Deref for ExternalImpulse {
399    type Target = Vector;
400
401    fn deref(&self) -> &Self::Target {
402        &self.impulse
403    }
404}
405
406impl DerefMut for ExternalImpulse {
407    fn deref_mut(&mut self) -> &mut Self::Target {
408        &mut self.impulse
409    }
410}
411
412impl Default for ExternalImpulse {
413    fn default() -> Self {
414        Self {
415            impulse: Vector::ZERO,
416            persistent: false,
417            angular_impulse: Torque::ZERO,
418        }
419    }
420}
421
422impl ExternalImpulse {
423    /// Zero external impulse.
424    pub const ZERO: Self = Self {
425        impulse: Vector::ZERO,
426        persistent: false,
427        angular_impulse: Torque::ZERO,
428    };
429
430    /// Creates a new [`ExternalImpulse`] component with a given world-space `impulse`.
431    pub fn new(impulse: Vector) -> Self {
432        Self {
433            impulse,
434            ..default()
435        }
436    }
437
438    /// Sets the world-space impulse. Note that the angular impulse caused by any impulses will not be reset.
439    pub fn set_impulse(&mut self, impulse: Vector) -> &mut Self {
440        **self = impulse;
441        self
442    }
443
444    /// Adds the given world-space `impulse` to the impulse that will be applied.
445    pub fn apply_impulse(&mut self, impulse: Vector) -> &mut Self {
446        **self += impulse;
447        self
448    }
449
450    /// Applies the given `impulse` at the specified `point`, which will also cause an angular impulse to be applied.
451    ///
452    /// The impulse, point, and center of mass must be given in world space.
453    pub fn apply_impulse_at_point(
454        &mut self,
455        impulse: Vector,
456        point: Vector,
457        center_of_mass: Vector,
458    ) -> &mut Self {
459        **self += impulse;
460        #[cfg(feature = "2d")]
461        {
462            self.angular_impulse += (point - center_of_mass).perp_dot(impulse);
463        }
464        #[cfg(feature = "3d")]
465        {
466            self.angular_impulse += (point - center_of_mass).cross(impulse);
467        }
468        self
469    }
470
471    /// Returns the impulse in world space.
472    pub fn impulse(&self) -> Vector {
473        self.impulse
474    }
475
476    /// Returns the angular impulse caused by impulses applied at certain points using
477    /// [`apply_impulse_at_point`](Self::apply_impulse_at_point).
478    pub fn angular_impulse(&self) -> Torque {
479        self.angular_impulse
480    }
481
482    /// Determines if the impulse is persistent or if it should be automatically cleared every physics frame.
483    #[doc(alias = "clear_automatically")]
484    pub fn with_persistence(mut self, is_persistent: bool) -> Self {
485        self.persistent = is_persistent;
486        self
487    }
488
489    /// Sets the impulse and the potential angular impulse caused by the impulse to zero.
490    pub fn clear(&mut self) {
491        self.impulse = Vector::ZERO;
492        self.angular_impulse = Torque::ZERO;
493    }
494}
495
496/// An external angular impulse applied instantly to a dynamic [rigid body](RigidBody).
497///
498/// By default, the angular impulse is cleared every frame. You can set `persistent` to true in order to persist
499/// the impulse across frames.
500///
501/// # Example
502///
503/// ```
504/// # #[cfg(feature = "2d")]
505/// # use avian2d::prelude::*;
506/// # #[cfg(feature = "3d")]
507/// use avian3d::prelude::*;
508/// use bevy::prelude::*;
509///
510/// # #[cfg(all(feature = "3d", feature = "f32"))]
511/// fn setup(mut commands: Commands) {
512///     // Apply an angular impulse.
513///     commands.spawn((RigidBody::Dynamic, ExternalAngularImpulse::new(Vec3::Y)));
514///
515///     // Apply an angular impulse every physics frame.
516///     commands.spawn((
517///         RigidBody::Dynamic,
518///         ExternalAngularImpulse::new(Vec3::Y).with_persistence(false),
519///     ));
520///
521///     // Apply multiple angular impulses.
522///     let mut angular_impulse = ExternalAngularImpulse::default();
523///     angular_impulse.apply_impulse(Vec3::Y).apply_impulse(Vec3::X);
524///     commands.spawn((RigidBody::Dynamic, angular_impulse));
525/// }
526/// ```
527#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq, From)]
528#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
529#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
530#[reflect(Debug, Component, PartialEq)]
531#[doc(alias = "ExternalTorqueImpulse")]
532pub struct ExternalAngularImpulse {
533    /// The total external angular impulse that will be applied.
534    impulse: Torque,
535    /// True if the angular impulse persists across frames, and false if
536    /// the angular impulse is automatically cleared every physics frame.
537    pub persistent: bool,
538}
539
540impl Deref for ExternalAngularImpulse {
541    type Target = Torque;
542
543    fn deref(&self) -> &Self::Target {
544        &self.impulse
545    }
546}
547
548impl DerefMut for ExternalAngularImpulse {
549    fn deref_mut(&mut self) -> &mut Self::Target {
550        &mut self.impulse
551    }
552}
553
554impl Default for ExternalAngularImpulse {
555    fn default() -> Self {
556        Self {
557            impulse: Torque::ZERO,
558            persistent: false,
559        }
560    }
561}
562
563impl ExternalAngularImpulse {
564    /// Zero external angular impulse.
565    pub const ZERO: Self = Self {
566        impulse: Torque::ZERO,
567        persistent: false,
568    };
569
570    /// Creates a new [`ExternalAngularImpulse`] component with a given `impulse`.
571    pub fn new(impulse: Torque) -> Self {
572        Self {
573            impulse,
574            ..default()
575        }
576    }
577
578    /// Sets the angular impulse.
579    pub fn set_impulse(&mut self, impulse: Torque) -> &mut Self {
580        **self = impulse;
581        self
582    }
583
584    /// Adds the given `impulse` to the angular impulse that will be applied.
585    pub fn apply_impulse(&mut self, impulse: Torque) -> &mut Self {
586        **self += impulse;
587        self
588    }
589
590    /// Determines if the angular impulse is persistent or if it should be automatically cleared every physics frame.
591    #[doc(alias = "clear_automatically")]
592    pub fn with_persistence(mut self, is_persistent: bool) -> Self {
593        self.persistent = is_persistent;
594        self
595    }
596
597    /// Returns the angular impulse.
598    pub fn impulse(&self) -> Torque {
599        self.impulse
600    }
601
602    /// Sets the angular impulse to zero.
603    pub fn clear(&mut self) {
604        self.impulse = Torque::ZERO;
605    }
606}