Tutorials » Physics » How to apply collision filters

A Collision Filter allows a 3D object to collide with some objects, but not with others.

For example, let's say that you want the astronaut to collide with the island, but not with the lunar module. Moreover, you also want the lunar module to only collide with the island, but not with the island.

Image

How would you set this restriction?

You would set the restriction through the use of Collision Filters. Collision Filters use the Collision Category and Collision Masks properties of an entity to determine with whom to collide.

Here is a nice way to remember what a Category and Mask means:

-Collision Categories means: I am of type...
-Collision Masks means: I collide with...

The Untold Engine provides a mechanism to set collision categories and masks using the U4DEngine::U4DStaticModel::setCollisionFilterCategory and U4DEngine::U4DStaticModel::setCollisionFilterMask methods, respectively.

Let's go through an example:

Step 1. Declare bitflags for Filtering

To use the Collision Filters, we need to declare bitflags as shown below. These bitflags will be used in the Category and Masks settings.

typedef enum{
    kAstronaut=0x0002, 
    kLunarModule=0x0004,
    kIsland=0x0008,
    kNegativeGroupIndex=-10,
    kPositiveGroupIndex=10,
    kZeroGroupIndex=0,
}GameEntityCollision;

Note: Collision Filtering only works with bitflags, not with Integers.

Step 2. Set the Collision Categories & Masks

Let's inform the Untold Engine the collision types of each entity in the game.

Astronaut

The astrounaut is of type kAstronaut and should only collide with types kIsland, thus:

//set collision filter category...I am of type kAstronaut
myAstronaut->setCollisionFilterCategory(kAstronaut);

//set collision filter mask...I collide with kIsland
myAstronaut->setCollisionFilterMask(kIsland);
Lunar Module

The Lunar Module is of type kLunarModule and should only collide with types kIsland, thus:

//set collision filter category...I am of type kLunarModule
lunarModule->setCollisionFilterCategory(kLunarModule);

//set collision filter mask...I collide with kIsland
lunarModule->setCollisionFilterMask(kIsland);
Island

The island is of type kIsland and should collide with both types: kAstronaut and kLunarModule, thus:

//set collision filter category...I am of type kIsland
island->setCollisionFilterCategory(kIsland);

//set collision filter mask...I collide with kAstronaut & kLunarModule
island->setCollisionFilterMask(kAstronaut|kLunarModule);

The setting above would result in both the Astronaut and Lunar Module able to collide with the island, but not with each other, as shown below:

Image

Group Index

Group Index provide finer control over the collision filtering and can overwrite the Category/Mask rule mentioned above.

Group Index follows the following rule:

-if either fixture has a groupIndex of zero, use the category/mask rules as above
-if both groupIndex values are non-zero but different, use the category/mask rules as above
-if both groupIndex values are the same and positive, collide
-if both groupIndex values are the same and negative, don't collide

For example, if you set the group index for the astronaut and lunar module to a positive value, the category/mask rule will be ignored, and all entities will collide among themselves.

The Untold Engine provides a mechanism to set collision group index using the following method U4DEngine::U4DStaticModel::setCollisionFilterGroupIndex.

Here is an example:

//set the Collision Group index for both entities to a positive value.
myAstronaut->setCollisionFilterGroupIndex(kPositiveGroupIndex);
lunarModule->setCollisionFilterGroupIndex(kPositiveGroupIndex);

Here is the result:

Image

Tip

  • When using the Collision filters. The categories must be defined as bitflags, i.e. 0x0002, 0x0004, 0x0008, 0x0010, etc. The group index must be defined as signed integers.