Softbody improvements, thanks to Nathanael

This commit is contained in:
erwin.coumans
2008-05-17 12:39:16 +00:00
parent 649709dc2d
commit d9e7058ff2
12 changed files with 2098 additions and 1828 deletions

View File

@@ -22,10 +22,319 @@ subject to the following restrictions:
#include "RenderingHelpers.h"
#include "GLFontRenderer.h"
#include "btBulletCollisionCommon.h"
#include "BulletSoftBody/btDbvtBroadphase.h"
#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
#include "Camera.h"
int numParts =2;
bool enableCulling = true;
bool cullFarPlane = false;
bool showCulling = false;
bool enableOcclusion = false;
bool showOcclusion = true;
int visiblecount = 0;
struct OcclusionBuffer
{
struct WriteOCL
{
static inline bool Process(btScalar& q,btScalar v) { if(q<v) q=v;return(false); }
};
struct QueryOCL
{
static inline bool Process(btScalar& q,btScalar v) { return(q<=v); }
};
bool initialized;
btAlignedObjectArray<btScalar> buffer;
int sizes[2];
btScalar scales[2];
btScalar offsets[2];
btScalar wtrs[16];
btVector3 eye;
btVector3 neardist;
btScalar ocarea;
btScalar qrarea;
GLuint texture;
OcclusionBuffer()
{
initialized=false;
neardist=btVector3(2,2,2);
ocarea=(btScalar)0;
qrarea=(btScalar)0;
}
void setup(int w,int h)
{
initialized=true;
sizes[0]=w;
sizes[1]=h;
scales[0]=w/2;
scales[1]=h/2;
offsets[0]=scales[0]+0.5;
offsets[1]=scales[1]+0.5;
glGenTextures(1,&texture);
clear();
}
void clear()
{
buffer.resize(0);
buffer.resize(sizes[0]*sizes[1],0);
}
void initialize()
{
if(!initialized)
{
setup(128,128);
}
GLint v[4];
GLdouble m[16],p[16];
glGetIntegerv(GL_VIEWPORT,v);
glGetDoublev(GL_MODELVIEW_MATRIX,m);
glGetDoublev(GL_PROJECTION_MATRIX,p);
for(int i=0;i<16;++i) wtrs[i]=p[i];
clear();
}
void drawBuffer( btScalar l,btScalar t,
btScalar r,btScalar b)
{
btAlignedObjectArray<GLubyte> data;
data.resize(buffer.size());
for(int i=0;i<data.size();++i)
{
data[i]=int(32/buffer[i])%255;
}
glBindTexture(GL_TEXTURE_2D,texture);
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,sizes[0],sizes[1],0,GL_LUMINANCE,GL_UNSIGNED_BYTE,&data[0]);
glBegin(GL_QUADS);
glColor4ub(255,255,255,255);
glTexCoord2f(0,0);glVertex2f(l,t);
glTexCoord2f(1,0);glVertex2f(r,t);
glTexCoord2f(1,1);glVertex2f(r,b);
glTexCoord2f(0,1);glVertex2f(l,b);
glEnd();
glDisable(GL_TEXTURE_2D);
}
btVector4 transform(const btVector3& x) const
{
btVector4 t;
t[0] = x[0]*wtrs[0]+x[1]*wtrs[4]+x[2]*wtrs[8]+wtrs[12];
t[1] = x[0]*wtrs[1]+x[1]*wtrs[5]+x[2]*wtrs[9]+wtrs[13];
t[2] = x[0]*wtrs[2]+x[1]*wtrs[6]+x[2]*wtrs[10]+wtrs[14];
t[3] = x[0]*wtrs[3]+x[1]*wtrs[7]+x[2]*wtrs[11]+wtrs[15];
return(t);
}
static bool project(btVector4* p,int n)
{
for(int i=0;i<n;++i)
{
const btScalar iw=1/p[i][3];
p[i][2]=1/p[i][3];
p[i][0]*=p[i][2];
p[i][1]*=p[i][2];
}
return(true);
}
template <const int NP>
static int clip(const btVector4* pi,btVector4* po)
{
btScalar s[NP];
int m=0;
for(int i=0;i<NP;++i)
{
s[i]=pi[i][2]+pi[i][3];
if(s[i]<0) m+=1<<i;
}
if(m==((1<<NP)-1)) return(0);
if(m!=0)
{
int n=0;
for(int i=NP-1,j=0;j<NP;i=j++)
{
const btVector4& a=pi[i];
const btVector4& b=pi[j];
const btScalar t=s[i]/(a[3]+a[2]-b[3]-b[2]);
if((t>0)&&(t<1))
{
po[n][0] = a[0]+(b[0]-a[0])*t;
po[n][1] = a[1]+(b[1]-a[1])*t;
po[n][2] = a[2]+(b[2]-a[2])*t;
po[n][3] = a[3]+(b[3]-a[3])*t;
++n;
}
if(s[j]>0) po[n++]=b;
}
return(n);
}
for(int i=0;i<NP;++i) po[i]=pi[i];
return(NP);
}
template <typename POLICY>
inline bool draw( const btVector4& a,
const btVector4& b,
const btVector4& c,
const btScalar minarea)
{
const btScalar a2=cross(b-a,c-a)[2];
if(a2>0)
{
if(a2<minarea) return(true);
const int x[]={ (int)(a.x()*scales[0]+offsets[0]),
(int)(b.x()*scales[0]+offsets[0]),
(int)(c.x()*scales[0]+offsets[0])};
const int y[]={ (int)(a.y()*scales[1]+offsets[1]),
(int)(b.y()*scales[1]+offsets[1]),
(int)(c.y()*scales[1]+offsets[1])};
const btScalar z[]={ a.z(),b.z(),c.z()};
const int mix=btMax(0,btMin(x[0],btMin(x[1],x[2])));
const int mxx=btMin(sizes[0],1+btMax(x[0],btMax(x[1],x[2])));
const int miy=btMax(0,btMin(y[0],btMin(y[1],y[2])));
const int mxy=btMin(sizes[1],1+btMax(y[0],btMax(y[1],y[2])));
const int width=mxx-mix;
const int height=mxy-miy;
if((width*height)>0)
{
const int dx[]={ y[0]-y[1],
y[1]-y[2],
y[2]-y[0]};
const int dy[]={ x[1]-x[0]-dx[0]*width,
x[2]-x[1]-dx[1]*width,
x[0]-x[2]-dx[2]*width};
const int a=x[2]*y[0]+x[0]*y[1]-x[2]*y[1]-x[0]*y[2]+x[1]*y[2]-x[1]*y[0];
const btScalar ia=1/(btScalar)a;
const btScalar dzx=ia*(y[2]*(z[1]-z[0])+y[1]*(z[0]-z[2])+y[0]*(z[2]-z[1]));
const btScalar dzy=ia*(x[2]*(z[0]-z[1])+x[0]*(z[1]-z[2])+x[1]*(z[2]-z[0]))-(dzx*width);
int c[]={ miy*x[1]+mix*y[0]-x[1]*y[0]-mix*y[1]+x[0]*y[1]-miy*x[0],
miy*x[2]+mix*y[1]-x[2]*y[1]-mix*y[2]+x[1]*y[2]-miy*x[1],
miy*x[0]+mix*y[2]-x[0]*y[2]-mix*y[0]+x[2]*y[0]-miy*x[2]};
btScalar v=ia*((z[2]*c[0])+(z[0]*c[1])+(z[1]*c[2]));
btScalar* scan=&buffer[miy*sizes[1]];
for(int iy=miy;iy<mxy;++iy)
{
for(int ix=mix;ix<mxx;++ix)
{
if((c[0]>=0)&&(c[1]>=0)&&(c[2]>=0))
{
if(POLICY::Process(scan[ix],v)) return(true);
}
c[0]+=dx[0];c[1]+=dx[1];c[2]+=dx[2];v+=dzx;
}
c[0]+=dy[0];c[1]+=dy[1];c[2]+=dy[2];v+=dzy;
scan+=sizes[0];
}
}
}
return(false);
}
template <const int NP,typename POLICY>
inline bool clipDraw( const btVector4* p,
btScalar minarea)
{
btVector4 o[NP*2];
const int n=clip<NP>(p,o);
bool earlyexit=false;
project(o,n);
for(int i=2;i<n;++i)
{
earlyexit|=draw<POLICY>(o[0],o[i-1],o[i],minarea);
}
return(earlyexit);
}
void appendOccluder( const btVector3& a,
const btVector3& b,
const btVector3& c)
{
const btVector4 p[]={transform(a),transform(b),transform(c)};
clipDraw<3,WriteOCL>(p,ocarea);
}
void appendOccluder( const btVector3& a,
const btVector3& b,
const btVector3& c,
const btVector3& d)
{
const btVector4 p[]={transform(a),transform(b),transform(c),transform(d)};
clipDraw<4,WriteOCL>(p,ocarea);
}
void appendOccluder( const btVector3& c,
const btVector3& e)
{
const btVector4 x[]={ transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]-e[2])),
transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]-e[2])),
transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]-e[2])),
transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]-e[2])),
transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]+e[2])),
transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]+e[2])),
transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]+e[2])),
transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]+e[2]))};
static const int d[]={ 1,0,3,2,
4,5,6,7,
4,7,3,0,
6,5,1,2,
7,6,2,3,
5,4,0,1};
for(int i=0;i<(sizeof(d)/sizeof(d[0]));)
{
const btVector4 p[]={ x[d[i++]],
x[d[i++]],
x[d[i++]],
x[d[i++]]};
clipDraw<4,WriteOCL>(p,ocarea);
}
}
inline bool queryOccluder( const btVector3& a,
const btVector3& b,
const btVector3& c)
{
const btVector4 p[]={transform(a),transform(b),transform(c)};
return(clipDraw<3,QueryOCL>(p,qrarea));
}
inline bool queryOccluder( const btVector3& a,
const btVector3& b,
const btVector3& c,
const btVector3& d)
{
const btVector4 p[]={transform(a),transform(b),transform(c),transform(d)};
return(clipDraw<4,QueryOCL>(p,qrarea));
}
inline bool queryOccluder( const btVector3& c,
const btVector3& e)
{
const btVector4 x[]={ transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]-e[2])),
transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]-e[2])),
transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]-e[2])),
transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]-e[2])),
transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]+e[2])),
transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]+e[2])),
transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]+e[2])),
transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]+e[2]))};
for(int i=0;i<8;++i)
{
if((x[i][2]+x[i][3])<=0) return(true);
}
static const int d[]={ 1,0,3,2,
4,5,6,7,
4,7,3,0,
6,5,1,2,
7,6,2,3,
5,4,0,1};
for(int i=0;i<(sizeof(d)/sizeof(d[0]));)
{
const btVector4 p[]={ x[d[i++]],
x[d[i++]],
x[d[i++]],
x[d[i++]]};
if(clipDraw<4,QueryOCL>(p,qrarea)) return(true);
}
return(false);
}
};
OcclusionBuffer ocb;
BulletSAPCompleteBoxPruningTest::BulletSAPCompleteBoxPruningTest(int numBoxes,int method) :
mBar (null),
mNbBoxes (numBoxes),
@@ -39,7 +348,7 @@ BulletSAPCompleteBoxPruningTest::BulletSAPCompleteBoxPruningTest(int numBoxes,in
btVector3 aabbMax(200,200,200);
int maxNumBoxes = numBoxes;
m_isdbvt=false;
switch (method)
{
case 1:
@@ -101,8 +410,9 @@ BulletSAPCompleteBoxPruningTest::BulletSAPCompleteBoxPruningTest(int numBoxes,in
}
break;
case 7:
m_broadphase = new btDbvtBroadphase();
methodname = "btDbvtBroadphase";
m_broadphase = new btDbvtBroadphase();
m_isdbvt = true;
methodname = "btDbvtBroadphase";
break;
default:
{
@@ -122,11 +432,13 @@ BulletSAPCompleteBoxPruningTest::~BulletSAPCompleteBoxPruningTest()
void BulletSAPCompleteBoxPruningTest::Init()
{
m_firstTime = true;
btClock clock;
m_firstTime = true;
SRand(0);
mBoxes = new AABB[mNbBoxes];
mFlags = new bool[mNbBoxes];
mBoxPtrs = new const AABB*[mNbBoxes];
mBoxTime = new float[mNbBoxes];
for(udword i=0;i<mNbBoxes;i++)
@@ -146,11 +458,12 @@ void BulletSAPCompleteBoxPruningTest::Init()
btVector3 aabbMax(Center.x+Extents.x,Center.y+Extents.y,Center.z+Extents.z);
int shapeType =0;
void* userPtr = 0;
btBroadphaseProxy* proxy = m_broadphase->createProxy(aabbMin,aabbMax,shapeType,(void*)i,1,1,0,0);//m_dispatcher);
btBroadphaseProxy* proxy = m_broadphase->createProxy(aabbMin,aabbMax,shapeType,&mBoxes[i],1,1,0,0);//m_dispatcher);
m_proxies.push_back( proxy );
mBoxTime[i] = 2000.0f*UnitRandomFloat();
}
printf("Initialization of %s with %u boxes: %ums\r\n",methodname,mNbBoxes,clock.getTimeMilliseconds());
}
void BulletSAPCompleteBoxPruningTest::Release()
@@ -166,6 +479,23 @@ void BulletSAPCompleteBoxPruningTest::Select()
mBar = TwNewBar("OPC_CompleteBoxPruning");
TwAddVarRW(mBar, "Speed", TW_TYPE_FLOAT, &mSpeed, " min=0.0 max=0.01 step=0.00001");
TwAddVarRW(mBar, "Amplitude", TW_TYPE_FLOAT, &mAmplitude, " min=10.0 max=200.0 step=0.1");
if(m_isdbvt)
{
TwAddVarRW(mBar, "Enable culling",TW_TYPE_BOOLCPP,&enableCulling,"");
TwAddVarRW(mBar, "Enable occlusion",TW_TYPE_BOOLCPP,&enableOcclusion,"");
TwAddVarRW(mBar, "Show culling",TW_TYPE_BOOLCPP,&showCulling,"");
TwAddVarRW(mBar, "Show occlusion",TW_TYPE_BOOLCPP,&showOcclusion,"");
TwAddVarRW(mBar, "Cull far plane",TW_TYPE_BOOLCPP,&cullFarPlane,"");
TwAddVarRW(mBar, "OC Min area",TW_TYPE_FLOAT,&ocb.ocarea,"min=0.0 max=1.0 step=0.001");
TwAddVarRW(mBar, "QR Min area",TW_TYPE_FLOAT,&ocb.qrarea,"min=0.0 max=1.0 step=0.001");
TwAddVarRW(mBar, "Dyn lkhd",TW_TYPE_INT32,&((btDbvtBroadphase*)m_broadphase)->m_sets[0].m_lkhd,"min=-1 max=32");
TwAddVarRW(mBar, "Fix lkhd",TW_TYPE_INT32,&((btDbvtBroadphase*)m_broadphase)->m_sets[1].m_lkhd,"min=-1 max=32");
TwAddVarRW(mBar, "Dyn opt/f(%)",TW_TYPE_INT32,&((btDbvtBroadphase*)m_broadphase)->m_dupdates,"min=0 max=100");
TwAddVarRW(mBar, "Fix opt/f(%)",TW_TYPE_INT32,&((btDbvtBroadphase*)m_broadphase)->m_fupdates,"min=0 max=100");
TwAddVarRO(mBar, "Dyn leafs",TW_TYPE_INT32,&((btDbvtBroadphase*)m_broadphase)->m_sets[0].m_leafs,"");
TwAddVarRO(mBar, "Fix leafs",TW_TYPE_INT32,&((btDbvtBroadphase*)m_broadphase)->m_sets[1].m_leafs,"");
TwAddVarRO(mBar, "Visible",TW_TYPE_INT32,&visiblecount,"");
}
}
printf("SubMethod: %s\r\n",methodname);
}
@@ -198,8 +528,8 @@ bool BulletSAPCompleteBoxPruningTest::UpdateBoxes(int numBoxes)
}
return true;
}
extern int doTree;
extern int percentUpdate;
extern int doTree;
extern int percentUpdate;
void BulletSAPCompleteBoxPruningTest::PerformTest()
{
@@ -239,8 +569,7 @@ void BulletSAPCompleteBoxPruningTest::PerformTest()
// printf("%d pairs colliding\r ", mPairs.GetNbPairs());
bool* Flags = (bool*)_alloca(sizeof(bool)*mNbBoxes);
ZeroMemory(Flags, sizeof(bool)*mNbBoxes);
ZeroMemory(mFlags,sizeof(bool)*mNbBoxes);
btOverlappingPairCache* pairCache = m_broadphase->getOverlappingPairCache();
const btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
@@ -249,8 +578,11 @@ void BulletSAPCompleteBoxPruningTest::PerformTest()
{
// Flags[pairPtr[i].m_pProxy0->getUid()-1] = true;
// Flags[pairPtr[i].m_pProxy1->getUid()-1] = true;
Flags[int(pairPtr[i].m_pProxy0->m_clientObject)] = true;
Flags[int(pairPtr[i].m_pProxy1->m_clientObject)] = true;
int j;
j=((AABB*)pairPtr[i].m_pProxy0->m_clientObject)-mBoxes;
mFlags[j] = true;
j=((AABB*)pairPtr[i].m_pProxy1->m_clientObject)-mBoxes;
mFlags[j] = true;
}
@@ -304,11 +636,13 @@ void BulletSAPCompleteBoxPruningTest::PerformTest()
glEnable(GL_DEPTH_TEST);
//glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
// Render boxes
OBB CurrentBox;
Render();
/*OBB CurrentBox;
CurrentBox.mRot.Identity();
for(udword i=0;i<mNbBoxes;i++)
{
@@ -317,7 +651,7 @@ void BulletSAPCompleteBoxPruningTest::PerformTest()
mBoxes[i].GetCenter(CurrentBox.mCenter);
mBoxes[i].GetExtents(CurrentBox.mExtents);
DrawOBB(CurrentBox);
}
}*/
char Buffer[4096];
sprintf(Buffer, "CompleteBoxPruning: %5.1f us (%d cycles) : %d pairs\n", mProfiler.mMsTime, mProfiler.mCycles,
@@ -328,6 +662,286 @@ void BulletSAPCompleteBoxPruningTest::PerformTest()
GLFontRenderer::print(10.0f, 10.0f, 0.02f, Buffer);
}
//
static void DrawVolume(const btDbvt::Volume& volume,const btVector3& color)
{
const btVector3 mins=volume.Mins();
const btVector3 maxs=volume.Maxs();
glColor3f(color.x(),color.y(),color.z());
glVertex3f(mins.x(),mins.y(),mins.z());
glVertex3f(maxs.x(),mins.y(),mins.z());
glVertex3f(maxs.x(),mins.y(),mins.z());
glVertex3f(maxs.x(),maxs.y(),mins.z());
glVertex3f(maxs.x(),maxs.y(),mins.z());
glVertex3f(mins.x(),maxs.y(),mins.z());
glVertex3f(mins.x(),maxs.y(),mins.z());
glVertex3f(mins.x(),mins.y(),mins.z());
glVertex3f(mins.x(),mins.y(),maxs.z());
glVertex3f(maxs.x(),mins.y(),maxs.z());
glVertex3f(maxs.x(),mins.y(),maxs.z());
glVertex3f(maxs.x(),maxs.y(),maxs.z());
glVertex3f(maxs.x(),maxs.y(),maxs.z());
glVertex3f(mins.x(),maxs.y(),maxs.z());
glVertex3f(mins.x(),maxs.y(),maxs.z());
glVertex3f(mins.x(),mins.y(),maxs.z());
glVertex3f(mins.x(),mins.y(),mins.z());
glVertex3f(mins.x(),mins.y(),maxs.z());
glVertex3f(maxs.x(),mins.y(),mins.z());
glVertex3f(maxs.x(),mins.y(),maxs.z());
glVertex3f(maxs.x(),maxs.y(),mins.z());
glVertex3f(maxs.x(),maxs.y(),maxs.z());
glVertex3f(mins.x(),maxs.y(),mins.z());
glVertex3f(mins.x(),maxs.y(),maxs.z());
}
//
void BulletSAPCompleteBoxPruningTest::RenderAll()
{
OBB CurrentBox;
CurrentBox.mRot.Identity();
for(udword i=0;i<mNbBoxes;i++)
{
if(mFlags[i]) glColor3f(1.0f, 0.0f, 0.0f);
else glColor3f(0.0f, 1.0f, 0.0f);
mBoxes[i].GetCenter(CurrentBox.mCenter);
mBoxes[i].GetExtents(CurrentBox.mExtents);
DrawOBB(CurrentBox);
}
}
//
void BulletSAPCompleteBoxPruningTest::Render()
{
visiblecount=mNbBoxes;
if((!m_isdbvt)||(!enableCulling))
{
RenderAll();
}
else
{
btDbvtBroadphase* pbp=(btDbvtBroadphase*)m_broadphase;
const int margin=0;
const int lc=margin;
const int rc=glutGet(GLUT_WINDOW_WIDTH)-(1+margin);
const int tc=margin;
const int bc=glutGet(GLUT_WINDOW_HEIGHT)-(1+margin);
const btVector3 c00(ComputeWorldRay(lc,tc).x,
ComputeWorldRay(lc,tc).y,
ComputeWorldRay(lc,tc).z);
const btVector3 c10(ComputeWorldRay(rc,tc).x,
ComputeWorldRay(rc,tc).y,
ComputeWorldRay(rc,tc).z);
const btVector3 c01(ComputeWorldRay(lc,bc).x,
ComputeWorldRay(lc,bc).y,
ComputeWorldRay(lc,bc).z);
const btVector3 c11(ComputeWorldRay(rc,bc).x,
ComputeWorldRay(rc,bc).y,
ComputeWorldRay(rc,bc).z);
const btVector3 eye(GetCameraPos().x,GetCameraPos().y,GetCameraPos().z);
const btVector3 dir(GetCameraDir().x,GetCameraDir().y,GetCameraDir().z);
const btVector3 x00=eye+c00*100;
const btVector3 x10=eye+c10*100;
const btVector3 x01=eye+c01*100;
const btVector3 x11=eye+c11*100;
ocb.initialize();
ocb.eye=eye;
btVector3 planes_n[5];
btScalar planes_o[5];
static const btScalar farplane=200;
static const int nplanes=sizeof(planes_n)/sizeof(planes_n[0]);
const int acplanes=cullFarPlane?5:4;
planes_n[0] = cross(c01,c00).normalized();
planes_n[1] = cross(c10,c11).normalized();
planes_n[2] = cross(c00,c10).normalized();
planes_n[3] = cross(c11,c01).normalized();
planes_n[4] = -dir;
planes_o[4] = -dot(eye+dir*farplane,planes_n[4]);
for(int i=0;i<4;++i) planes_o[i]=-dot(eye,planes_n[i]);
struct SceneRenderer : btDbvt::ICollide
{
int drawn;
BulletSAPCompleteBoxPruningTest* self;
OBB box;
OcclusionBuffer* ocb;
SceneRenderer()
{
drawn=0;
box.mRot.Identity();
}
bool Descent(const btDbvt::Node* node)
{
return(ocb->queryOccluder(node->volume.Center(),node->volume.Extent()));
}
void Process(const btDbvt::Node* leaf)
{
btBroadphaseProxy* proxy=(btBroadphaseProxy*)leaf->data;
int i=((AABB*)proxy->m_clientObject)-self->mBoxes;
if(self->mFlags[i]) glColor3f(1.0f, 0.0f, 0.0f);
else glColor3f(0.0f, 1.0f, 0.0f);
self->mBoxes[i].GetCenter(box.mCenter);
self->mBoxes[i].GetExtents(box.mExtents);
DrawOBB(box);drawn++;
if(ocb)
{
ocb->appendOccluder(btVector3(box.mCenter.x,box.mCenter.y,box.mCenter.z),
btVector3(box.mExtents.x,box.mExtents.y,box.mExtents.z));
}
}
} srenderer;
srenderer.self=this;
srenderer.ocb=0;
if(enableOcclusion)
{
srenderer.ocb=&ocb;
btDbvt::collideOCL(pbp->m_sets[1].m_root,planes_n,planes_o,dir,acplanes,srenderer);
btDbvt::collideOCL(pbp->m_sets[0].m_root,planes_n,planes_o,dir,acplanes,srenderer);
}
else
{
btDbvt::collideKDOP(pbp->m_sets[1].m_root,planes_n,planes_o,acplanes,srenderer);
btDbvt::collideKDOP(pbp->m_sets[0].m_root,planes_n,planes_o,acplanes,srenderer);
}
visiblecount=srenderer.drawn;
if(showOcclusion&&enableOcclusion)
{
const btScalar ratio=((float)glutGet(GLUT_WINDOW_HEIGHT))/((float)glutGet(GLUT_WINDOW_WIDTH));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1,1,-1,1,-1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
const float mm[]={ 1,0,0,0,
0,1,0,0,
0,0,0,1,
0,0,0,1};
glMultMatrixf(mm);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
const float size=0.6f;
const float orgx=0.3f;
const float orgy=0.25f;
const float left=orgx;
const float right=orgx+size;
const float top=orgy+size;
const float bottom=orgy;
ocb.drawBuffer(left,bottom,right,top);
}
if(showCulling)
{
const btScalar ratio=((float)glutGet(GLUT_WINDOW_HEIGHT))/((float)glutGet(GLUT_WINDOW_WIDTH));
static const float scale=0.004;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1,1,-1*ratio,1*ratio,-1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
const float mm[]={ 1,0,0,0,
0,0,1,0,
0,1,0,0,
0,0,0,1};
glMultMatrixf(mm);
glScalef(scale,scale,scale);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor4f(1,1,1,1);
struct DebugRenderer : btDbvt::ICollide
{
OcclusionBuffer* ocb;
int sid;
bool AllLeafs(const btDbvt::Node* node)
{
Process(node);
return(false);
}
bool Descent(const btDbvt::Node* node)
{
return(ocb->queryOccluder(node->volume.Center(),node->volume.Extent()));
}
void Process(const btDbvt::Node* node)
{
if(ocb)
{
ocb->appendOccluder(node->volume.Center(),node->volume.Extent());
}
if(sid>=0)
{
const float f=sid/1023.;
DrawVolume(node->volume,btVector3(1,f,f));
sid=(sid+1)%1024;
}
else
{
if(node->isinternal())
DrawVolume(node->volume,btVector3(0,1,0));
else
DrawVolume(node->volume,btVector3(1,0,1));
}
}
} drenderer;
if(enableOcclusion)
{
drenderer.ocb=&ocb;
drenderer.sid=0;
ocb.clear();
btDbvt::collideOCL(pbp->m_sets[1].m_root,planes_n,planes_o,dir,acplanes,drenderer);
btDbvt::collideOCL(pbp->m_sets[0].m_root,planes_n,planes_o,dir,acplanes,drenderer);
}
else
{
drenderer.ocb=0;
drenderer.sid=-1;
btDbvt::collideKDOP(pbp->m_sets[1].m_root,planes_n,planes_o,acplanes,drenderer);
btDbvt::collideKDOP(pbp->m_sets[0].m_root,planes_n,planes_o,acplanes,drenderer);
}
glEnd();
glBegin(GL_LINES);
glColor4f(1,1,1,1);
glVertex3f(eye.x(),eye.y(),eye.z());
glVertex3f(x00.x(),x00.y(),x00.z());
glVertex3f(eye.x(),eye.y(),eye.z());
glVertex3f(x10.x(),x10.y(),x10.z());
glVertex3f(eye.x(),eye.y(),eye.z());
glVertex3f(x01.x(),x01.y(),x01.z());
glVertex3f(eye.x(),eye.y(),eye.z());
glVertex3f(x11.x(),x11.y(),x11.z());
glVertex3f(x00.x(),x00.y(),x00.z());
glVertex3f(x10.x(),x10.y(),x10.z());
glVertex3f(x10.x(),x10.y(),x10.z());
glVertex3f(x11.x(),x11.y(),x11.z());
glVertex3f(x11.x(),x11.y(),x11.z());
glVertex3f(x01.x(),x01.y(),x01.z());
glVertex3f(x01.x(),x01.y(),x01.z());
glVertex3f(x00.x(),x00.y(),x00.z());
glEnd();
}
}
}
void BulletSAPCompleteBoxPruningTest::KeyboardCallback(unsigned char key, int x, int y)
{
}