Class Diagram

- CollisionManager: A member of every scene and responsible for tracking and performing all Collision tests, through a list of CollidableGroups and CollisionTestCommands.
- Collidable: The class that contains all the functionality for collision. Is what all GameObjects that want to have collision need to extend.
- CollisionTestCommand: Contains the logic for performing collision tests as well as the CollidableGroups it will be testing and the CollisionDIspatch it will use to callback. Created by the CollisionManager.
- CollidableGroup: A container for all the registered Collidables.
- CollisionVolume: An abstract class that all CollisionVolumes extend from. Contains all the information necessary to perform collision tests.
- CollisionDispatchProxy: A Proxy class used to callback to the users Collision functions. A proxy is used to hide the templates from the CollisionTestCommands and kick the responsibility for casting from the Collidables to the templated class off to the implemented CollisionDispatch.
Tiered Tests
My collision system uses a tiered testing system which avoids performing the more costly collision tests until the cheaper ones have passed.

// CollisionPairTestCmd.cpp
// ...
// Test Group Volumes
if (!EngineMath::Intersect(CollectionVolume1, CollectionVolume2))
return;
// ...
// Test Collidable1's primitive volume against CollidableGroup2's group volume
if (EngineMath::Intersect(CollectionVolume2, pPrimVol1)) {
// ...
// Test Collidable2's primitive volume against CollidableGroup1's group volume
if (EngineMath::Intersect(CollectionVolume1, pPrimVol2)) {
// ...
// Test Collidable1's primitive volume against Collidable2's primitive volume
if (EngineMath::Intersect(pPrimVol1, pPrimVol2)) {
// ...
// Test The Actual Collision Volumes
if (EngineMath::Intersect(pColVol1, pColVol2))
pDispatch->ProcessCallbacks(*it1, *it2); // If The Objects Intersect, Process The Callbacks
// ...
}
// ...
}
// ...
}
// ...
// CollisionManager.cpp
// In ProcessCollisions() Which is called every frame
// Update the collidable groups AABB
for (unsigned int i = 0; i < this->ColGroupCollection.size(); i++) {
// Some Collidable Groups may be empty
if (this->ColGroupCollection[i] != nullptr)
this->ColGroupCollection[i]->UpdateGroupColData();
}
// Run all the tests
for (CollisionTestCommands::iterator it = colTestCommands.begin(); it != colTestCommands.end(); it++)
(*it)->Execute();
As you can see above, the CollisionManager updates the group collision volumes every frame before running the collision tests. It does so using the primitive Bsphere volume of each Collidable. Finding the Max/Min of the entire group using the center and radius of each one.
The collision tests themselves are your basic geometric collision tests, however, you’ll notice they are all abstracted away using a Visitor pattern, and a function call to EngineMath. The visitor pattern allows us to abstract away the different volumes in the tests, while the EngineMath class compartmentalizes the math behind the code to make testing and such much easier.
This system allows for scenes like this one from my game TANKS to run smoothly despite the MANY collision tests being run.
