Added 2 optimizations for the SAP broadphase: check AABB before remove, and a faster 2D overlap test.

Thanks to Pierre Terdiman/OPCODE Array SAP. Performance goes down from 4.6 to 2.9ms for the 8192 Extras/CDTestFramework benchmark.
This commit is contained in:
erwin.coumans 2008-09-11 07:34:18 +00:00
parent 32ab5d3691
commit 8b3270f22f

View File

@ -27,6 +27,7 @@
#include "btOverlappingPairCallback.h" #include "btOverlappingPairCallback.h"
//#define DEBUG_BROADPHASE 1 //#define DEBUG_BROADPHASE 1
#define USE_OVERLAP_TEST_ON_REMOVES 1
/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase. /// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
/// It uses quantized integers to represent the begin and end points for each of the 3 axis. /// It uses quantized integers to represent the begin and end points for each of the 3 axis.
@ -98,7 +99,7 @@ protected:
void freeHandle(BP_FP_INT_TYPE handle); void freeHandle(BP_FP_INT_TYPE handle);
bool testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB); bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1);
#ifdef DEBUG_BROADPHASE #ifdef DEBUG_BROADPHASE
void debugPrintAxis(int axis,bool checkCardinality=true); void debugPrintAxis(int axis,bool checkCardinality=true);
@ -600,34 +601,17 @@ bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* pr
} }
template <typename BP_FP_INT_TYPE> template <typename BP_FP_INT_TYPE>
bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB) bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1)
{ {
//optimization 1: check the array index (memory address), instead of the m_pos //optimization 1: check the array index (memory address), instead of the m_pos
for (int axis = 0; axis < 3; axis++) if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] ||
{ pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
if (axis != ignoreAxis) pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
{ pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1])
if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
{ {
return false; return false;
} }
}
}
//optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization)
/*for (int axis = 0; axis < 3; axis++)
{
if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos ||
m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos)
{
return false;
}
}
*/
return true; return true;
} }
@ -697,7 +681,9 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE
if (pPrev->IsMax()) if (pPrev->IsMax())
{ {
// if previous edge is a maximum check the bounds and add an overlap if necessary // if previous edge is a maximum check the bounds and add an overlap if necessary
if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev)) const int axis1 = (1 << axis) & 3;
const int axis2 = (1 << axis1) & 3;
if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2))
{ {
m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev); m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
if (m_userPairCallback) if (m_userPairCallback)
@ -744,13 +730,20 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE ed
Handle* pHandleNext = getHandle(pNext->m_handle); Handle* pHandleNext = getHandle(pNext->m_handle);
if (pNext->IsMax()) if (pNext->IsMax())
{
// if next edge is maximum remove any overlap between the two handles
if (updateOverlaps)
{ {
Handle* handle0 = getHandle(pEdge->m_handle); Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pNext->m_handle); Handle* handle1 = getHandle(pNext->m_handle);
const int axis1 = (1 << axis) & 3;
const int axis2 = (1 << axis1) & 3;
// if next edge is maximum remove any overlap between the two handles
if (updateOverlaps
#ifdef USE_OVERLAP_TEST_ON_REMOVES
&& testOverlap2D(handle0,handle1,axis1,axis2)
#endif //USE_OVERLAP_TEST_ON_REMOVES
)
{
m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
if (m_userPairCallback) if (m_userPairCallback)
@ -796,12 +789,20 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE
if (!pPrev->IsMax()) if (!pPrev->IsMax())
{ {
// if previous edge was a minimum remove any overlap between the two handles // if previous edge was a minimum remove any overlap between the two handles
if (updateOverlaps) Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pPrev->m_handle);
const int axis1 = (1 << axis) & 3;
const int axis2 = (1 << axis1) & 3;
if (updateOverlaps
#ifdef USE_OVERLAP_TEST_ON_REMOVES
&& testOverlap2D(handle0,handle1,axis1,axis2)
#endif //USE_OVERLAP_TEST_ON_REMOVES
)
{ {
//this is done during the overlappingpairarray iteration/narrowphase collision //this is done during the overlappingpairarray iteration/narrowphase collision
Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pPrev->m_handle);
m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
if (m_userPairCallback) if (m_userPairCallback)
m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
@ -847,10 +848,13 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE ed
{ {
Handle* pHandleNext = getHandle(pNext->m_handle); Handle* pHandleNext = getHandle(pNext->m_handle);
const int axis1 = (1 << axis) & 3;
const int axis2 = (1 << axis1) & 3;
if (!pNext->IsMax()) if (!pNext->IsMax())
{ {
// if next edge is a minimum check the bounds and add an overlap if necessary // if next edge is a minimum check the bounds and add an overlap if necessary
if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext)) if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2))
{ {
Handle* handle0 = getHandle(pEdge->m_handle); Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pNext->m_handle); Handle* handle1 = getHandle(pNext->m_handle);