void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) { struct MyNodeOverlapCallback : public btNodeOverlapCallback { btStridingMeshInterface* m_meshInterface; btTriangleCallback* m_callback; MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) :m_meshInterface(meshInterface), m_callback(callback) { } virtual void processNode(int nodeSubPart, int nodeTriangleIndex) { btVector3 m_triangle[3]; const unsigned char *vertexbase; int numverts; PHY_ScalarType type; int stride; const unsigned char *indexbase; int indexstride; int numfaces; PHY_ScalarType indicestype; m_meshInterface->getLockedReadOnlyVertexIndexBase( &vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, nodeSubPart); unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); const btVector3& meshScaling = m_meshInterface->getScaling(); for (int j=2;j>=0;j--) { int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); } /* Perform ray vs. triangle collision here */ m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); } }; MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax); }
void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) { btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy); multiProxy->m_aabbMin = aabbMin; multiProxy->m_aabbMax = aabbMax; // bool fullyContained = false; // bool alreadyInSimple = false; struct MyNodeOverlapCallback : public btNodeOverlapCallback { btMultiSapBroadphase* m_multiSap; btMultiSapProxy* m_multiProxy; btDispatcher* m_dispatcher; MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher) :m_multiSap(multiSap), m_multiProxy(multiProxy), m_dispatcher(dispatcher) { } virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex) { btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex]; int containingBroadphaseIndex = -1; //already found? for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++) { if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) { containingBroadphaseIndex = i; break; } } if (containingBroadphaseIndex<0) { //add it btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy); m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase); } } }; MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher); if (m_optimizedAabbTree) m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); int i; for ( i=0;i<multiProxy->m_bridgeProxies.size();i++) { btVector3 worldAabbMin,worldAabbMax; multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax); bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); if (!overlapsBroadphase) { //remove it now btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i]; btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1); multiProxy->m_bridgeProxies.pop_back(); } } /* if (1) { //find broadphase that contain this multiProxy int numChildBroadphases = getBroadphaseArray().size(); for (int i=0;i<numChildBroadphases;i++) { btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i]; btVector3 worldAabbMin,worldAabbMax; childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax); bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); // fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); int containingBroadphaseIndex = -1; //if already contains this for (int i=0;i<multiProxy->m_bridgeProxies.size();i++) { if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) { containingBroadphaseIndex = i; } alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase); } if (overlapsBroadphase) { if (containingBroadphaseIndex<0) { btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); childProxy->m_multiSapParentProxy = multiProxy; addToChildBroadphase(multiProxy,childProxy,childBroadphase); } } else { if (containingBroadphaseIndex>=0) { //remove btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex]; btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1); multiProxy->m_bridgeProxies.pop_back(); } } } ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force) ///hopefully we don't end up with many entries here (can assert/provide feedback on stats) if (0)//!multiProxy->m_bridgeProxies.size()) { ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision ///this is needed to be able to calculate the aabb overlap btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); childProxy->m_multiSapParentProxy = multiProxy; addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); } } if (!multiProxy->m_bridgeProxies.size()) { ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision ///this is needed to be able to calculate the aabb overlap btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); childProxy->m_multiSapParentProxy = multiProxy; addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); } */ //update for ( i=0;i<multiProxy->m_bridgeProxies.size();i++) { btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i]; bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher); } }
//perform bvh tree traversal and report overlapping triangles to 'callback' void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const { #ifdef DISABLE_BVH //brute force traverse all triangles btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax); #else //first get all the nodes struct MyNodeOverlapCallback : public btNodeOverlapCallback { btStridingMeshInterface* m_meshInterface; btTriangleCallback* m_callback; btVector3 m_triangle[3]; MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) :m_meshInterface(meshInterface), m_callback(callback) { } virtual void processNode(int nodeSubPart, int nodeTriangleIndex) { const unsigned char *vertexbase; int numverts; PHY_ScalarType type; int stride; const unsigned char *indexbase; int indexstride; int numfaces; PHY_ScalarType indicestype; m_meshInterface->getLockedReadOnlyVertexIndexBase( &vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, nodeSubPart); unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR); const btVector3& meshScaling = m_meshInterface->getScaling(); for (int j=2;j>=0;j--) { int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j]; #ifdef DEBUG_TRIANGLE_MESH printf("%d ,",graphicsindex); #endif //DEBUG_TRIANGLE_MESH if (type == PHY_FLOAT) { float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); m_triangle[j] = btVector3( graphicsbase[0]*meshScaling.getX(), graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ()); } else { double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); m_triangle[j] = btVector3( btScalar(graphicsbase[0])*meshScaling.getX(), btScalar(graphicsbase[1])*meshScaling.getY(), btScalar(graphicsbase[2])*meshScaling.getZ()); } #ifdef DEBUG_TRIANGLE_MESH printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z()); #endif //DEBUG_TRIANGLE_MESH } m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); } }; MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); #endif//DISABLE_BVH }