Skip to main content

soft_body_contacts

A soft-body collides through the collider covering its surface, which is a deformable triangle-mesh (a polyline in 2D) built from the template given to the builder.

Thickness​

The radius of the particles (the particleRadius field of R3SoftBodyDesc) is the thickness of the soft-body wrt. collision-detection: it is the contact skin of its surface collider, i.e., the distance kept between the surface and the objects touching it, as well as the distance the solver bounds the motion of one particle by at each substep. A radius that is too small relative to the distance between two neighboring particles may let thin objects pass through the surface, whereas a radius larger than that distance will make the body collide with itself even when it is at rest. Therefore it is recommended to keep it well below the distance between two neighboring particles. Note that every constructor picks a sensible default, i.e., about half the length of its edges or of its cells.

Oriented surfaces and shells​

A closed surface (a balloon, a jelly cube, a filled polygon) is oriented: its contacts are generated on its outward side only, like for an oriented triangle-mesh, so nothing is held inside it. An open surface (a rope, a cloth) is two-sided, because a body arriving from either side must be stopped. This is what the builder does by default, and it is what a solid body wants. A shell, i.e., a closed surface which inner side must hold the bodies contained in it, is obtained by asking for a surface that is not oriented (the oriented field of R3SoftBodyDesc):

// A shell: a closed surface that is not oriented, so its inner side holds the bodies put
// inside it (a bowl, a box, a container). A closed surface is oriented by default.
R2SoftBodyDesc bowl = r2DiskSoftBodyDesc(r2Vector(-3.0, 2.0), 0.8, 24);
// Default: disabled, i.e., oriented if the surface is closed.
bowl.oriented = (R2OptionalBool){1, 0};
bowl.material = r2UniformSoftBodyMaterial((R2SpringCoefficients){60.0, 1.0});
R2SoftBodyHandle bowl_handle = r2InsertSoftBody(world, &bowl);
note

After the insertion, the shape of the surface collider (given by r3SoftBody_MeshColliders) is the authority: the flag is changed there, like for any other collider.

Self-contacts​

A soft-body doesn't collide with itself by default. Self-contacts are enabled by the selfContacts field of R3SoftBodyDesc, which makes the vertices and the edges of the surface collide with the surface of their own body: this is what keeps a cloth folding onto itself, or a jelly squashed against itself, from passing through itself. Note that they are more expensive, since the whole surface must be tested against itself.

Penetrations and tangles​

The contacts between two meshes are computed triangle by triangle (segment by segment in 2D), without any notion of their interiors. As long as the two surfaces don't penetrate, this works well. But as soon as they do, some of these local contacts start pointing the wrong way, and actively keep the two surfaces in their penetrating state instead of separating them. Deformations make it worse, since a single surface can also cross itself and end up tangled:

Local contacts between penetrating meshes

Rapier handles these configurations by measuring the volume of the overlap between the two surfaces. The gradient of that volume gives a good approximation of the direction separating the two bodies, aka. the volume normal, which is used both to push the overlapping regions apart, and to correct the direction of the local contacts inside them:

Contact directions corrected with the volume normal

This is enabled by default for the closed surfaces, against other soft-bodies as well as against rigid colliders.

It is configured, along with the detection and the recovery of the tangled configurations, by the recovery settings of the global settings (softBodies.recovery of R3IntegrationParameters). Every mechanism can be switched off individually, and the table below lists the ones to look at for the most common problems:

ProblemWhat to change
Thin or fast objects pass through a surface.Raise the particle radius (particleRadius). Let the body request more substeps while it is hit fast (maxExtraSubsteps).
Two bodies crossing corner-first don't collide.Enable edgeSpeculation (note that it can leave pressed 3D piles crossed).
A body stays tangled with itself.Keep selfStandDown enabled (the default), which lets the elasticity untangle it, or push the crossed features apart with crossingRepulsion.
The recovery from a penetration is too slow, or too violent.Change the recoveryPace, i.e., the corrective speed allowed to the recovery (in length units per second).
Soft contacts feel too spongy.Raise the contactStiffening of the soft-body contacts relative to the rigid ones.
The overlap of two bodies isn't resolved at all.Make sure both surfaces are closed: the intersection-volume constraints (overlapConstraints) only apply to them.
info

Each of these settings has its own setter (and getter), named after its field: r3SoftBodiesSetMaxExtraSubsteps and r3SoftBodiesSetContactStiffening for the settings of the soft-bodies, and r3RecoverySetEdgeSpeculation, r3RecoverySetSelfStandDown, r3RecoverySetCrossingRepulsion, etc. for the recovery settings. See the global settings for an example.