soft_body_forces_and_impulses
Forces and impulses can be applied to a soft-body as a whole
(SoftBodyExternalForce::force,
SoftBodyExternalImpulse::velocity_change),
or to one particular particle
(SoftBodyExternalForce::particle_forces,
SoftBodyExternalImpulse::particle_impulses).
A force added to the whole body is added to each of its free particles and is persistent, i.e., it keeps being applied
at each step until the forces are reset (i.e., until the SoftBodyExternalForce component
changes or is removed), exactly like the forces of
a rigid-body. An impulse applied to the whole body is a velocity change
applied to each of its free particles, so the body is kicked as a whole without being deformed. Note that the pinned
particles ignore both.
Two additional methods are provided for the effects which magnitude depends on the distance to a point: an impulse
applied within a radius
(apply_impulse_at_point), and a
radial blast pushing the particles away from its center
(apply_radial_impulse). In both
cases the impulse is scaled linearly down to zero at the given radius. Like for the rigid-bodies,
the last boolean argument of all these methods ensures the soft-body is
awake before the force or the impulse is applied:
The SoftBodyExternalForce and SoftBodyExternalImpulse components wake the soft-body up
automatically, and the impulses of the SoftBodyExternalImpulse component are reset to zero once they are applied. The
impulses depending on the distance to a point are applied to the Rapier soft-body of the entity directly:
- Example 2D
- Example 3D
fn apply_forces(
mut commands: Commands,
mut context: WriteRapierContext,
sheet: Single<Entity, With<Sheet>>,
) -> Result {
commands.entity(*sheet).insert((
// Persistent forces: applied at each step until the component changes or is removed.
SoftBodyExternalForce {
force: Vec2::new(0.0, 1.0),
particle_forces: vec![(3, Vec2::new(0.0, 1.0))],
},
// One-time impulses: applied (and reset to zero) at the next step.
SoftBodyExternalImpulse {
velocity_change: Vec2::new(0.0, 0.1),
particle_impulses: vec![(3, Vec2::new(0.0, 0.1))],
},
));
// The other impulses are applied to the Rapier soft-body directly. The `true` argument
// makes sure the soft-body is awake.
let mut context = context.single_mut()?;
if let Some(soft_body) = context.soft_body_mut(*sheet) {
// An impulse on the particles within 0.5 of a point, scaled down with the distance.
soft_body.apply_impulse_at_point(Vec2::new(0.0, 0.1), Vec2::new(-3.0, 3.0), 0.5, true);
// A blast pushing the particles away from a center.
soft_body.apply_radial_impulse(Vec2::new(-3.0, 3.0), 0.1, 1.0, true);
}
Ok(())
}
fn apply_forces(
mut commands: Commands,
mut context: WriteRapierContext,
cloth: Single<Entity, With<Cloth>>,
) -> Result {
commands.entity(*cloth).insert((
// Persistent forces: applied at each step until the component changes or is removed.
SoftBodyExternalForce {
force: Vec3::new(0.0, 1.0, 0.0),
particle_forces: vec![(3, Vec3::new(0.0, 1.0, 0.0))],
},
// One-time impulses: applied (and reset to zero) at the next step.
SoftBodyExternalImpulse {
velocity_change: Vec3::new(0.0, 0.1, 0.0),
particle_impulses: vec![(3, Vec3::new(0.0, 0.1, 0.0))],
},
));
// The other impulses are applied to the Rapier soft-body directly. The `true` argument
// makes sure the soft-body is awake.
let mut context = context.single_mut()?;
if let Some(soft_body) = context.soft_body_mut(*cloth) {
// An impulse on the particles within 0.5 of a point, scaled down with the distance.
soft_body.apply_impulse_at_point(
Vec3::new(0.0, 0.1, 0.0),
Vec3::new(0.0, 2.0, 0.0),
0.5,
true,
);
// A blast pushing the particles away from a center.
soft_body.apply_radial_impulse(Vec3::new(0.0, 2.0, 0.0), 0.1, 1.0, true);
}
Ok(())
}