Make raycast benchmark default, to show improved raycasting performance.

Add rayTest to btBroadphaseInterface, and implement efficient version for btDbvtBroadphase to accelerate raycasting.
btAxisSweep3, btSimpleBroadphase and btMultiSapBroadphase implement brute-force method (as before). For now, it is recommended to use btDbvtBroadphase for fastest world raycast.
This commit is contained in:
erwin.coumans
2008-10-14 06:23:45 +00:00
parent 780350a9e1
commit fffca75e9f
11 changed files with 123 additions and 25 deletions

View File

@@ -272,9 +272,11 @@ void BenchmarkDemo::initPhysics()
///Don't make the world AABB size too large, it will harm simulation quality and performance
btVector3 worldAabbMin(-10000,-10000,-10000);
btVector3 worldAabbMax(10000,10000,10000);
//m_overlappingPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,3500);
// m_overlappingPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,3500);
// m_overlappingPairCache = new btSimpleBroadphase();
m_overlappingPairCache = new btDbvtBroadphase();
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;

View File

@@ -26,13 +26,13 @@ int main(int argc,char** argv)
{
GLDebugDrawer gDebugDrawer;
BenchmarkDemo1 benchmarkDemo;
// BenchmarkDemo1 benchmarkDemo;
// BenchmarkDemo2 benchmarkDemo;
// BenchmarkDemo3 benchmarkDemo;
// BenchmarkDemo4 benchmarkDemo;
// BenchmarkDemo5 benchmarkDemo;
// BenchmarkDemo6 benchmarkDemo;
// BenchmarkDemo7 benchmarkDemo;
BenchmarkDemo7 benchmarkDemo;
benchmarkDemo.initPhysics();

View File

@@ -140,6 +140,8 @@ public:
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback);
void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const;
///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
void unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
@@ -244,6 +246,23 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy,cons
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback)
{
//choose axis?
BP_FP_INT_TYPE axis = 0;
//for each proxy
for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
{
if (m_pEdges[axis][i].IsMax())
{
rayCallback.process(getHandle(m_pEdges[axis][i].m_handle));
}
}
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
{

View File

@@ -23,6 +23,11 @@ class btDispatcher;
#include "btBroadphaseProxy.h"
class btOverlappingPairCache;
struct btBroadphaseRayCallback
{
virtual bool process(const btBroadphaseProxy* proxy) = 0;
};
#include "LinearMath/btVector3.h"
///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs.
@@ -38,6 +43,8 @@ public:
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback) = 0;
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0;

View File

@@ -210,6 +210,37 @@ void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy,btVector3& aabbMin, b
aabbMax = proxy->m_aabbMax;
}
void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback)
{
struct BroadphaseRayTester : btDbvt::ICollide
{
btBroadphaseRayCallback& m_rayCallback;
BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)
:m_rayCallback(orgCallback)
{
}
void Process(const btDbvtNode* leaf)
{
btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;
m_rayCallback.process(proxy);
}
};
BroadphaseRayTester callback(rayCallback);
m_sets[0].collideRAY( m_sets[0].m_root,
rayFrom,
rayTo,
callback);
m_sets[1].collideRAY( m_sets[1].m_root,
rayFrom,
rayTo,
callback);
}
//
void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy,
const btVector3& aabbMin,

View File

@@ -105,6 +105,8 @@ void optimize();
btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
void calculateOverlappingPairs(btDispatcher* dispatcher);
btOverlappingPairCache* getOverlappingPairCache();

View File

@@ -156,6 +156,14 @@ void btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin,
aabbMax = multiProxy->m_aabbMax;
}
void btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback)
{
for (int i=0;i<m_multiSapProxies.size();i++)
{
rayCallback.process(m_multiSapProxies[i]);
}
}
//#include <stdio.h>

View File

@@ -110,6 +110,8 @@ public:
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback);
void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase);
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb

View File

@@ -151,7 +151,14 @@ void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbM
sbp->m_aabbMax = aabbMax;
}
void btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback)
{
for (int i=0;i<m_numHandles;i++)
{
btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
rayCallback.process(proxy);
}
}

View File

@@ -121,6 +121,8 @@ public:
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback);
btOverlappingPairCache* getOverlappingPairCache()
{

View File

@@ -599,52 +599,70 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
}
}
void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
struct btSingleRayCallback : public btBroadphaseRayCallback
{
BT_PROFILE("rayTest");
btVector3 m_rayFromWorld;
btVector3 m_rayToWorld;
const btCollisionWorld* m_world;
btCollisionWorld::RayResultCallback& m_resultCallback;
btTransform rayFromTrans,rayToTrans;
rayFromTrans.setIdentity();
rayFromTrans.setOrigin(rayFromWorld);
rayToTrans.setIdentity();
btSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btCollisionWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
:m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld),
m_world(world),
m_resultCallback(resultCallback)
{
rayToTrans.setOrigin(rayToWorld);
}
/// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD)
int i;
for (i=0;i<m_collisionObjects.size();i++)
virtual bool process(const btBroadphaseProxy* proxy)
{
///terminate further ray tests, once the closestHitFraction reached zero
if (resultCallback.m_closestHitFraction == btScalar(0.f))
break;
if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
return false;
btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
btCollisionObject* collisionObject= m_collisionObjects[i];
//only perform raycast if filterMask matches
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
//btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
//collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
//getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
btScalar hitLambda = resultCallback.m_closestHitFraction;
btScalar hitLambda = m_resultCallback.m_closestHitFraction;
btVector3 hitNormal;
{
if (btRayAabb(rayFromWorld,rayToWorld,collisionObject->getBroadphaseHandle()->m_aabbMin,collisionObject->getBroadphaseHandle()->m_aabbMax,hitLambda,hitNormal))
if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObject->getBroadphaseHandle()->m_aabbMin,collisionObject->getBroadphaseHandle()->m_aabbMax,hitLambda,hitNormal))
{
rayTestSingle(rayFromTrans,rayToTrans,
btTransform rayFromTrans,rayToTrans;
rayFromTrans.setIdentity();
rayFromTrans.setOrigin(m_rayFromWorld);
rayToTrans.setIdentity();
rayToTrans.setOrigin(m_rayToWorld);
m_world->rayTestSingle(rayFromTrans,rayToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback);
m_resultCallback);
}
}
}
return true;
}
};
void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
{
BT_PROFILE("rayTest");
/// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD)
btSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
}