Files
bullet3/Extras/CDTestFramework/DbvtTest.cpp
erwin.coumans 8ddbf12f1a only move 10% of objects
added relative path to Bullet projectfiles (math/collision)
2008-04-02 19:22:08 +00:00

307 lines
8.5 KiB
C++

/*
Bounding Volume Hierarchy Test
Copyright (c) 2008 Nathanael Presson, as part of Bullet Physics Library
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "stdafx.h"
#include "DbvtTest.h"
#include "RenderingHelpers.h"
#include "GLFontRenderer.h"
#include "btBulletCollisionCommon.h"
#include "btDbvt.h"
namespace _0E5F0A41_1DC2_4e14_9ABC_1CBE13DF25C8_
{
//
class btDbvtProxy : public btBroadphaseProxy
{
public:
AABB aabb;
btDbvt::Node* leaf;
bool contact;
};
//
struct btDbvtPair
{
btDbvtProxy* proxies[2];
};
//
class btDbvtBroadphase : public btBroadphaseInterface
{
public:
btDbvtBroadphase();
virtual ~btDbvtBroadphase() {}
virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void calculateOverlappingPairs(btDispatcher* dispatcher) {}
virtual btOverlappingPairCache* getOverlappingPairCache() { return(0); }
virtual const btOverlappingPairCache* getOverlappingPairCache() const { return(0); }
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const {}
virtual void printStats() {}
btAlignedObjectArray<btDbvtProxy*> m_proxies;
btAlignedObjectArray<btDbvtPair> m_pairs;
btDbvt* m_dbvt;
};
//
btDbvtBroadphase::btDbvtBroadphase()
{
while(m_proxies.size()) destroyProxy(m_proxies[0],0);
}
//
btBroadphaseProxy* btDbvtBroadphase::createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy)
{
btDbvtProxy* pp=new btDbvtProxy();
pp->aabb.SetMinMax( Point(aabbMin.x(),aabbMin.y(),aabbMin.z()),
Point(aabbMax.x(),aabbMax.y(),aabbMax.z()));
pp->leaf=m_dbvt->Insert((aabbMin+aabbMax)/2,(aabbMax-aabbMin)/2,pp);
m_proxies.push_back(pp);
return(pp);
}
//
void btDbvtBroadphase::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
btDbvtProxy* pp=(btDbvtProxy*)proxy;
m_proxies.remove(pp);
m_dbvt->Remove(pp->leaf);
delete proxy;
}
//
void btDbvtBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
{
AABB box;
btDbvtProxy* pp=(btDbvtProxy*)proxy;
box.SetMinMax( Point(aabbMin.x(),aabbMin.y(),aabbMin.z()),
Point(aabbMax.x(),aabbMax.y(),aabbMax.z()));
pp->aabb=box;
}
}
using namespace _0E5F0A41_1DC2_4e14_9ABC_1CBE13DF25C8_;
DbvtTest::DbvtTest(int numBoxes)
{
m_bfirsttime = true;
m_nbox = numBoxes;
m_broadphase = new btDbvtBroadphase();
m_margin = 0.5;
m_bar = 0;
m_speed = 0.005;
m_amp = 100;
}
DbvtTest::~DbvtTest()
{
}
void DbvtTest::Init()
{
SRand(0);
((btDbvtBroadphase*)m_broadphase)->m_dbvt=btDbvt::Create();
m_times.resize(m_nbox);
for(int i=0;i<m_nbox;i++)
{
Point Center, Extents;
Center.x = (UnitRandomFloat()-0.5f) * 100.0f;
Center.y = (UnitRandomFloat()-0.5f) * 10.0f;
Center.z = (UnitRandomFloat()-0.5f) * 100.0f;
Extents.x = 2.0f + UnitRandomFloat() * 2.0f;
Extents.y = 2.0f + UnitRandomFloat() * 2.0f;
Extents.z = 2.0f + UnitRandomFloat() * 2.0f;
btVector3 aabbMin(Center.x-Extents.x,Center.y-Extents.y,Center.z-Extents.z);
btVector3 aabbMax(Center.x+Extents.x,Center.y+Extents.y,Center.z+Extents.z);
m_broadphase->createProxy(aabbMin,aabbMax,0,0,1,1,0,0);
m_times[i]=2000.0f*UnitRandomFloat();
}
}
void DbvtTest::Release()
{
}
void DbvtTest::Select()
{
m_bar=TwNewBar("Dbvt");
TwAddVarRW(m_bar,"Margin",TW_TYPE_FLOAT,&m_margin," min=0.0 max=10.0 step=0.5");
TwAddVarRW(m_bar,"Speed", TW_TYPE_FLOAT, &m_speed, " min=0.0 max=0.01 step=0.00001");
TwAddVarRW(m_bar,"Amplitude", TW_TYPE_FLOAT, &m_amp, " min=10.0 max=200.0 step=0.1");
}
void DbvtTest::Deselect()
{
if(m_bar)
{
TwDeleteBar(m_bar);
m_bar=0;
}
}
static inline bool Intersect( const btDbvt::Aabb& a,
const btDbvt::Aabb& b)
{
return( (a.mi.x()<=b.mx.x())&&
(a.mx.x()>=b.mi.x())&&
(a.mi.y()<=b.mx.y())&&
(a.mx.y()>=b.mi.y())&&
(a.mi.z()<=b.mx.z())&&
(a.mx.z()>=b.mi.z()));
}
static void TreeTreeParse( const btDbvt::Node* a,
const btDbvt::Node* b,
btAlignedObjectArray<btDbvtPair>& pairs)
{
if(a==b)
{
if(a->isinternal())
{
TreeTreeParse(a->childs[0],a->childs[0],pairs);
TreeTreeParse(a->childs[1],a->childs[1],pairs);
TreeTreeParse(a->childs[0],a->childs[1],pairs);
}
}
else if(Intersect(a->box,b->box))
{
if(a->isinternal())
{
if(b->isinternal())
{
TreeTreeParse(a->childs[0],b->childs[0],pairs);
TreeTreeParse(a->childs[1],b->childs[0],pairs);
TreeTreeParse(a->childs[0],b->childs[1],pairs);
TreeTreeParse(a->childs[1],b->childs[1],pairs);
}
else
{
TreeTreeParse(a->childs[0],b,pairs);
TreeTreeParse(a->childs[1],b,pairs);
}
}
else
{
if(b->isinternal())
{
TreeTreeParse(a,b->childs[0],pairs);
TreeTreeParse(a,b->childs[1],pairs);
}
else
{
btDbvtPair p;
p.proxies[0]=(btDbvtProxy*)a->data;
p.proxies[1]=(btDbvtProxy*)b->data;
if(p.proxies[0]->aabb.Intersect(p.proxies[1]->aabb))
{
pairs.push_back(p);
}
}
}
}
}
void DbvtTest::PerformTest()
{
btDbvtBroadphase* pb=(btDbvtBroadphase*)m_broadphase;
const btScalar speed=m_speed;
const btScalar ampl=m_amp;
const int nupd=m_bfirsttime? pb->m_proxies.size():
(pb->m_proxies.size()*10)/100;
/* Move boxes */
m_profiler.Start();
for(int i=0;i<nupd;i++)
{
const btScalar time=(m_times[i]+=speed);
Point center( cosf(time*2.17)*ampl+sinf(time)*ampl*0.5,
cosf(time*1.38)*ampl+sinf(time*ampl),
sinf(time*0.777)*ampl);
Point extent;
pb->m_proxies[i]->aabb.GetExtents(extent);
pb->m_proxies[i]->aabb.SetCenterExtents(center,extent);
pb->m_dbvt->Update( pb->m_proxies[i]->leaf,
btVector3(center.x,center.y,center.z),
btVector3(extent.x,extent.y,extent.z),
m_margin);
}
if(m_bfirsttime)
{
pb->m_dbvt->OptimizeTopDown();
}
/* Overlap */
pb->m_pairs.resize(0);
TreeTreeParse( pb->m_dbvt->m_root,
pb->m_dbvt->m_root,
pb->m_pairs);
m_profiler.End();
m_profiler.Accum();
#if 0
int check=0;
for(int i=0,ni=pb->m_proxies.size();i<ni;++i)
{
AABB boxa=pb->m_proxies[i]->aabb;
for(int j=i+1;j<ni;++j)
{
if(boxa.Intersect(pb->m_proxies[j]->aabb))
{
++check;
}
}
}
if(check!=pb->m_pairs.size())
{
printf("Check failed %u => %u\r\n",check,pb->m_pairs.size());
}
#endif
/* Render boxes */
OBB CurrentBox;
CurrentBox.mRot.Identity();
for(int i=0,ni=pb->m_proxies.size();i<ni;i++)
{
pb->m_proxies[i]->contact=false;
}
for(int i=0,ni=pb->m_pairs.size();i<ni;i++)
{
pb->m_pairs[i].proxies[0]->contact=true;
pb->m_pairs[i].proxies[1]->contact=true;
}
for(int i=0,ni=pb->m_proxies.size();i<ni;i++)
{
if(pb->m_proxies[i]->contact) glColor3f(1.0f, 0.0f, 0.0f);
else glColor3f(0.0f, 1.0f, 0.0f);
pb->m_proxies[i]->aabb.GetCenter(CurrentBox.mCenter);
pb->m_proxies[i]->aabb.GetExtents(CurrentBox.mExtents);
DrawOBB(CurrentBox);
}
char Buffer[4096];
sprintf(Buffer,"Dbvt: %5.1f us (%d cycles) : %d pairs\n",m_profiler.mMsTime,m_profiler.mCycles,pb->m_pairs.size());
GLFontRenderer::print(10.0f, 10.0f, 0.02f, Buffer);
m_bfirsttime=false;
}
void DbvtTest::KeyboardCallback(unsigned char key, int x, int y)
{
}
void DbvtTest::MouseCallback(int button, int state, int x, int y)
{
}
void DbvtTest::MotionCallback(int x, int y)
{
}