//by default, Bullet will use this near callback void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) { btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; if (dispatcher.needsCollision(colObj0,colObj1)) { //dispatcher will keep algorithms persistent in the collision pair if (!collisionPair.m_algorithm) { collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1); } if (collisionPair.m_algorithm) { btManifoldResult contactPointResult(colObj0,colObj1); if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) { //discrete collision detection query collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult); } else { //continuous collision detection query, time of impact (toi) btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); if (dispatchInfo.m_timeOfImpact > toi) dispatchInfo.m_timeOfImpact = toi; } } } }
void run() { btCollisionObject *obj0 = (btCollisionObject *)m_pair.m_pProxy0->m_clientObject; btCollisionObject *obj1 = (btCollisionObject *)m_pair.m_pProxy1->m_clientObject; // Check for invalid numbers being passed through btAssert(obj0->getWorldTransform() == obj0->getWorldTransform()); btAssert(obj1->getWorldTransform() == obj1->getWorldTransform()); btCollisionObjectWrapper obj0Wrap(0, obj0->getCollisionShape(), obj0, obj0->getWorldTransform(), -1, -1); btCollisionObjectWrapper obj1Wrap(0, obj1->getCollisionShape(), obj1, obj1->getWorldTransform(), -1, -1); if (!m_pair.m_algorithm) { m_pair.m_algorithm = m_pDispatcher->findAlgorithm(&obj0Wrap, &obj1Wrap); } if (m_pair.m_algorithm) { btManifoldResult contactPointResult(&obj0Wrap, &obj1Wrap); if (m_pInfo->m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) { m_pair.m_algorithm->processCollision(&obj0Wrap, &obj1Wrap, *m_pInfo, &contactPointResult); } else { // Continuous dispatch m_pair.m_algorithm->calculateTimeOfImpact(obj0, obj1, *m_pInfo, &contactPointResult); } } }
float collisionTester::collisionTest(btCollisionObject * objectA, btCollisionObject * objectB, btCollisionAlgorithm * algo){ float dist = 99999; btCollisionObjectWrapper ob0(0,objectA->getCollisionShape(),objectA, objectA->getWorldTransform()); btCollisionObjectWrapper ob1(0,objectB->getCollisionShape(),objectB, objectB->getWorldTransform()); // // btCollisionAlgorithm* algo = collisionWorld->getDispatcher()->findAlgorithm(&ob0, &ob1); btManifoldResult contactPointResult(&ob0,&ob1); algo->processCollision(&ob0,&ob1,collisionWorld->getDispatchInfo(),&contactPointResult); btManifoldArray manifoldArray; algo->getAllContactManifolds(manifoldArray); int numManifolds = manifoldArray.size(); for(int i=0;i<numManifolds;i++) { btPersistentManifold* contactManifold = manifoldArray[i]; const btCollisionObject* obA = static_cast<const btCollisionObject*>(contactManifold->getBody0()); // btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1()); int numContacts = contactManifold->getNumContacts(); bool swap = obA == objectA; //printf("numManifolds=%i, numContact = %i \n", numManifolds, numContacts); for (int j=0;j<numContacts;j++) { btManifoldPoint& pt = contactManifold->getContactPoint(j); // glDisable(GL_DEPTH_TEST); // glBegin(GL_LINES); // glColor3f(0, 0, 1); btVector3 ptA = swap ?pt.getPositionWorldOnA():pt.getPositionWorldOnB(); btVector3 ptB = swap ? pt.getPositionWorldOnB():pt.getPositionWorldOnA(); // glVertex3d(ptA.x(),ptA.y(),ptA.z()); // glVertex3d(ptB.x(),ptB.y(),ptB.z()); //contactPts.push_back(ptA); //contactPts.push_back(ptB); // glEnd(); float distTmp = pt.getDistance(); if(distTmp<dist) dist=distTmp; } //you can un-comment out this line, and then all points are removed contactManifold->clearManifold(); } return dist; }
///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected. ///it reports one or more contact points (including the one with deepest penetration) void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback) { btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(colObjA,colObjB); if (algorithm) { btBridgedManifoldResult contactPointResult(colObjA,colObjB, resultCallback); //discrete collision detection query algorithm->processCollision(colObjA,colObjB, getDispatchInfo(),&contactPointResult); algorithm->~btCollisionAlgorithm(); getDispatcher()->freeCollisionAlgorithm(algorithm); } }
void Uncollider::nearCallback(btBroadphasePair &collisionPair, btCollisionDispatcher &dispatcher, const btDispatcherInfo &dispatchInfo) { btCollisionObject *colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject *colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; if (dispatcher.needsCollision(colObj0, colObj1)) { btCollisionObjectWrapper obj0Wrap(nullptr, colObj0->getCollisionShape(), colObj0, colObj0->getWorldTransform(), -1, -1); btCollisionObjectWrapper obj1Wrap(nullptr, colObj1->getCollisionShape(), colObj1, colObj1->getWorldTransform(), -1, -1); btManifoldResult contactPointResult(&obj0Wrap, &obj1Wrap); if (not collisionPair.m_algorithm) { #if (BT_BULLET_VERSION >=286) collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap, &obj1Wrap, contactPointResult.getPersistentManifold(), ebtDispatcherQueryType::BT_CONTACT_POINT_ALGORITHMS); #else collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap, &obj1Wrap); #endif } if (collisionPair.m_algorithm) { if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) { collisionPair.m_algorithm->processCollision(&obj0Wrap, &obj1Wrap, dispatchInfo, &contactPointResult); for (int i = 0; i < contactPointResult.getPersistentManifold()->getNumContacts(); ++i) { const btManifoldPoint &pt = contactPointResult.getPersistentManifold()-> getContactPoint(i); const btVector3 &cp = pt.getPositionWorldOnA(); if (isPointInUncollideVolume(cp)) { contactPointResult.getPersistentManifold()->removeContactPoint(i--); } } } else { btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0, colObj1, dispatchInfo, &contactPointResult); if (dispatchInfo.m_timeOfImpact > toi) { dispatchInfo.m_timeOfImpact = toi; } } } } }
//вызываеться при столкновении геометрий void PhysicsManager::mNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) { btCollisionObject* colObj0 = static_cast<btCollisionObject*>(collisionPair.m_pProxy0->m_clientObject); btCollisionObject* colObj1 = static_cast<btCollisionObject*>(collisionPair.m_pProxy1->m_clientObject); if(dispatcher.needsCollision(colObj0,colObj1)) { btCollisionObjectWrapper obj0Wrap(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform()); btCollisionObjectWrapper obj1Wrap(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform()); //dispatcher will keep algorithms persistent in the collision pair if (!collisionPair.m_algorithm) { collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap,&obj1Wrap); } if (collisionPair.m_algorithm) { btManifoldResult contactPointResult(&obj0Wrap,&obj1Wrap); if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) { //discrete collision detection query collisionPair.m_algorithm->processCollision(&obj0Wrap,&obj1Wrap,dispatchInfo,&contactPointResult); } else { //continuous collision detection query, time of impact (toi) btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); if (dispatchInfo.m_timeOfImpact > toi) { dispatchInfo.m_timeOfImpact = toi; } } if (contactPointResult.getPersistentManifold()->getNumContacts()>0) //только сдесь мы уверены что есть пересечения { GameLogic::getSingletonPtr()->CollideBody(colObj0, colObj1); } } } dispatcher.defaultNearCallback(collisionPair, dispatcher, dispatchInfo); }
virtual bool process(const btBroadphaseProxy* proxy) { btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; if (collisionObject == m_collisionObject) return true; //only perform raycast if filterMask matches if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) { btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(m_collisionObject,collisionObject); if (algorithm) { btBridgedManifoldResult contactPointResult(m_collisionObject,collisionObject, m_resultCallback); //discrete collision detection query algorithm->processCollision(m_collisionObject,collisionObject, m_world->getDispatchInfo(),&contactPointResult); algorithm->~btCollisionAlgorithm(); m_world->getDispatcher()->freeCollisionAlgorithm(algorithm); } } return true; }
void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher) { if (dispatchInfo.m_enableSPU) { m_maxNumOutstandingTasks = m_threadInterface->getNumTasks(); { BT_PROFILE("processAllOverlappingPairs"); if (!m_spuCollisionTaskProcess) m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks); m_spuCollisionTaskProcess->setNumTasks(m_maxNumOutstandingTasks); // printf("m_maxNumOutstandingTasks =%d\n",m_maxNumOutstandingTasks); m_spuCollisionTaskProcess->initialize2(dispatchInfo.m_useEpa); ///modified version of btCollisionDispatcher::dispatchAllCollisionPairs: { btSpuCollisionPairCallback collisionCallback(dispatchInfo,this); pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); } } //send one big batch int numTotalPairs = pairCache->getNumOverlappingPairs(); if (numTotalPairs) { btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr(); int i; { int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS; if (numTotalPairs < (m_spuCollisionTaskProcess->getNumTasks()*SPU_BATCHSIZE_BROADPHASE_PAIRS)) { pairRange = (numTotalPairs/m_spuCollisionTaskProcess->getNumTasks())+1; } BT_PROFILE("addWorkToTask"); for (i=0;i<numTotalPairs;) { //Performance Hint: tweak this number during benchmarking int endIndex = (i+pairRange) < numTotalPairs ? i+pairRange : numTotalPairs; m_spuCollisionTaskProcess->addWorkToTask(pairPtr,i,endIndex); i = endIndex; } } { BT_PROFILE("PPU fallback"); //handle PPU fallback pairs for (i=0;i<numTotalPairs;i++) { btBroadphasePair& collisionPair = pairPtr[i]; if (collisionPair.m_internalTmpValue == 3) { if (collisionPair.m_algorithm) { btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; if (dispatcher->needsCollision(colObj0,colObj1)) { //discrete collision detection query btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform()); btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform()); btManifoldResult contactPointResult(&ob0,&ob1); if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) { collisionPair.m_algorithm->processCollision(&ob0,&ob1,dispatchInfo,&contactPointResult); } else { //continuous collision detection query, time of impact (toi) btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); if (dispatchInfo.m_timeOfImpact > toi) dispatchInfo.m_timeOfImpact = toi; } } } } } } } { BT_PROFILE("flush2"); //make sure all SPU work is done m_spuCollisionTaskProcess->flush2(); } } else { ///PPU fallback ///!Need to make sure to clear all 'algorithms' when switching between SPU and PPU btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo,dispatcher); } }
void CollisionInterfaceDemo::displayCallback(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_LIGHTING); btScalar m[16]; btVector3 worldBoundsMin,worldBoundsMax; collisionWorld->getBroadphase()->getBroadphaseAabb(worldBoundsMin,worldBoundsMax); int i; for (i=0;i<numObjects;i++) { objects[i].getWorldTransform().getOpenGLMatrix( m ); m_shapeDrawer->drawOpenGL(m,objects[i].getCollisionShape(),btVector3(1,1,1),getDebugMode(),worldBoundsMin,worldBoundsMax); } collisionWorld->getDispatchInfo().m_debugDraw = &debugDrawer; if (collisionWorld) collisionWorld->performDiscreteCollisionDetection(); #ifndef TEST_NOT_ADDING_OBJECTS_TO_WORLD collisionWorld->debugDrawWorld(); ///one way to draw all the contact points is iterating over contact manifolds in the dispatcher: int numManifolds = collisionWorld->getDispatcher()->getNumManifolds(); for (i=0;i<numManifolds;i++) { btPersistentManifold* contactManifold = collisionWorld->getDispatcher()->getManifoldByIndexInternal(i); btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0()); btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1()); int numContacts = contactManifold->getNumContacts(); for (int j=0;j<numContacts;j++) { btManifoldPoint& pt = contactManifold->getContactPoint(j); glBegin(GL_LINES); glColor3f(0, 0, 0); btVector3 ptA = pt.getPositionWorldOnA(); btVector3 ptB = pt.getPositionWorldOnB(); glVertex3d(ptA.x(),ptA.y(),ptA.z()); glVertex3d(ptB.x(),ptB.y(),ptB.z()); glEnd(); } //you can un-comment out this line, and then all points are removed //contactManifold->clearManifold(); } #else glDisable(GL_TEXTURE_2D); for (i=0;i<numObjects;i++) { collisionWorld->debugDrawObject(objects[i].getWorldTransform(),objects[i].getCollisionShape(), btVector3(1,1,0)); } btDrawingResult renderCallback; //collisionWorld->contactPairTest(&objects[0],&objects[1], renderCallback); collisionWorld->contactTest(&objects[0],renderCallback); #if 0 //another way is to directly query the dispatcher for both objects. The objects don't need to be inserted into the world btCollisionAlgorithm* algo = collisionWorld->getDispatcher()->findAlgorithm(&objects[0],&objects[1]); btManifoldResult contactPointResult(&objects[0],&objects[1]); algo->processCollision(&objects[0],&objects[1],collisionWorld->getDispatchInfo(),&contactPointResult); btManifoldArray manifoldArray; algo->getAllContactManifolds(manifoldArray); int numManifolds = manifoldArray.size(); for (i=0;i<numManifolds;i++) { btPersistentManifold* contactManifold = manifoldArray[i]; btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0()); // btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1()); glDisable(GL_DEPTH_TEST); int numContacts = contactManifold->getNumContacts(); bool swap = obA == &objects[0]; for (int j=0;j<numContacts;j++) { btManifoldPoint& pt = contactManifold->getContactPoint(j); glBegin(GL_LINES); glColor3f(0, 0, 0); btVector3 ptA = swap ?pt.getPositionWorldOnA():pt.getPositionWorldOnB(); btVector3 ptB = swap ? pt.getPositionWorldOnB():pt.getPositionWorldOnA(); glVertex3d(ptA.x(),ptA.y(),ptA.z()); glVertex3d(ptB.x(),ptB.y(),ptB.z()); glEnd(); } //you can un-comment out this line, and then all points are removed //contactManifold->clearManifold(); } #endif #endif //GL_ShapeDrawer::drawCoordSystem(); btQuaternion qA = objects[0].getWorldTransform().getRotation(); btQuaternion qB = objects[1].getWorldTransform().getRotation(); if (!m_idle) { btScalar timeInSeconds = getDeltaTimeMicroseconds()/1000.f; btQuaternion orn; objects[0].getWorldTransform().getBasis().getEulerYPR(yaw,pitch,roll); pitch += 0.00005f*timeInSeconds; yaw += 0.0001f*timeInSeconds; objects[0].getWorldTransform().getBasis().setEulerYPR(yaw,pitch,roll); orn.setEuler(yaw,pitch,roll); objects[1].getWorldTransform().setOrigin(objects[1].getWorldTransform().getOrigin()+btVector3(0,-0.00001*timeInSeconds,0)); //objects[0].getWorldTransform().setRotation(orn); } glFlush(); swapBuffers(); }