Hi everybody!
This is my problem: I'm currently developing a game were the AI's are using the btKinematicCharacterController of bullet. And my question is, has anybody implemented collision btKinematicCharacterControllers between btKinematicCharacterControllers??
thanks!!
KinematicCharacterController vs KinematicCharacterController
-
- Posts: 10
- Joined: Mon Apr 02, 2012 2:25 pm
-
- Posts: 10
- Joined: Mon Apr 02, 2012 2:25 pm
Re: KinematicCharacterController vs KinematicCharacterContro
I detect my problem. I'm currently using the 'needBroadphaseCollision' method inherited from btOverlapfilterCallback. Well, some of my classes, were implementing it and of course, registering it with this sentence:
- _physicServer->getScene()->GetbtDiscreteDynamicWorld()->getPairCache()->setOverlapFilterCallback(this);
The problem is that you can only register one FilterCallback in bullet world. So now, I'm developing my own filter Callback that will dispatch all the collision to the desired entity. This can be done with polymorphism technics of C++.
ciao!
p.d.: If u are having troubles with this, ask me directly.
- _physicServer->getScene()->GetbtDiscreteDynamicWorld()->getPairCache()->setOverlapFilterCallback(this);
The problem is that you can only register one FilterCallback in bullet world. So now, I'm developing my own filter Callback that will dispatch all the collision to the desired entity. This can be done with polymorphism technics of C++.
ciao!
p.d.: If u are having troubles with this, ask me directly.
-
- Posts: 149
- Joined: Fri Jun 24, 2011 8:53 am
Re: KinematicCharacterController vs KinematicCharacterContro
Interesting. Would you elaborate?
-
- Posts: 10
- Joined: Mon Apr 02, 2012 2:25 pm
Re: KinematicCharacterController vs KinematicCharacterContro
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.
//add some additional logic here that modified 'collides' return collides;
And then create an object of this class and register this callback using:
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
//PhysicFilterCallback.cpp
I hope this can be useful.
ciao!
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: Select all
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);
And then create an object of this class and register this callback using:
Code: Select all
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: Select all
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;
};
Code: Select all
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!
-
- Posts: 149
- Joined: Fri Jun 24, 2011 8:53 am
Re: KinematicCharacterController vs KinematicCharacterContro
Thank you very much for your very detailed answer. I was hoping at an overview at best.
So basically you're relying on reintepret_cast to cast the userData pointer to a base interface and then dispatch there.
I am rather currently using a different approach based on manifold inspection by a custom controller. The goal was to stay out of physics pipeline as much as possible.
So basically you're relying on reintepret_cast to cast the userData pointer to a base interface and then dispatch there.
I am rather currently using a different approach based on manifold inspection by a custom controller. The goal was to stay out of physics pipeline as much as possible.
-
- Posts: 10
- Joined: Mon Apr 02, 2012 2:25 pm
Re: KinematicCharacterController vs KinematicCharacterContro
Yep, that's my goal too. This is the more lightly way I've found.The goal was to stay out of physics pipeline as much as possible.
It works quite well.
ciao!!