void BulletPhysics::BulletInternalTickCallback(btDynamicsWorld* world, btScalar timeStep) { // called after bullet sdk performs its internal step CB_ASSERT(world); CB_ASSERT(world->getWorldUserInfo()); BulletPhysics* bulletPhysics = static_cast<BulletPhysics*>(world->getWorldUserInfo()); CollisionPairs currentTickCollisionPairs; // look at all existing collisions btDispatcher* dispatcher = world->getDispatcher(); const int numManifolds = dispatcher->getNumManifolds(); for (int i = 0; i < numManifolds; i++) { // get the manifold which is the data corresponding to a contact point between two colliders const btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); CB_ASSERT(manifold); // get the colliding bodies const btRigidBody* body0 = static_cast<const btRigidBody *>(manifold->getBody0()); const btRigidBody* body1 = static_cast<const btRigidBody *>(manifold->getBody1()); // swap them if need be const bool swapped = body0 > body1; const btRigidBody* sortedBody0 = swapped ? body1 : body0; const btRigidBody* sortedBody1 = swapped ? body0 : body1; // insert the collision pair into the set const CollisionPair pair = std::make_pair(sortedBody0, sortedBody1); currentTickCollisionPairs.insert(pair); // if this is a new contact, send an event if (bulletPhysics->m_PreviousTickCollisionPairs.find(pair) == bulletPhysics->m_PreviousTickCollisionPairs.end()) { bulletPhysics->SendCollisionPairAddEvent(manifold, body0, body1); } } CollisionPairs removedCollisionPairs; // use set difference to see which collisions existed last tick but are no longer colliding std::set_difference(bulletPhysics->m_PreviousTickCollisionPairs.begin(), bulletPhysics->m_PreviousTickCollisionPairs.end(), currentTickCollisionPairs.begin(), currentTickCollisionPairs.end(), std::inserter(removedCollisionPairs, removedCollisionPairs.begin())); // send collision exit events for (auto it = removedCollisionPairs.begin(); it != removedCollisionPairs.end(); ++it) { const btRigidBody* body0 = it->first; const btRigidBody* body1 = it->second; bulletPhysics->SendCollisionPairRemoveEvent(body0, body1); } // update the collision pairs bulletPhysics->m_PreviousTickCollisionPairs = currentTickCollisionPairs; }
void BulletOpenGLApplication::CheckForCollisionEvents() { // keep a list of the collision pairs we // found during the current update CollisionPairs pairsThisUpdate; // iterate through all of the manifolds in the dispatcher for (int i = 0; i < m_pDispatcher->getNumManifolds(); ++i) { // get the manifold btPersistentManifold* pManifold = m_pDispatcher->getManifoldByIndexInternal(i); // ignore manifolds that have // no contact points. if (pManifold->getNumContacts() > 0) { // get the two rigid bodies involved in the collision const btRigidBody* pBody0 = static_cast<const btRigidBody*>(pManifold->getBody0()); const btRigidBody* pBody1 = static_cast<const btRigidBody*>(pManifold->getBody1()); // always create the pair in a predictable order // (use the pointer value..) bool const swapped = pBody0 > pBody1; const btRigidBody* pSortedBodyA = swapped ? pBody1 : pBody0; const btRigidBody* pSortedBodyB = swapped ? pBody0 : pBody1; // create the pair CollisionPair thisPair = std::make_pair(pSortedBodyA, pSortedBodyB); // insert the pair into the current list pairsThisUpdate.insert(thisPair); // if this pair doesn't exist in the list // from the previous update, it is a new // pair and we must send a collision event if (m_pairsLastUpdate.find(thisPair) == m_pairsLastUpdate.end()) { CollisionEvent((btRigidBody*)pBody0, (btRigidBody*)pBody1); } } } // create another list for pairs that // were removed this update CollisionPairs removedPairs; // this handy function gets the difference beween // two sets. It takes the difference between // collision pairs from the last update, and this // update and pushes them into the removed pairs list std::set_difference( m_pairsLastUpdate.begin(), m_pairsLastUpdate.end(), pairsThisUpdate.begin(), pairsThisUpdate.end(), std::inserter(removedPairs, removedPairs.begin())); // iterate through all of the removed pairs // sending separation events for them for (CollisionPairs::const_iterator iter = removedPairs.begin(); iter != removedPairs.end(); ++iter) { SeparationEvent((btRigidBody*)iter->first, (btRigidBody*)iter->second); } // in the next iteration we'll want to // compare against the pairs we found // in this iteration m_pairsLastUpdate = pairsThisUpdate; }