An introduction to soft-body physics

While rope, cloth, and foam rubber can be simulated using many small rigid bodies, it is more convenient and efficient to treat them as individual bodies that can be deformed. To this end, Libbulletjme supports simulation of soft bodies in a manner roughly analogous to rigid bodies:

PhysicsSoftSpace is a subclass of PhysicsSpace. It implements soft-body physics in addition to all the features of an ordinary PhysicsSpace (such as rigid bodies).

The abstract class PhysicsBody is a superclass of both PhysicsRigidBody and PhysicsSoftBody. It provides access to properties that rigid bodies and soft bodies have in common, such as gravity, location, mass, and joints.

Soft bodies can collide with both rigid bodies and other soft bodies. They can also be joined to bodies of both types, using special subclasses of PhysicsJoint.

A comparison of soft bodies and rigid bodies

Unlike a rigid body, a soft body doesn’t have a CollisionShape or an orientation. Instead, it is composed of point masses (called "nodes") whose locations are specified in physics-space coordinates. A soft body’s shape, structure, mass distribution, and position are all defined by its mesh of nodes:

  • To simulate rope, nodes can be connected in pairs (called links).

  • To simulate cloth, nodes can be connected to form triangles (called faces).

  • To simulate foam rubber, nodes can be connected to form tetrahedra (also called tetras).

Unlike a rigid body, the physics location of a soft body is not its center of mass, but rather the center of its axis-aligned bounding box.

Like rigid bodies, soft bodies have collision margins. However, since a soft body lacks a CollisionShape, different accessors are used:

float oldMargin = softBody.margin();
softBody.setMargin(0.1f);

Soft bodies lack many other features of rigid bodies, including:

  • motion state (for extrapolating between simulation steps),

  • deactivation/sleeping (for efficient simulation), and

  • continuous collision detection (CCD) (for fast-moving objects).

Constructing a soft body

To construct a soft body, start with the no-argument constructor:

PhysicsSoftBody softBody = new PhysicsSoftBody()

This produces an empty body (one without any nodes, links, faces, tetras, or joints) that isn’t added to any physics space.

Methods are provided to append nodes, links, and faces to a soft body. However, it’s often more convenient to generate a Mesh with the desired shape and topology and append it to the body using a utility method:

  • NativeSoftBodyUtil.appendFromTriMesh() to append nodes and faces from a mesh composed of triangles

  • NativeSoftBodyUtil.appendFromLineMesh() to append nodes and links from a mesh composed of lines

Be aware that meshes intended for graphics rendering often prove unsuitable for soft-body simulation. For instance, they may define multiple vertices at the same position or their edges/faces may be insufficiently subdivided.

Soft-body configuration and pose matching

Each soft body has numerous properties that can affect its behavior. Most of these are stored in its configuration object, which can be accessed using getSoftConfig(). Soft bodies and configuration objects are one-to-one.

Configuration properties with float values are enumerated by the Sbcp ("soft-body configuration parameter") enum. For instance, a soft body can have a preferred shape (called its "default pose") that it tends to return to when deformed. The strength of this tendency depends on the configuration object’s "pose matching" parameter, which defaults to zero.

For a simple example of a soft body, see HelloSoftBody.

Soft-soft collisions

By default, collisions between soft bodies are not handled (ignored). One way to handle soft-soft collisions for a specific body is to set the VF_SS collision flag in its configuration object:

SoftBodyConfig config = softBody.getSoftConfig();
int oldFlags = config.getCollisionFlags();
config.setCollisionFlags(oldFlags, ConfigFlag.VF_SS);

For a simple example of a collision between 2 soft bodies, see HelloSoftSoft.

Solver iterations

During each simulation step, Bullet applies a series of iterative solvers to each soft body:

  • a cluster solver

  • a drift solver

  • a position solver

  • a velocity solver

The number of iterations for each solver is stored in the body’s configuration object. When simulating collisions, you can often improve accuracy by increasing the number of position-solver iterations:

SoftBodyConfig config = softBody.getSoftConfig();
config.setPositionIterations(numIterations);  // default=1

Stiffness coefficients

Each soft body has 3 stiffness coefficients. These are stored in its "material" object, which can be accessed using getSoftMaterial(). Soft bodies and their material objects are one-to-one.

To simulate an object that flexes easily (such as cloth), create a soft body with many faces and set its angular-stiffness coefficient to a small value (such as zero):

PhysicsSoftBody.Material softMaterial = softBody.getSoftMaterial();
softMaterial.setAngularStiffness(0f); // default=1

For a simple example of cloth simulation, see HelloCloth.

Mass distribution

When a node is appended to a soft body, it has mass=1. To alter the mass of a pre-existing node, use the setNodeMass() method:

softBody.setNodeMass(nodeIndex, desiredMass);

You can also alter the total mass of a soft body, distributing the mass across the pre-existing nodes in various ways:

  • in proportion to the current mass of each node, using setMassByCurrent(),

  • in proportion to the area of adjacent faces, using setMassByArea(), or

  • in a custom fashion, using setMasses().

softBody.setMass() is equivalent to setMassByCurrent().

If a soft-body node has mass=0, it becomes pinned (immovable, like a static rigid body).

For a simple example of a pinned node, see HelloPin.java.

Simulating a rope

HelloSoftRope is a SPORT app that demonstrates one way to simulate rope using a soft body.

TODO: applying forces, anchors, soft joints, world info

Aerodynamics

HelloWind is a SPORT app that simulates the effect of wind on a flag.

Things notice while running the app:

  1. The flag is a piece of cloth with 2 of its corners pinned.

  2. Wind direction is indicated by the white arrow.

  3. Initially, the wind blows from left to right.

  4. Press kbd:[Left arrow] and kbd:[Right arrow] to alter the wind direction.

Clusters

By default, soft-body collisions are handled using nodes and faces. As an alternative, they can be handled using groups of connected nodes (called "clusters"). To enable cluster-based rigid-soft collisions for a specific soft body, set its CL_RS collision flag. To enable cluster-based soft-soft collisions, set its CL_SS flag.

Clusters can overlap, but they can’t span multiple bodies. In other words, a single node can belong to multiple clusters, but a single cluster can’t contain nodes from multiple bodies.

When a soft body is created, it doesn’t have any clusters. Once nodes are appended to a body, clusters can be generated automatically, using an iterative algorithm that’s built into Bullet:

softBody.generateClusters(k, numIterations);

Summary

  • Soft bodies are a convenient and efficient way to simulate objects that can be deformed.