Skip to main content

collider_collision_groups

The most efficient way of preventing some pairs of colliders from interacting with each other is to use collision groups or solver groups. Each collider is given:

  • A collision_groups for filtering what pair of colliders should have their contacts (or intersection test if at least one of the colliders is a sensor) computed by the narrow-phase. This filtering happens right after the broad-phase, at the beginning of the narrow phase.
  • A solver_groups for filtering what pair of colliders should have their contact forces computed. This filtering happens at the end of the narrow-phase, before the constraints solver.

In other words, the solver_groups is here to prevent contact forces from being computed between some colliders, whereas the collision_groups will also prevent the contact themselves (and contact events) from being computed. The collision_groups should be preferred most of the time because it skips more computations. The solver_groups is only useful if you really want the contact information to be computed but not the forces, for example so that you can apply your own forces based on these contacts.

A collision group or solver group is described as a pair of bit masks:

  • The groups membership indicates what groups the collider is part of (one bit per group).
  • The groups filter indicates what groups the collider can interact with (one bit per group).

The membership and filter are both 16-bit bit masks packed into a single 32-bits value. The 16 left-most bits contain the memberships whereas the 16 right-most bits contain the filter.

For example, let's say we want our collider A to be part of the groups [0, 2, 3] and to be able to interact with the groups [2], then its groups membership is 0b0000_0000_0000_1101 = 0x000D and its groups filter is 0b0000_0000_0000_0100 = 0x0004. The corresponding packed bit mask is 0x000D0004. The collision groups and solver groups of a collider can be set during or after its creation:

/* Set the collision groups and solver groups when the collider is created. */
let colliderDesc = RAPIER.ColliderDesc.ball(0.5)
.setCollisionGroups(0x000D0004)
.setSolverGroups(0x00500010);
let collider = world.createCollider(colliderDesc);
/* Set the collision groups and solver groups after the collider creation. */
collider.setCollisionGroups(0x000D0004);
collider.setSolverGroups(0x000D0004);

After the broad-phase detects that two colliders A and B may start being in contact, the narrow-phase will check the collision groups of both colliders to see if it needs to compute contacts. The check operates as follows:

  • If the collider A is not member of any collision group in the filter of B, then no contact is computed.
  • If the collider B is not member of any collision group in the filter of A, then no contact is computed.
  • The exact bit-wise check is the following:
   ((A.collisionGroups() >> 16) & (B.collisionGroups() & 0xffff)) != 0
&& ((B.collisionGroups() >> 16) & (A.collisionGroups() & 0xffff)) != 0

If this test succeeds, then the narrow-phase will compute the contacts. Then it will check the solver groups of both colliders, using the same kind of tests as described before but using the solver_groups instead of collision_groups. If the test succeeds then the constraints solver will compute forces for these contacts. Otherwise, it won't.