Well, in bullet user manual, you could find this:
Filtering Collisions Using a Broadphase Filter Callback
One efficient way is to register a broadphase filter callback. This callback is called at a very early stage in the collision pipeline, and prevents collision pairs from being generated.
Code:
struct YourOwnFilterCallback : public btOverlapFilterCallback {
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const {
} };
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
//add some additional logic here that modified 'collides' return collides;
And then create an object of this class and register this callback using:
Code:
btOverlapFilterCallback * filterCallback = new YourOwnFilterCallback(); dynamicsWorld->getPairCache()->setOverlapFilterCallback(filterCallback);
I thought that you could register all the callback that you desire. Well, that's wrong thinking. You can only register
ONE callback in bullet world.
Solution?: the one I mentioned above. Implementing your own broadPhaseCollision Dispatcher. I'm going to paste my code, but is specific of my game:
//PhysicFilterCallback.h
Code:
class PhysicFilterCallback : public btOverlapFilterCallback
{
public:
PhysicFilterCallback();
~PhysicFilterCallback();
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
void SetOverlapFilterCallback();
private:
std::map<btCollisionObject *,int> _objectsColliding;
std::map<btCollisionObject *,int>::iterator _it;
bool _colCharacterTrigger;
bool _colCharacterCharacter;
};
//PhysicFilterCallback.cpp
Code:
PhysicFilterCallback::PhysicFilterCallback() : _colCharacterTrigger(false), _colCharacterCharacter(false)
{
}
PhysicFilterCallback::~PhysicFilterCallback()
{
_objectsColliding.clear();
}
void PhysicFilterCallback::SetOverlapFilterCallback()
{
//Registrando el callback en el mundo fisico de bullet.
CServer::getSingletonPtr()->getScene()->GetbtDiscreteDynamicWorld()->getPairCache()->setOverlapFilterCallback(this);
}
bool PhysicFilterCallback::needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
btCollisionObject* objTrigger = NULL;
btCollisionObject* objCharacter0 = NULL;
btCollisionObject* objCharacter1 = NULL;
btBroadphaseProxy* proxyTrigger = NULL;
btBroadphaseProxy* proxyChart0 = NULL;
btBroadphaseProxy* proxyChart1 = NULL;
//Colision entre trigger y character.
if (proxy0->m_collisionFilterGroup == btBroadphaseProxy::CharacterFilter &&
proxy1->m_collisionFilterGroup == btBroadphaseProxy::SensorTrigger)
{
objCharacter0 = (btCollisionObject*)proxy0->m_clientObject;
proxyChart0 = proxy0;
objTrigger = (btCollisionObject*)proxy1->m_clientObject;
proxyTrigger = proxy1;
_colCharacterTrigger = true;
}
else if (proxy1->m_collisionFilterGroup == btBroadphaseProxy::CharacterFilter &&
proxy0->m_collisionFilterGroup == btBroadphaseProxy::SensorTrigger)
{
objCharacter0 = (btCollisionObject*)proxy1->m_clientObject;
proxyChart0 = proxy1;
objTrigger = (btCollisionObject*)proxy0->m_clientObject;
proxyTrigger = proxy0;
_colCharacterTrigger = true;
}
//Colsion entre character y character.
else if (proxy1->m_collisionFilterGroup == btBroadphaseProxy::CharacterFilter &&
proxy0->m_collisionFilterGroup == btBroadphaseProxy::CharacterFilter)
{
objCharacter0 = (btCollisionObject*)proxy0->m_clientObject;
proxyChart0 = proxy0;
objCharacter1 = (btCollisionObject*)proxy1->m_clientObject;
proxyChart1 = proxy1;
_colCharacterCharacter = true;
}
if ( _colCharacterCharacter ) //Character -> Character
{
//Obteniendo la parte logica del character0.
TActorInfo *infoChart0 = (TActorInfo *)(objCharacter0->getUserPointer());
assert(infoChart0 != NULL && "No se ha encontrado UserData asociada al objetos fisico de bullet");
Logic::CPhysicEntity *physicCharacter0 = reinterpret_cast<Logic::CPhysicEntity*> (infoChart0->pPhysicObj->userData);
Logic::CEntity *logicCharacter0 = physicCharacter0->getEntity();
TActorInfo *infoChart1 = (TActorInfo *)(objCharacter1->getUserPointer());
assert(infoChart1 != NULL && "No se ha encontrado UserData asociada al objetos fisico de bullet");
Logic::CPhysicEntity *physicCharacter1 = reinterpret_cast<Logic::CPhysicEntity*> (infoChart1->pPhysicObj->userData);
Logic::CEntity *logicCharacter1 = physicCharacter1->getEntity();
//Invocacion mediante polimorfismo.
}
else if ( _colCharacterTrigger ) //Character -> Trigger
{
//Obteniendo la parte logica del trigger.
TActorInfo *infoTrigger = (TActorInfo *)(objTrigger->getUserPointer());
assert(infoTrigger != NULL && "No se ha encontrado UserData asociada al objetos fisico de bullet");
Logic::CManualTrigger *physicTrigger = reinterpret_cast<Logic::CManualTrigger*> (infoTrigger->pPhysicObj->userData);
Logic::CEntity *logicTrigger = physicTrigger->getEntity();
//Obteniendo la parte logica del character0.
TActorInfo *infoChart0 = (TActorInfo *)(objCharacter0->getUserPointer());
assert(infoChart0 != NULL && "No se ha encontrado UserData asociada al objetos fisico de bullet");
Logic::CPhysicEntity *physicCharacter0 = reinterpret_cast<Logic::CPhysicEntity*> (infoChart0->pPhysicObj->userData);
Logic::CEntity *logicCharacter0 = physicCharacter0->getEntity();
//using polimorphysm.
physicTrigger->needBroadphaseCollision(logicTrigger, proxyTrigger, logicCharacter0, proxyChart0);
}
_colCharacterCharacter = _colCharacterTrigger = false;
return true;
}
I hope this can be useful.
ciao!