KinematicCharacterController vs KinematicCharacterController

Knn0N
Posts: 10
Joined: Mon Apr 02, 2012 2:25 pm

KinematicCharacterController vs KinematicCharacterController

Post by Knn0N »

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!!
Knn0N
Posts: 10
Joined: Mon Apr 02, 2012 2:25 pm

Re: KinematicCharacterController vs KinematicCharacterContro

Post by Knn0N »

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.
MaxDZ8
Posts: 149
Joined: Fri Jun 24, 2011 8:53 am

Re: KinematicCharacterController vs KinematicCharacterContro

Post by MaxDZ8 »

Interesting. Would you elaborate?
Knn0N
Posts: 10
Joined: Mon Apr 02, 2012 2:25 pm

Re: KinematicCharacterController vs KinematicCharacterContro

Post by Knn0N »

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: 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);
//add some additional logic here that modified 'collides' return collides;
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;
};
//PhysicFilterCallback.cpp

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!
MaxDZ8
Posts: 149
Joined: Fri Jun 24, 2011 8:53 am

Re: KinematicCharacterController vs KinematicCharacterContro

Post by MaxDZ8 »

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.
Knn0N
Posts: 10
Joined: Mon Apr 02, 2012 2:25 pm

Re: KinematicCharacterController vs KinematicCharacterContro

Post by Knn0N »

The goal was to stay out of physics pipeline as much as possible.
Yep, that's my goal too. This is the more lightly way I've found.

It works quite well.


ciao!!