Bullet 关于碰撞检测的几种callback

来源:互联网 发布:中国移动积分商城源码 编辑:程序博客网 时间:2024/04/29 19:43

 

一、筛选性回调(来源于bullet用户文档)

1) mask回调

这种回调方式用一个short int的掩码来决定两个物体是否能发生碰撞,每个object有两种个掩码,myGroup掩码和collideMask掩码。只有当以下条件成立时两object 才能发生碰撞

int myGroup = 1;

int collideMask = 4;

world->addCollisionObject(object,myGroup,collideMask);

bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;

collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);

即两objectmyGroup掩码与另一个物体的collideMask码交操作后都不为0.

2) broadphase回调

该种方法创建一个broadphase回调类,实现其中的一个函数,能在broadphase阶段之前过滤掉某些不需要的碰撞。Broadphase最后产生的overlap对不会出现被过滤的object对。

代码:

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;

}

};

然后注册

btOverlapFilterCallback * filterCallback = new YourOwnFilterCallback();

dynamicsWorld->getPairCache()->setOverlapFilterCallback(filterCallback);

btOverlapFilterCallback类是被用于产生broadphase阶段回调的一个虚基类

3) narrowphase回调

该回调在narrowphase碰撞检测判定前被调用。

void MyNearCallback(btBroadphasePair& collisionPair,

btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) {

    // Do your collision logic here

    // Only dispatch the Bullet collision information if you want the physics to continue

    dispatcher.defaultNearCallback(collisionPair, dispatcher, dispatchInfo);

}

mDispatcher->setNearCallback(MyNearCallback);

注意回调函数中的dispatcher.defaultNearCallback(collisionPair, dispatcher, dispatchInfo);语句必须存在,该函数是实际的碰撞检测和contact生成代码。即当collisionPair需要碰撞时,调用这个语句。

二、碰撞后的回调

上面说的几种回调都是发生在碰撞检测之前,即用于在检测前过滤掉一些不需要的碰撞。有些时候我们需要对发生碰撞的object对进行相关操作,这需要先进行相关的碰撞检测,然后进行回调。但是bullet似乎并没有直接给出了这种回调,但是有一种可以的实现方法。

dynamicWorld进行了一步simulation之后,碰撞的object对被保存在一个btPersistentManifold数组里,其中每个btPersistentManifold实例都包含了一对碰撞的信息。这个数组在DisPatcher类里面。示例代码如下:

int objclass[3] ={0,1,2};

boxBody->setUserPointer(&objclass[0]);

ground->setUserPointer(&objclass[1]);

wall->setUserPointer(&objclass[2]);

void Collide_callback(){

    int type_obj1, type_obj2;

    int numManifolds = sDynamicsWorld->getDispatcher()->getNumManifolds();

    for(int i=0;i<numManifolds;i++)

    {

        btPersistentManifold * contactManifold = sDynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);

        int numContacts= contactManifold->getNumContacts();

        if(numContacts>0)

        {   

            btCollisionObject * obA = static_cast<btCollisionObject*>(contactManifold->getBody0());

            btCollisionObject * obB = static_cast<btCollisionObject*>(contactManifold->getBody1());

            type_obj1 = * (int *)obA->getUserPointer();

            type_obj2 = * (int *)obB->getUserPointer();

            if((type_obj1==0)&&(type_obj2==1))

            {

                [g_ResManager playSound:@"test.caf"];

            }

            if((type_obj1==0)&&(type_obj2==2))

            {

                [g_ResManager playSound:@"test.caf"];

            }           

        }

    }

}

相关类

btCollisionObject

该类是所有碰撞object的基类,它有一个指针成员,可以指向用户的数据,并且该指针不会被bullet的库代码所引用,即只是给用户使用。

void * getUserPointer () const

users can point to their objects, userPointer is not used by Bullet

void setUserPointer (void *userPointer)

users can point to their objects, userPointer is not used by Bullet

btPersistentManifold

这个类用于存放碰撞对的信息,可以从该类中得到碰撞的物体,碰撞点等相关信息