Skip to main content

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:

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(())
}