avian2d/dynamics/rigid_body/forces/
plugin.rs1use crate::{
2 dynamics::{
3 integrator::{
4 self, CustomVelocityIntegration, IntegrationSystems, VelocityIntegrationData,
5 },
6 solver::{
7 SolverDiagnostics,
8 solver_body::{SolverBody, SolverBodyInertia},
9 },
10 },
11 prelude::*,
12};
13use bevy::prelude::*;
14
15use super::AccumulatedLocalAcceleration;
16
17pub struct ForcePlugin;
21
22impl Plugin for ForcePlugin {
23 fn build(&self, app: &mut App) {
24 app.configure_sets(
26 PhysicsSchedule,
27 (
28 ForceSystems::ApplyConstantForces
29 .in_set(IntegrationSystems::UpdateVelocityIncrements)
30 .before(integrator::pre_process_velocity_increments),
31 ForceSystems::Clear.in_set(SolverSystems::PostSubstep),
32 ),
33 );
34 app.configure_sets(
35 SubstepSchedule,
36 ForceSystems::ApplyLocalAcceleration
37 .in_set(IntegrationSystems::Velocity)
38 .before(integrator::integrate_velocities),
39 );
40
41 app.add_systems(
43 PhysicsSchedule,
44 (
45 apply_constant_forces,
46 apply_constant_torques,
47 apply_constant_linear_acceleration,
48 apply_constant_angular_acceleration,
49 apply_constant_local_forces,
50 #[cfg(feature = "3d")]
51 apply_constant_local_torques,
52 apply_constant_local_linear_acceleration,
53 #[cfg(feature = "3d")]
54 apply_constant_local_angular_acceleration,
55 )
56 .chain()
57 .in_set(ForceSystems::ApplyConstantForces),
58 );
59
60 app.add_systems(
63 SubstepSchedule,
64 apply_local_acceleration.in_set(ForceSystems::ApplyLocalAcceleration),
65 );
66
67 app.add_systems(
69 PhysicsSchedule,
70 clear_accumulated_local_acceleration.in_set(ForceSystems::Clear),
71 );
72 }
73}
74
75#[derive(SystemSet, Clone, Copy, Debug, PartialEq, Eq, Hash)]
77pub enum ForceSystems {
78 #[cfg_attr(
80 feature = "2d",
81 doc = "to [`VelocityIntegrationData`], and [`ConstantLocalForce`] and [`ConstantLocalLinearAcceleration`]"
82 )]
83 #[cfg_attr(
84 feature = "3d",
85 doc = "to [`VelocityIntegrationData`], and [`ConstantLocalForce`], [`ConstantLocalTorque`], [`ConstantLocalLinearAcceleration`], and [`ConstantLocalAngularAcceleration`]"
86 )]
87 ApplyConstantForces,
89 ApplyLocalAcceleration,
91 Clear,
93}
94
95fn apply_constant_forces(
97 mut bodies: Query<(&mut VelocityIntegrationData, &ComputedMass, &ConstantForce)>,
98) {
99 bodies
100 .iter_mut()
101 .for_each(|(mut integration, mass, constant_force)| {
102 integration.linear_increment += mass.inverse() * constant_force.0;
103 })
104}
105
106fn apply_constant_torques(
108 mut bodies: Query<(
109 &mut VelocityIntegrationData,
110 &SolverBodyInertia,
111 &ConstantTorque,
112 )>,
113) {
114 bodies
115 .iter_mut()
116 .for_each(|(mut integration, inertia, constant_torque)| {
117 integration.angular_increment +=
118 inertia.effective_inv_angular_inertia() * constant_torque.0;
119 })
120}
121
122fn apply_constant_linear_acceleration(
124 mut bodies: Query<(&mut VelocityIntegrationData, &ConstantLinearAcceleration)>,
125) {
126 bodies
127 .iter_mut()
128 .for_each(|(mut integration, constant_acceleration)| {
129 integration.linear_increment += constant_acceleration.0;
130 })
131}
132
133fn apply_constant_angular_acceleration(
135 mut bodies: Query<(&mut VelocityIntegrationData, &ConstantAngularAcceleration)>,
136) {
137 bodies
138 .iter_mut()
139 .for_each(|(mut integration, constant_acceleration)| {
140 integration.angular_increment += constant_acceleration.0;
141 })
142}
143
144fn apply_constant_local_forces(
146 mut bodies: Query<(
147 &mut AccumulatedLocalAcceleration,
148 &ComputedMass,
149 &ConstantLocalForce,
150 )>,
151) {
152 bodies
153 .iter_mut()
154 .for_each(|(mut acceleration, mass, constant_force)| {
155 acceleration.linear += mass.inverse() * constant_force.0;
156 })
157}
158
159#[cfg(feature = "3d")]
161fn apply_constant_local_torques(
162 mut bodies: Query<(
163 &mut AccumulatedLocalAcceleration,
164 &ComputedAngularInertia,
165 &ConstantLocalTorque,
166 )>,
167) {
168 bodies
169 .iter_mut()
170 .for_each(|(mut acceleration, angular_inertia, constant_torque)| {
171 acceleration.angular += angular_inertia.inverse() * constant_torque.0;
172 })
173}
174
175fn apply_constant_local_linear_acceleration(
177 mut bodies: Query<(
178 &mut AccumulatedLocalAcceleration,
179 &ConstantLocalLinearAcceleration,
180 )>,
181) {
182 bodies
183 .iter_mut()
184 .for_each(|(mut acceleration, constant_acceleration)| {
185 acceleration.linear += constant_acceleration.0;
186 })
187}
188
189#[cfg(feature = "3d")]
191fn apply_constant_local_angular_acceleration(
192 mut bodies: Query<(
193 &mut AccumulatedLocalAcceleration,
194 &ConstantLocalAngularAcceleration,
195 )>,
196) {
197 bodies
198 .iter_mut()
199 .for_each(|(mut acceleration, constant_acceleration)| {
200 acceleration.angular += constant_acceleration.0;
201 })
202}
203
204fn apply_local_acceleration(
208 mut bodies: Query<
209 (&mut SolverBody, &AccumulatedLocalAcceleration, &Rotation),
210 Without<CustomVelocityIntegration>,
211 >,
212 mut diagnostics: ResMut<SolverDiagnostics>,
213 time: Res<Time<Substeps>>,
214) {
215 let start = crate::utils::Instant::now();
216
217 let delta_secs = time.delta_secs_f64() as Scalar;
218
219 bodies
220 .iter_mut()
221 .for_each(|(mut body, acceleration, rotation)| {
222 let rotation = body.delta_rotation * *rotation;
223 let locked_axes = body.flags.locked_axes();
224
225 let world_linear_acceleration =
227 locked_axes.apply_to_vec(rotation * acceleration.linear);
228 #[cfg(feature = "3d")]
229 let world_angular_acceleration =
230 locked_axes.apply_to_vec(rotation * acceleration.angular);
231
232 body.linear_velocity += world_linear_acceleration * delta_secs;
234 #[cfg(feature = "3d")]
235 {
236 body.angular_velocity += world_angular_acceleration * delta_secs;
237 }
238 });
239
240 diagnostics.integrate_velocities += start.elapsed();
241}
242
243fn clear_accumulated_local_acceleration(mut query: Query<&mut AccumulatedLocalAcceleration>) {
244 query.iter_mut().for_each(|mut acceleration| {
245 acceleration.linear = Vector::ZERO;
246 #[cfg(feature = "3d")]
247 {
248 acceleration.angular = Vector::ZERO;
249 }
250 });
251}