Choosing collision shapes

A collision shape describes the shape and size of a physics object such as a rigid body.

The 18 shape classes

The examples so far have all used spheres, cubes, and/or cylinders. However, those are but 3 of the 18 concrete subclasses of Shape.

The subclasses are summarized here, in lexicographic order, with illustrations and lists of key properties (explained below):

1. BoxShape

→ convex with convex radius
→ movable

box

2. CapsuleShape

→ convex without convex radius
→ movable

capsule

3. ConvexHullShape

→ convex with convex radius
→ movable

convexHull

4. CylinderShape

→ convex with convex radius
→ movable

cylinder

5. EmptyShape

→ non-convex
→ movable
→ used as a placeholder

(no image)

6. HeightfieldShape

→ used to simulate terrain efficiently
→ may contain holes
→ non-convex
→ must be static

heightField

7. MeshShape

→ non-convex
→ must be static
→ costly to simulate

mesh

8. MutableCompoundShape

→ compound (non-convex)
→ movable if all children are movable

compound

9. OffsetCenterOfMassShape

→ decorated (non-convex)
→ movable if inner shape is movable

ocoms

10. PlaneShape

→ non-convex
→ must be static

plane

11. RotatedTranslatedShape

→ decorated (non-convex)
→ movable if inner shape is movable

rotatedTranslated

12. ScaledShape

→ decorated (non-convex)
→ movable if inner shape is movable

(no image)

13. SoftBodyShape

→ non-convex
→ applies only to soft bodies, not rigid ones

(no image)

14. SphereShape

→ convex without convex radius
→ movable

sphere

15. StaticCompoundShape

→ compound (non-convex)
→ movable if all children are movable

compound

16. TaperedCapsuleShape

→ convex without convex radius
→ movable

taperedCapsule

17. TaperedCylinderShape

→ convex with convex radius
→ movable

taperedCylinder

18. TriangleShape

→ convex with convex radius
→ movable

triangle

Creating shapes

While simple shapes like boxes and spheres can be instantiated directly, some shapes can only be created using a settings object. For instance, to instantiate a ConvexHullShape, you must use a ConvexHullShapeSettings object:

ConvexHullShapeSettings settings = new ConvexHullShapeSettings(points);
ShapeResult result = settings.create();
assert result.isValid();
ShapeRefC ref = result.get();
ConvexHullShape shape = (ConvexHullShape) ref.getPtr();

Decorated and compound

A decorated shape is derived from a pre-existing inner shape. For instance, you can create spheres with off-center mass by applying OffsetCenterOfMassShape to ordinary spheres.

A compound shape combines any number of pre-existing child shapes into a single shape:

  • A MutableCompoundShape allows child shapes to be added or removed from after the compound is created.

  • A StaticCompoundShape prohibits such modifications.

Convex versus non-convex

The convex collision-shape classes are those that guarantee the convex property: for any 2 locations inside a shape, the line segment connecting those locations lies entirely inside the shape.

To test whether a shape belongs to a convex class:

boolean convexClass = (shape instanceof ConvexShape);
// or
boolean convexClass = (shape.getType() == EShapeType.Convex);
In Jolt JNI, "convex" is a property of classes, not objects. While specific instances of non-convex classes possess the convex property, those classes don’t guarantee it for all instances.

Convex radius

Convex radius is a property found only in convex shapes with sharp edges and/or corners.

To speed up collision detection, Jolt Physics rounds off edges and corners. The geometrical shape is first shrunk by the convex radius, then inflated again by the same amount.

For boxes, cylinders, tapered cylinders, and triangles, convex radius limits the minimum size of shapes. For such shapes, the radius defaults to 5 centimeters. To create very small shapes of this sort, it may be necessary override the default value.

For convex hulls, the default convex radius depends on the vertices used to construct the shape.

Choosing a shape

For efficient simulation, the general rule is: "Use the simplest shape that yields the desired behavior." Focusing on behavior (rather than appearance) helps you avoid simulating details that don’t matter. For instance:

  • A character’s hair should probably be omitted from their collision shape.

  • Any small object that only encounters large, flat surfaces can probably be approximated by a convex hull.

  • As long as a container remains sealed, its collision shape need not be hollow.

Mesh shapes, which support the greatest detail, cannot be used in movable bodies. If you need to simulate a moving mesh, first try approximating the mesh with a convex shape. For meshes that cannot be approximated this way (due to bends, holes, indentations, or steep protrusions) the fallback is to decompose the mesh into a small number of convex shapes that, when compounded together, approximate the desired behavior.

Depending how much you know about a mesh, there are various approaches to decomposing it:

  • If the mesh is generated procedurally, it may be convenient to decompose it during the generation process.

  • If the mesh was crafted in a tool such as Blender, it may be practical to manually decompose it there, into sub-meshes that are convex or nearly so.

  • As a last resort, you can decompose any mesh into triangle shapes, though the resulting compound shape may be expensive to simulate.

Automated decomposition

For situations where other decomposition approaches are impractical, Jolt JNI incorporates Khaled Mamou’s Volumetric-Hierarchical Approximate Convex Decomposition (V-HACD) algorithm. V-HACD makes it easy to decompose a 3-D mesh of triangles into a compound of convex-hull shapes:

import com.github.stephengold.joltjni.vhacd.ConvexHull;
import com.github.stephengold.joltjni.vhacd.Decomposer;
import com.github.stephengold.joltjni.vhacd.Parameters;

// ...

float[] locationArray = /* vertex locations in the mesh ... */
int[] indexArray = /* vertex indices in the mesh ... */
Decomposer decomposer = new Decomposer();
Parameters tuningParameters = new Parameters();
Collection<ConvexHull> hulls
        = decomposer.decompose(locationArray, indexArray, tuningParameters);
StaticCompoundShapeSettings compoundSettings
        = new StaticCompoundShapeSettings();
compoundSettings.addHulls(hulls);

Summary

  • Jolt JNI provides 18 types of collision shapes, ranging from the trivial EmptyShape to the detail-oriented MeshShape.

  • Collision-shape instances classified as "non-convex" may still exhibit the convex property.

  • Most convex shapes incorporate a convex radius to round off the corners.

  • Use the simplest shape that yields the desired behavior.

  • For moving bodies, mesh shapes can be approximated by compounds of convex shapes, such as convex hulls.