Collision Things

From Physics Simulation Wiki

Jump to: navigation, search


Warning/TODO: this is unverified documentation

refer to [Collision Filtering] page for more information[1]

Collision Filtering

Selective collisions

Bullet provides two easy ways to ensure that only certain objects collide with each other: masks, and nearcallbacks.

It is worth noting that mask-based collision selection happens a lot further up the toolchain than the nearcallback does. In short, if masks are sufficient for your purposes, use them; they perform better and are a lot simpler to use.

Of course, don't try to shoehorn something into a mask-based selection system that clearly doesn't fit there just because performance may be a little better. caveat emptor

Filtering collisions using masks

Bullet supports bitwise masks as a way of deciding whether or not things should collide with other things, or receive collisions.

For example, in a spaceship game, you could have your spaceships ignore collisions with other spaceships [the spaceships would just fly through each other], but always collide with walls [the spaceships always bounce off walls].

Your spaceship needs a callback when it collides with a wall [for example, to produce a “plink” sound], but the walls do nothing when you collide with them so they do not need to receive callbacks.

A third type of object, “powerup”, collides with walls and spaceships. Spaceships do not receive collisions from them, since we don't want the trajectory of the spaceship changed by collecting a powerup. The powerup object modifies the spaceship from its own collision callback.

In order to do this, you need a bit mask for the walls, spaceships, and powerups:

#define BIT(x) (1<<(x))
enum collisiontypes {
    COL_NOTHING = 0, //<Collide with nothing
    COL_SHIP = BIT(1), //<Collide with ships
    COL_WALL = BIT(2), //<Collide with walls
    COL_POWERUP = BIT(3) //<Collide with powerups

int shipCollidesWith = COL_WALL;
int wallCollidesWith = COL_NOTHING;
int powerupCollidesWith = COL_SHIP | COL_WALL;

After setting these up, simply add your body objects to the world as normal, except as the second and third parameters pass your collision type for that body, and the collision mask.

If you are not using a recent enough version of Bullet, you may find this overload of addRigidBody does not exist. In this case, use btDynamicsWorld::addCollisionObject instead of the more usual btDynamicsWorld::addRigidBody. You may have to set the gravity on the rigid body manually in this case.

btRigidBody ship; // Set up the other ship stuff
btRigidBody wall; // Set up the other wall stuff
btRigidBody powerup; // Set up the other powerup stuff

mWorld->addRigidBody(ship, COL_SHIP, shipCollidesWith);
mWorld->addRigidBody(wall, COL_WALL, wallCollidesWith);
mWorld->addRigidBody(powerup, COL_POWERUP, powerupCollidesWith);

Filtering Collisions Using a Custom NearCallback

It's worth noting that if you are using masks, and they're sufficient for your needs, then you do not need a custom nearCallback.

If you have more types of objects than bits available to you in the masks above, or some collisions are enabled or disabled based on other factors, then you need to add a different nearCallback that implements this logic and only passes on collisions that are the ones you want:

void MyNearCallback(btBroadphasePair& collisionPair,
  btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) {

    // Do your collision logic here
    // Only dispatch the Bullet collision information if you want the physics to continue
    dispatcher.defaultNearCallback(collisionPair, dispatcher, dispatchInfo);

Personal tools