Managing collisions
During each simulation step, Bullet performs collision detection in 2 phases: broadphase and narrowphase.
-
Broadphase enumerates pairs of objects in close proximity, based on overlaps between their axis-aligned bounding boxes (AABBs).
-
Narrowphase uses detailed collision shapes to test each pair found during broadphase, resulting in a list of manifolds where the shapes intersect.
Each manifold is composed of up to 4 contact points. Bullet’s rigid-body dynamics uses manifolds and contact points to implement contact response, including friction and restitution.
Minie provides mechanisms to:
-
count or enumerate overlaps,
-
customize which overlaps are handled and which are ignored,
-
access the manifolds and contact points, and
-
perform custom actions when Bullet creates or destroys a manifold or when it processes a contact point.
It also provides mechanisms:
-
to test for intersection between 2 collision objects or
-
to count or enumerate collision objects that intersect with:
-
a specific line segment,
-
a shape in a specific position, or
-
a shape sweeping from one position to another.
-
Such intersection tests are typically performed between simulation steps. They are useful (for instance) when you want to add a collision object to a space without causing an immediate collision.
Ghosts
A ghost is a collision object without contact response,
created solely to detect overlaps with other collision objects.
You can create a ghost directly by invoking the
PhysicsGhostObject
constructor.
In order to work, the ghost must be added to a space.
The constructor allows you to specify a collision shape. However, the details of the shape are unimportant. The key property of a ghost is its axis-aligned bounding box, which is determined by the ghost’s shape and position.
The AABBs generated by Bullet aren’t minimal. Approximations in Bullet make them somewhat larger than necessary. However, they are usually accurate enough to be useful. |
HelloGhost
is a simple application
that illustrates how a ghost could be used
to detect a character entering/leaving a box-shaped zone.
Things notice while running the app:
-
The ghost (in yellow) has a spherical shape, but its AABB (in white) is box-shaped.
-
The character (in pink) has a capsule shape. To clarify what’s going on, its AABB is outlined in white.
-
The ghost’s overlap count (displayed at the bottom of the window) is initially one, due to its overlap with the ground plane.
-
Press Right arrow to walk the character toward the ghost.
-
As soon as the character’s AABB touches the ghost’s AABB, the count increases to 2, even though their collision shapes haven’t intersected yet.
-
Press Space bar to jump.
-
The character can jump high enough to leave the ghost’s AABB, at which time the count will momentarily return to 1.
In addition the counting overlapping objects,
you can enumerate them using ghost.getOverlappingObjects()
.
The alternative to creating a ghost directly is to add a
GhostControl
to the scene graph.
Filtering AABB overlaps
You might want to prevent collisions from occurring between certain objects, perhaps under specific conditions. Filtering out an overlap during broadphase prevents collisions between the overlapping objects. Minie provides several mechanisms to implement such filtering.
The wheels of a PhysicsVehicle aren’t collision objects,
so these mechanisms don’t affect them.
|
Using collision groups
You can filter overlaps using collision groups. This is the most efficient filtering mechanism.
16 groups are defined,
and each collision object belongs to exactly one group.
By default, that group is COLLISION_GROUP_01
.
To assign an object to a different group,
invoke collisionObject.setCollisionGroup()
.
By default, collision objects collide only with objects in COLLISION_GROUP_01
.
To alter an object’s collides-with set,
invoke collisionObject.setCollideWithGroup()
.
For a collision to occur between objects X and Y, either X must collide with Y’s group OR Y must collide with X’s group.
Using ignore lists
You can filter AABB overlaps on a pair-by-pair basis by creating ignore lists for specific collision objects. Ignore lists are more flexible than collision groups, but less efficient.
Each collision object is created with an empty ignore list.
You can disable collisions between two objects X and Y by invoking
x.addToIgnoreList(y)
.
There’s no need to also invoke y.addToIgnoreList(x) .
That would be redundant.
|
Ignore lists are used internally by physics joints to disable collisions between the ends of a joint. |
Using a dynamic filter
For each collision group in a space, you can register a collision-group listener. Minie invokes the collision-group listeners for each AABB overlap that isn’t suppressed by collision groups or ignore lists.
You can dynamically filter AABB overlaps
by registering a listener that returns true
for overlaps that may
cause collisions and false
for those that should never cause collisions.
Collision-group listeners are the most flexible mechanism for filtering collisions.
Access to manifolds and contact points
The physicsSpace.countManifolds()
method
returns the number of contact manifolds in the space.
Each manifold has a native ID, as does each contact point.
-
The
physicsSpace.listManifoldIds()
method enumerates the IDs of all manifolds in the space. -
To obtain detailed information about a specific manifold, use the methods in
PersistentManifolds
. -
The
PersistentManifolds.listPointIds()
method enumerates the IDs of the contact points in a particular manifold. -
To obtain detailed information about a specific contact point, use the methods in
ManifoldPoints
.
A manifold may persist for a while after the bodies no longer intersect.
To confirm intersection,
use ManifoldPoints.getDistance1() to get the separation distance.
When the distance is positive, there’s no intersection.
|
ConveyorDemo
is a simple application
that implements conveyor belts using contact-point modification.
Collision/contact listeners
For each physics space, you can register 3 kinds of collision/contact listeners:
registration method | Listeners are invoked during… | for every… |
---|---|---|
|
|
contact created since the last |
|
|
contact point processed since the last |
|
|
contact created or removed and every contact point that is processed. |
BulletAppState invokes distributeEvents() during each update.
|
Intersection tests
Pair test
The space.pairTest()
method
performs a pair test between 2 collision objects,
returning true
if they intersect.
Although a space is required, the objects needn’t be added to any space. |
You can request a callback for each contact point that would be created if both collision objects were added to the space.
Ray test
The space.rayTest()
method performs a ray test against a space,
returning a list of objects in the space
that intersect with the specified line segment.
Unlike a mathematical ray, the "ray" used in a ray test has both a starting point and an ending point. |
To configure details of how ray tests are performed,
use the space.setRayTestFlags()
method.
Contact test
The contactTest()
method performs a contact test against a space,
returning the number of contact points that would be created
if a specified collision object were added to the space.
To obtain more information about the contacts, you can request a callback for each point.
Contact testing doesn’t detect contacts involving soft bodies. |
Summary
-
Overlaps, intersections, manifolds, and contact points are distinct concepts.
-
Minie provides filtering mechanisms to control which overlaps should be handled and which should be ignored.
-
Minie provides methods to enumerate overlaps, manifolds, and contact points.
-
You can trigger custom actions during each stage of collision processing.
-
Between simulation steps, you can perform pair tests, ray tests, contact tests, and sweep tests against a space.