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}