2 BulletSAPCompleteBoxPruningTest, Copyright (c) 2008 Erwin Coumans
4 CDTestFramework http://codercorner.com
5 Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com
7 This software is provided 'as-is', without any express or implied warranty.
8 In no event will the authors be held liable for any damages arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it freely,
11 subject to the following restrictions:
13 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.
14 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
15 3. This notice may not be removed or altered from any source distribution.
18 //This file was added by Erwin Coumans, to test Bullet SAP performance
21 #include "BulletSAPCompleteBoxPruningTest.h"
22 #include "RenderingHelpers.h"
23 #include "GLFontRenderer.h"
24 #include "btBulletCollisionCommon.h"
25 #include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
27 #ifdef USE_CUDA_BROADPHASE
28 #include "../CUDA/btCudaBroadphase.h"
30 #include "LinearMath/btQuickprof.h"
34 bool enableCulling = true;
35 bool cullFarPlane = false;
36 bool showCulling = false;
37 bool enableOcclusion = false;
38 bool showOcclusion = true;
41 static bool sBulletProfilerToggle = false;
43 struct OcclusionBuffer
47 static inline bool Process(btScalar& q,btScalar v) { if(q<v) q=v;return(false); }
51 static inline bool Process(btScalar& q,btScalar v) { return(q<=v); }
54 btAlignedObjectArray<btScalar> buffer;
67 neardist=btVector3(2,2,2);
71 void setup(int w,int h)
78 offsets[0]=scales[0]+0.5;
79 offsets[1]=scales[1]+0.5;
80 glGenTextures(1,&texture);
86 buffer.resize(sizes[0]*sizes[1],0);
96 glGetIntegerv(GL_VIEWPORT,v);
97 glGetDoublev(GL_MODELVIEW_MATRIX,m);
98 glGetDoublev(GL_PROJECTION_MATRIX,p);
99 for(int i=0;i<16;++i) wtrs[i]=p[i];
102 void drawBuffer( btScalar l,btScalar t,
103 btScalar r,btScalar b)
105 btAlignedObjectArray<GLubyte> data;
106 data.resize(buffer.size());
107 for(int i=0;i<data.size();++i)
109 data[i]=int(32/buffer[i])%255;
111 glBindTexture(GL_TEXTURE_2D,texture);
113 glEnable(GL_TEXTURE_2D);
114 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
115 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
116 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
117 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
118 glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,sizes[0],sizes[1],0,GL_LUMINANCE,GL_UNSIGNED_BYTE,&data[0]);
120 glColor4ub(255,255,255,255);
121 glTexCoord2f(0,0);glVertex2f(l,t);
122 glTexCoord2f(1,0);glVertex2f(r,t);
123 glTexCoord2f(1,1);glVertex2f(r,b);
124 glTexCoord2f(0,1);glVertex2f(l,b);
126 glDisable(GL_TEXTURE_2D);
128 btVector4 transform(const btVector3& x) const
131 t[0] = x[0]*wtrs[0]+x[1]*wtrs[4]+x[2]*wtrs[8]+wtrs[12];
132 t[1] = x[0]*wtrs[1]+x[1]*wtrs[5]+x[2]*wtrs[9]+wtrs[13];
133 t[2] = x[0]*wtrs[2]+x[1]*wtrs[6]+x[2]*wtrs[10]+wtrs[14];
134 t[3] = x[0]*wtrs[3]+x[1]*wtrs[7]+x[2]*wtrs[11]+wtrs[15];
137 static bool project(btVector4* p,int n)
141 const btScalar iw=1/p[i][3];
148 template <const int NP>
149 static int clip(const btVector4* pi,btVector4* po)
153 for(int i=0;i<NP;++i)
155 s[i]=pi[i][2]+pi[i][3];
158 if(m==((1<<NP)-1)) return(0);
162 for(int i=NP-1,j=0;j<NP;i=j++)
164 const btVector4& a=pi[i];
165 const btVector4& b=pi[j];
166 const btScalar t=s[i]/(a[3]+a[2]-b[3]-b[2]);
169 po[n][0] = a[0]+(b[0]-a[0])*t;
170 po[n][1] = a[1]+(b[1]-a[1])*t;
171 po[n][2] = a[2]+(b[2]-a[2])*t;
172 po[n][3] = a[3]+(b[3]-a[3])*t;
175 if(s[j]>0) po[n++]=b;
179 for(int i=0;i<NP;++i) po[i]=pi[i];
182 template <typename POLICY>
183 inline bool draw( const btVector4& a,
186 const btScalar minarea)
188 const btScalar a2=(b-a).cross(c-a)[2];
191 if(a2<minarea) return(true);
192 const int x[]={ (int)(a.x()*scales[0]+offsets[0]),
193 (int)(b.x()*scales[0]+offsets[0]),
194 (int)(c.x()*scales[0]+offsets[0])};
195 const int y[]={ (int)(a.y()*scales[1]+offsets[1]),
196 (int)(b.y()*scales[1]+offsets[1]),
197 (int)(c.y()*scales[1]+offsets[1])};
198 const btScalar z[]={ a.z(),b.z(),c.z()};
199 const int mix=btMax(0,btMin(x[0],btMin(x[1],x[2])));
200 const int mxx=btMin(sizes[0],1+btMax(x[0],btMax(x[1],x[2])));
201 const int miy=btMax(0,btMin(y[0],btMin(y[1],y[2])));
202 const int mxy=btMin(sizes[1],1+btMax(y[0],btMax(y[1],y[2])));
203 const int width=mxx-mix;
204 const int height=mxy-miy;
207 const int dx[]={ y[0]-y[1],
210 const int dy[]={ x[1]-x[0]-dx[0]*width,
211 x[2]-x[1]-dx[1]*width,
212 x[0]-x[2]-dx[2]*width};
213 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];
214 const btScalar ia=1/(btScalar)a;
215 const btScalar dzx=ia*(y[2]*(z[1]-z[0])+y[1]*(z[0]-z[2])+y[0]*(z[2]-z[1]));
216 const btScalar dzy=ia*(x[2]*(z[0]-z[1])+x[0]*(z[1]-z[2])+x[1]*(z[2]-z[0]))-(dzx*width);
217 int c[]={ miy*x[1]+mix*y[0]-x[1]*y[0]-mix*y[1]+x[0]*y[1]-miy*x[0],
218 miy*x[2]+mix*y[1]-x[2]*y[1]-mix*y[2]+x[1]*y[2]-miy*x[1],
219 miy*x[0]+mix*y[2]-x[0]*y[2]-mix*y[0]+x[2]*y[0]-miy*x[2]};
220 btScalar v=ia*((z[2]*c[0])+(z[0]*c[1])+(z[1]*c[2]));
221 btScalar* scan=&buffer[miy*sizes[1]];
222 for(int iy=miy;iy<mxy;++iy)
224 for(int ix=mix;ix<mxx;++ix)
226 if((c[0]>=0)&&(c[1]>=0)&&(c[2]>=0))
228 if(POLICY::Process(scan[ix],v)) return(true);
230 c[0]+=dx[0];c[1]+=dx[1];c[2]+=dx[2];v+=dzx;
232 c[0]+=dy[0];c[1]+=dy[1];c[2]+=dy[2];v+=dzy;
239 template <const int NP,typename POLICY>
240 inline bool clipDraw( const btVector4* p,
244 const int n=clip<NP>(p,o);
245 bool earlyexit=false;
249 earlyexit|=draw<POLICY>(o[0],o[i-1],o[i],minarea);
253 void appendOccluder( const btVector3& a,
257 const btVector4 p[]={transform(a),transform(b),transform(c)};
258 clipDraw<3,WriteOCL>(p,ocarea);
260 void appendOccluder( const btVector3& a,
265 const btVector4 p[]={transform(a),transform(b),transform(c),transform(d)};
266 clipDraw<4,WriteOCL>(p,ocarea);
268 void appendOccluder( const btVector3& c,
271 const btVector4 x[]={ transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]-e[2])),
272 transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]-e[2])),
273 transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]-e[2])),
274 transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]-e[2])),
275 transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]+e[2])),
276 transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]+e[2])),
277 transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]+e[2])),
278 transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]+e[2]))};
279 static const int d[]={ 1,0,3,2,
285 for(int i=0;i<(sizeof(d)/sizeof(d[0]));)
287 const btVector4 p[]={ x[d[i++]],
291 clipDraw<4,WriteOCL>(p,ocarea);
294 inline bool queryOccluder( const btVector3& a,
298 const btVector4 p[]={transform(a),transform(b),transform(c)};
299 return(clipDraw<3,QueryOCL>(p,qrarea));
301 inline bool queryOccluder( const btVector3& a,
306 const btVector4 p[]={transform(a),transform(b),transform(c),transform(d)};
307 return(clipDraw<4,QueryOCL>(p,qrarea));
309 inline bool queryOccluder( const btVector3& c,
312 const btVector4 x[]={ transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]-e[2])),
313 transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]-e[2])),
314 transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]-e[2])),
315 transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]-e[2])),
316 transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]+e[2])),
317 transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]+e[2])),
318 transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]+e[2])),
319 transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]+e[2]))};
322 if((x[i][2]+x[i][3])<=0) return(true);
324 static const int d[]={ 1,0,3,2,
330 for(int i=0;i<(sizeof(d)/sizeof(d[0]));)
332 const btVector4 p[]={ x[d[i++]],
336 if(clipDraw<4,QueryOCL>(p,qrarea)) return(true);
344 BulletSAPCompleteBoxPruningTest::BulletSAPCompleteBoxPruningTest(int numBoxes,int method) :
353 btVector3 aabbMin(-200,-200,-200);
354 btVector3 aabbMax(200,200,200);
356 int maxNumBoxes = numBoxes;
358 bool disableRaycastAccelerator = true;
362 m_broadphase = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,0,disableRaycastAccelerator);
363 methodname = "btAxisSweep3";
366 m_broadphase = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,new btNullPairCache(),disableRaycastAccelerator);
367 methodname = "btAxisSweep3+btNullPairCache";
370 m_broadphase = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,new btSortedOverlappingPairCache(),disableRaycastAccelerator);
371 methodname = "btAxisSweep3+btSortedOverlappingPairCache";
374 m_broadphase = new btSimpleBroadphase(maxNumBoxes,new btSortedOverlappingPairCache());
375 methodname = "btSimpleBroadphase+btSortedOverlappingPairCache";
378 m_broadphase = new btSimpleBroadphase(maxNumBoxes,new btNullPairCache());
379 methodname = "btSimpleBroadphase+btNullPairCache";
384 methodname = "btMultiSapBroadphase";
385 btMultiSapBroadphase* multiSap = new btMultiSapBroadphase(maxNumBoxes);
386 m_broadphase = multiSap;
388 btVector3 tmpAabbMin,tmpAabbMax;
390 float numP = (float) numParts;
392 for (int i=0;i<numParts;i++)
394 tmpAabbMin[0] = aabbMin[0] + i*(aabbMax[0]-aabbMin[0])/numP;
395 tmpAabbMax[0] = aabbMin[0] + (i+1)*(aabbMax[0]-aabbMin[0])/numP;
397 for (int j=0;j<numParts;j++)
399 tmpAabbMin[1] = aabbMin[1] + j*(aabbMax[1]-aabbMin[1])/numP;
400 tmpAabbMax[1] = aabbMin[1] + (j+1)*(aabbMax[1]-aabbMin[1])/numP;
402 for (int k=0;k<numParts;k++)
404 tmpAabbMin[2] = aabbMin[2] + k*(aabbMax[2]-aabbMin[2])/numP;
405 tmpAabbMax[2] = aabbMin[2] + (k+1)*(aabbMax[2]-aabbMin[2])/numP;
407 btAxisSweep3* childBp = new btAxisSweep3(tmpAabbMin,tmpAabbMax,maxNumBoxes,multiSap->getOverlappingPairCache(),disableRaycastAccelerator);
408 multiSap->getBroadphaseArray().push_back(childBp);
413 // btAxisSweep3* childBp = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,multiSap->getOverlappingPairCache());
414 // multiSap->getBroadphaseArray().push_back(childBp);
415 multiSap->buildTree(aabbMin,aabbMax);
422 btDbvtBroadphase* pbp=new btDbvtBroadphase();
424 pbp->m_deferedcollide = true; /* Faster initialization, set to false after. */
426 methodname = "dynamic AABB tree, btDbvtBroadphase";
430 // m_broadphase = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes);
431 // m_broadphase = new btSimpleBroadphase(maxNumBoxes,new btSortedOverlappingPairCache());
432 // m_broadphase = new btCudaBroadphase(aabbMin, aabbMax, 8, 8, 8, 8192, 8192, 64, 16);
433 // m_broadphase = new btCudaBroadphase(aabbMin, aabbMax, 12, 12, 12, 8192, 8192, 64, 16);
434 // m_broadphase = new btCudaBroadphase(aabbMin, aabbMax, 16, 16, 16, 8192, 8192, 64, 16);
435 #ifdef USE_CUDA_BROADPHASE
436 m_broadphase = new btCudaBroadphase(aabbMin, aabbMax, 24, 24, 24,maxNumBoxes , maxNumBoxes, 64, 16);
437 // m_broadphase = new btCudaBroadphase(aabbMin, aabbMax, 32, 32, 32, 8192, 8192, 64, 16);
438 methodname = "btCudaBroadphase";
442 m_broadphase = new bt3DGridBroadphase(aabbMin, aabbMax, 24, 24, 24,maxNumBoxes , maxNumBoxes, 64, 16);
443 methodname = "bt3DGridBroadphase";
445 #endif //USE_CUDA_BROADPHASE
450 btDbvtBroadphase* pbp=new btDbvtBroadphase();
452 pbp->m_deferedcollide = true; /* Faster initialization, set to false after. */
454 methodname = "dynamic AABB tree, btDbvtBroadphase";
456 //m_broadphase = new btAxisSweep3(aabbMin,aabbMax,numBoxes,new btNullPairCache());
457 //methodname = "btAxisSweep3+btNullPairCache";
462 BulletSAPCompleteBoxPruningTest::~BulletSAPCompleteBoxPruningTest()
464 DELETEARRAY(mBoxTime);
465 DELETEARRAY(mBoxPtrs);
470 void BulletSAPCompleteBoxPruningTest::Init()
477 mBoxes = new AABB[mNbBoxes];
478 mFlags = new bool[mNbBoxes];
479 mBoxPtrs = new const AABB*[mNbBoxes];
480 mBoxTime = new float[mNbBoxes];
481 for(udword i=0;i<mNbBoxes;i++)
483 Point Center, Extents;
485 Center.x = (UnitRandomFloat()-0.5f) * 100.0f;
486 Center.y = (UnitRandomFloat()-0.5f) * 10.0f;
487 Center.z = (UnitRandomFloat()-0.5f) * 100.0f;
488 Extents.x = 2.0f + UnitRandomFloat() * 2.0f;
489 Extents.y = 2.0f + UnitRandomFloat() * 2.0f;
490 Extents.z = 2.0f + UnitRandomFloat() * 2.0f;
492 mBoxes[i].SetCenterExtents(Center, Extents);
493 mBoxPtrs[i] = &mBoxes[i];
494 btVector3 aabbMin(Center.x-Extents.x,Center.y-Extents.y,Center.z-Extents.z);
495 btVector3 aabbMax(Center.x+Extents.x,Center.y+Extents.y,Center.z+Extents.z);
498 btBroadphaseProxy* proxy = m_broadphase->createProxy(aabbMin,aabbMax,shapeType,&mBoxes[i],1,1,0,0);//m_dispatcher);
499 m_proxies.push_back( proxy );
501 mBoxTime[i] = 2000.0f*UnitRandomFloat();
503 printf("Initialization of %s with %u boxes: %ums\r\n",methodname,mNbBoxes,clock.getTimeMilliseconds());
506 void BulletSAPCompleteBoxPruningTest::Release()
508 DELETEARRAY(mBoxTime);
513 extern int percentUpdate;
514 extern float objectSpeed;
515 extern bool enableDraw;
517 static void TW_CALL NormalMode(void* pdata)
519 btDbvtBroadphase* pb=(btDbvtBroadphase*)pdata;
520 pb->m_deferedcollide = true;
523 static void TW_CALL SlowSpeedMode(void* pdata)
525 btDbvtBroadphase* pb=(btDbvtBroadphase*)pdata;
526 pb->m_deferedcollide = false;
529 void BulletSAPCompleteBoxPruningTest::Select()
531 // Create a tweak bar
533 mBar = TwNewBar("OPC_CompleteBoxPruning");
534 TwAddVarRW(mBar, "Speed", TW_TYPE_FLOAT, &objectSpeed, " min=0.0 max=0.01 step=0.0001");
535 TwAddVarRW(mBar, "Amplitude", TW_TYPE_FLOAT, &mAmplitude, " min=10.0 max=200.0 step=0.1");
538 btDbvtBroadphase* pbp=(btDbvtBroadphase*)m_broadphase;
539 TwAddVarRW(mBar, "Enable culling",TW_TYPE_BOOLCPP,&enableCulling,"");
540 TwAddVarRW(mBar, "Enable occlusion",TW_TYPE_BOOLCPP,&enableOcclusion,"");
541 TwAddVarRW(mBar, "Show culling",TW_TYPE_BOOLCPP,&showCulling,"");
542 TwAddVarRW(mBar, "Show occlusion",TW_TYPE_BOOLCPP,&showOcclusion,"");
543 TwAddVarRW(mBar, "Cull far plane",TW_TYPE_BOOLCPP,&cullFarPlane,"");
544 TwAddVarRW(mBar, "OC Min area",TW_TYPE_FLOAT,&ocb.ocarea,"min=0.0 max=1.0 step=0.001");
545 TwAddVarRW(mBar, "QR Min area",TW_TYPE_FLOAT,&ocb.qrarea,"min=0.0 max=1.0 step=0.001");
546 TwAddVarRW(mBar, "Dyn lkhd",TW_TYPE_INT32,&pbp->m_sets[0].m_lkhd,"min=-1 max=32");
547 TwAddVarRW(mBar, "Fix lkhd",TW_TYPE_INT32,&pbp->m_sets[1].m_lkhd,"min=-1 max=32");
548 TwAddVarRW(mBar, "Dyn opt/f(%)",TW_TYPE_INT32,&pbp->m_dupdates,"min=0 max=100");
549 TwAddVarRW(mBar, "Fix opt/f(%)",TW_TYPE_INT32,&pbp->m_fupdates,"min=0 max=100");
550 TwAddVarRW(mBar, "Cln opt/f(%)",TW_TYPE_INT32,&pbp->m_cupdates,"min=0 max=100");
551 TwAddVarRW(mBar, "Prediction",TW_TYPE_FLOAT,&pbp->m_prediction,"min=0.0 max=2.0 step=0.1");
552 TwAddVarRW(mBar, "Defered collide",TW_TYPE_BOOLCPP,&pbp->m_deferedcollide,"");
553 TwAddVarRO(mBar, "Dyn leafs",TW_TYPE_INT32,&pbp->m_sets[0].m_leaves,"");
554 TwAddVarRO(mBar, "Fix leafs",TW_TYPE_INT32,&pbp->m_sets[1].m_leaves,"");
555 TwAddVarRO(mBar, "Updates ratio",TW_TYPE_FLOAT,&pbp->m_updates_ratio,"");
556 TwAddVarRO(mBar, "Visible",TW_TYPE_INT32,&visiblecount,"");
557 TwAddButton(mBar,"Normal mode",&NormalMode,m_broadphase,"");
558 TwAddButton(mBar,"Slow speed mode",&SlowSpeedMode,m_broadphase,"");
561 printf("SubMethod: %s\r\n",methodname);
564 void BulletSAPCompleteBoxPruningTest::Deselect()
573 bool BulletSAPCompleteBoxPruningTest::UpdateBoxes(int numBoxes)
575 static bool once=true;
577 for(udword i=0;i<(udword)numBoxes;i++)
579 mBoxTime[i] += objectSpeed;
581 Point Center,Extents;
582 mBoxes[i].GetExtents(Extents);
584 Center.x = cosf(mBoxTime[i]*2.17f)*mAmplitude + sinf(mBoxTime[i])*mAmplitude*0.5f;
585 Center.y = cosf(mBoxTime[i]*1.38f)*mAmplitude + sinf(mBoxTime[i]*mAmplitude);
586 Center.z = sinf(mBoxTime[i]*0.777f)*mAmplitude;
588 mBoxes[i].SetCenterExtents(Center, Extents);
593 void BulletSAPCompleteBoxPruningTest::PerformTest()
595 int numUpdatedBoxes = (mNbBoxes*percentUpdate)/100;
598 numUpdatedBoxes = mNbBoxes;
601 UpdateBoxes(numUpdatedBoxes);
606 //CompleteBoxPruning(mNbBoxes, mBoxPtrs, mPairs, Axes(AXES_XZY));
610 for (int i=0;i<numUpdatedBoxes;i++)
614 mBoxPtrs[i]->GetCenter(Center);
615 mBoxPtrs[i]->GetExtents(Extents);
616 btVector3 aabbMin(Center.x-Extents.x,Center.y-Extents.y,Center.z-Extents.z);
617 btVector3 aabbMax(Center.x+Extents.x,Center.y+Extents.y,Center.z+Extents.z);
618 m_broadphase->setAabb(m_proxies[i],aabbMin,aabbMax,0);//m_dispatcher);
621 #ifndef BT_NO_PROFILE
622 if(sBulletProfilerToggle)
624 CProfileManager::Reset();
626 #endif //BT_NO_PROFILE
628 m_broadphase->calculateOverlappingPairs(0);
630 #ifndef BT_NO_PROFILE
631 if(sBulletProfilerToggle)
633 CProfileManager::Increment_Frame_Counter();
634 CProfileManager::dumpAll();
636 #endif //BT_NO_PROFILE
644 //initialization messes up timings
648 ((btDbvtBroadphase*)m_broadphase)->m_deferedcollide=false;
656 for(int i=0;i<m_proxies.size();++i)
658 btDbvtProxy* pa((btDbvtProxy*)m_proxies[i]);
659 for(int j=i+1;j<m_proxies.size();++j)
661 btDbvtProxy* pb((btDbvtProxy*)m_proxies[j]);
662 if(Intersect(pa->aabb,pb->aabb))
666 if(spa>spb) btSwap(spa,spb);
667 if(!m_broadphase->getOverlappingPairCache()->findPair(spa,spb))
670 printf("Cannot find %i,%i\r\n",i,j);
675 if(missedpairs>0) printf("Missed pairs: %u\r\n",missedpairs);
679 // printf("%d pairs colliding\r ", mPairs.GetNbPairs());
681 ZeroMemory(mFlags,sizeof(bool)*mNbBoxes);
683 btOverlappingPairCache* pairCache = m_broadphase->getOverlappingPairCache();
684 const btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
686 for(udword i=0;i<(udword)pairCache->getNumOverlappingPairs();i++)
688 // Flags[pairPtr[i].m_pProxy0->getUid()-1] = true;
689 // Flags[pairPtr[i].m_pProxy1->getUid()-1] = true;
691 j=((AABB*)pairPtr[i].m_pProxy0->m_clientObject)-mBoxes;
693 j=((AABB*)pairPtr[i].m_pProxy1->m_clientObject)-mBoxes;
699 btVector3 aabbMin(-200,-200,-200);
700 btVector3 aabbMax(200,200,200);
702 btVector3 tmpAabbMin,tmpAabbMax;
703 glDisable(GL_DEPTH_TEST);
706 float numP = (float) numParts;
708 for (int i=0;i<numParts;i++)
710 tmpAabbMin[0] = aabbMin[0] + i*(aabbMax[0]-aabbMin[0])/numP;
711 tmpAabbMax[0] = aabbMin[0] + (i+1)*(aabbMax[0]-aabbMin[0])/numP;
713 for (int j=0;j<numParts;j++)
715 tmpAabbMin[1] = aabbMin[1] + j*(aabbMax[1]-aabbMin[1])/numP;
716 tmpAabbMax[1] = aabbMin[1] + (j+1)*(aabbMax[1]-aabbMin[1])/numP;
718 for (int k=0;k<numParts;k++)
720 tmpAabbMin[2] = aabbMin[2] + k*(aabbMax[2]-aabbMin[2])/numP;
721 tmpAabbMax[2] = aabbMin[2] + (k+1)*(aabbMax[2]-aabbMin[2])/numP;
725 CurrentBox.mRot.Identity();
728 Point mmin(tmpAabbMin[0],tmpAabbMin[1],tmpAabbMin[2]);
729 Point mmax(tmpAabbMax[0],tmpAabbMax[1],tmpAabbMax[2]);
731 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
733 glColor4f(i, j,k,0.2);//1.0f, 0.0f);
734 CurrentBox.mCenter = (mmin+mmax)*0.5;
735 CurrentBox.mExtents = (mmax-mmin)*0.5;
747 glEnable(GL_DEPTH_TEST);
748 //glDisable(GL_DEPTH_TEST);
755 sprintf_s(Buffer, sizeof(Buffer), "Bullet %s: %5.1f us (%d cycles) : %d pairs\n", methodname, mProfiler.mMsTime, mProfiler.mCycles,
756 m_broadphase->getOverlappingPairCache()->getNumOverlappingPairs());
758 // m_broadphase)->printStats();
760 GLFontRenderer::print(10.0f, 10.0f, 0.02f, Buffer);
764 static void DrawVolume(const btDbvtVolume& volume,const btVector3& color)
766 const btVector3 mins=volume.Mins();
767 const btVector3 maxs=volume.Maxs();
768 glColor3f(color.x(),color.y(),color.z());
769 glVertex3f(mins.x(),mins.y(),mins.z());
770 glVertex3f(maxs.x(),mins.y(),mins.z());
772 glVertex3f(maxs.x(),mins.y(),mins.z());
773 glVertex3f(maxs.x(),maxs.y(),mins.z());
775 glVertex3f(maxs.x(),maxs.y(),mins.z());
776 glVertex3f(mins.x(),maxs.y(),mins.z());
778 glVertex3f(mins.x(),maxs.y(),mins.z());
779 glVertex3f(mins.x(),mins.y(),mins.z());
781 glVertex3f(mins.x(),mins.y(),maxs.z());
782 glVertex3f(maxs.x(),mins.y(),maxs.z());
784 glVertex3f(maxs.x(),mins.y(),maxs.z());
785 glVertex3f(maxs.x(),maxs.y(),maxs.z());
787 glVertex3f(maxs.x(),maxs.y(),maxs.z());
788 glVertex3f(mins.x(),maxs.y(),maxs.z());
790 glVertex3f(mins.x(),maxs.y(),maxs.z());
791 glVertex3f(mins.x(),mins.y(),maxs.z());
793 glVertex3f(mins.x(),mins.y(),mins.z());
794 glVertex3f(mins.x(),mins.y(),maxs.z());
796 glVertex3f(maxs.x(),mins.y(),mins.z());
797 glVertex3f(maxs.x(),mins.y(),maxs.z());
799 glVertex3f(maxs.x(),maxs.y(),mins.z());
800 glVertex3f(maxs.x(),maxs.y(),maxs.z());
802 glVertex3f(mins.x(),maxs.y(),mins.z());
803 glVertex3f(mins.x(),maxs.y(),maxs.z());
807 void BulletSAPCompleteBoxPruningTest::RenderAll()
810 CurrentBox.mRot.Identity();
811 for(udword i=0;i<mNbBoxes;i++)
813 if(mFlags[i]) glColor3f(1.0f, 0.0f, 0.0f);
814 else glColor3f(0.0f, 1.0f, 0.0f);
815 mBoxes[i].GetCenter(CurrentBox.mCenter);
816 mBoxes[i].GetExtents(CurrentBox.mExtents);
822 void BulletSAPCompleteBoxPruningTest::Render()
824 visiblecount=mNbBoxes;
825 if((!m_isdbvt)||(!enableCulling))
831 btDbvtBroadphase* pbp=(btDbvtBroadphase*)m_broadphase;
834 const int rc=glutGet(GLUT_WINDOW_WIDTH)-(1+margin);
836 const int bc=glutGet(GLUT_WINDOW_HEIGHT)-(1+margin);
837 const btVector3 c00(ComputeWorldRay(lc,tc).x,
838 ComputeWorldRay(lc,tc).y,
839 ComputeWorldRay(lc,tc).z);
840 const btVector3 c10(ComputeWorldRay(rc,tc).x,
841 ComputeWorldRay(rc,tc).y,
842 ComputeWorldRay(rc,tc).z);
843 const btVector3 c01(ComputeWorldRay(lc,bc).x,
844 ComputeWorldRay(lc,bc).y,
845 ComputeWorldRay(lc,bc).z);
846 const btVector3 c11(ComputeWorldRay(rc,bc).x,
847 ComputeWorldRay(rc,bc).y,
848 ComputeWorldRay(rc,bc).z);
850 const btVector3 eye(GetCameraPos().x,GetCameraPos().y,GetCameraPos().z);
851 const btVector3 dir(GetCameraDir().x,GetCameraDir().y,GetCameraDir().z);
852 const btVector3 x00=eye+c00*100;
853 const btVector3 x10=eye+c10*100;
854 const btVector3 x01=eye+c01*100;
855 const btVector3 x11=eye+c11*100;
860 btVector3 planes_n[5];
861 btScalar planes_o[5];
862 static const btScalar farplane=200;
863 static const int nplanes=sizeof(planes_n)/sizeof(planes_n[0]);
864 const int acplanes=cullFarPlane?5:4;
865 planes_n[0] = c01.cross(c00).normalized();
866 planes_n[1] = c10.cross(c11).normalized();
867 planes_n[2] = c00.cross(c10).normalized();
868 planes_n[3] = c11.cross(c01).normalized();
870 planes_o[4] = -(eye+dir*farplane).dot(planes_n[4]);
871 for(int i=0;i<4;++i) planes_o[i]=-(eye.dot(planes_n[i]));
873 struct SceneRenderer : btDbvt::ICollide
876 BulletSAPCompleteBoxPruningTest* self;
878 OcclusionBuffer* ocb;
884 bool Descent(const btDbvtNode* node)
886 return(ocb->queryOccluder(node->volume.Center(),node->volume.Extents()));
888 void Process(const btDbvtNode* node,btScalar depth)
892 void Process(const btDbvtNode* leaf)
894 btBroadphaseProxy* proxy=(btBroadphaseProxy*)leaf->data;
895 int i=((AABB*)proxy->m_clientObject)-self->mBoxes;
896 if(self->mFlags[i]) glColor3f(1.0f, 0.0f, 0.0f);
897 else glColor3f(0.0f, 1.0f, 0.0f);
898 self->mBoxes[i].GetCenter(box.mCenter);
899 self->mBoxes[i].GetExtents(box.mExtents);
900 DrawOBB(box);drawn++;
903 ocb->appendOccluder(btVector3(box.mCenter.x,box.mCenter.y,box.mCenter.z),
904 btVector3(box.mExtents.x,box.mExtents.y,box.mExtents.z));
913 btDbvt::collideOCL(pbp->m_sets[1].m_root,planes_n,planes_o,dir,acplanes,srenderer);
914 btDbvt::collideOCL(pbp->m_sets[0].m_root,planes_n,planes_o,dir,acplanes,srenderer);
918 btDbvt::collideKDOP(pbp->m_sets[1].m_root,planes_n,planes_o,acplanes,srenderer);
919 btDbvt::collideKDOP(pbp->m_sets[0].m_root,planes_n,planes_o,acplanes,srenderer);
921 visiblecount=srenderer.drawn;
922 if(showOcclusion&&enableOcclusion)
924 const btScalar ratio=((float)glutGet(GLUT_WINDOW_HEIGHT))/((float)glutGet(GLUT_WINDOW_WIDTH));
925 glMatrixMode(GL_PROJECTION);
927 glOrtho(-1,1,-1,1,-1,1);
928 glMatrixMode(GL_MODELVIEW);
930 const float mm[]={ 1,0,0,0,
935 glDisable(GL_DEPTH_TEST);
936 glDisable(GL_LIGHTING);
937 const float size=0.6f;
938 const float orgx=0.3f;
939 const float orgy=0.25f;
940 const float left=orgx;
941 const float right=orgx+size;
942 const float top=orgy+size;
943 const float bottom=orgy;
944 ocb.drawBuffer(left,bottom,right,top);
948 const btScalar ratio=((float)glutGet(GLUT_WINDOW_HEIGHT))/((float)glutGet(GLUT_WINDOW_WIDTH));
949 static const float scale=0.004;
951 glMatrixMode(GL_PROJECTION);
953 glOrtho(-1,1,-1*ratio,1*ratio,-1,1);
954 glMatrixMode(GL_MODELVIEW);
956 const float mm[]={ 1,0,0,0,
961 glScalef(scale,scale,scale);
963 glDisable(GL_DEPTH_TEST);
964 glDisable(GL_LIGHTING);
969 struct DebugRenderer : btDbvt::ICollide
971 OcclusionBuffer* ocb;
973 bool AllLeafs(const btDbvtNode* node)
978 bool Descent(const btDbvtNode* node)
980 return(ocb->queryOccluder(node->volume.Center(),node->volume.Extents()));
982 void Process(const btDbvtNode* node,btScalar depth)
986 void Process(const btDbvtNode* node)
990 ocb->appendOccluder(node->volume.Center(),node->volume.Extents());
994 const float f=sid/1023.;
995 DrawVolume(node->volume,btVector3(1,f,f));
1000 if(node->isinternal())
1001 DrawVolume(node->volume,btVector3(0,1,0));
1003 DrawVolume(node->volume,btVector3(1,0,1));
1012 btDbvt::collideOCL(pbp->m_sets[1].m_root,planes_n,planes_o,dir,acplanes,drenderer);
1013 btDbvt::collideOCL(pbp->m_sets[0].m_root,planes_n,planes_o,dir,acplanes,drenderer);
1019 btDbvt::collideKDOP(pbp->m_sets[1].m_root,planes_n,planes_o,acplanes,drenderer);
1020 btDbvt::collideKDOP(pbp->m_sets[0].m_root,planes_n,planes_o,acplanes,drenderer);
1026 glVertex3f(eye.x(),eye.y(),eye.z());
1027 glVertex3f(x00.x(),x00.y(),x00.z());
1028 glVertex3f(eye.x(),eye.y(),eye.z());
1029 glVertex3f(x10.x(),x10.y(),x10.z());
1030 glVertex3f(eye.x(),eye.y(),eye.z());
1031 glVertex3f(x01.x(),x01.y(),x01.z());
1032 glVertex3f(eye.x(),eye.y(),eye.z());
1033 glVertex3f(x11.x(),x11.y(),x11.z());
1035 glVertex3f(x00.x(),x00.y(),x00.z());
1036 glVertex3f(x10.x(),x10.y(),x10.z());
1038 glVertex3f(x10.x(),x10.y(),x10.z());
1039 glVertex3f(x11.x(),x11.y(),x11.z());
1041 glVertex3f(x11.x(),x11.y(),x11.z());
1042 glVertex3f(x01.x(),x01.y(),x01.z());
1044 glVertex3f(x01.x(),x01.y(),x01.z());
1045 glVertex3f(x00.x(),x00.y(),x00.z());
1051 void BulletSAPCompleteBoxPruningTest::KeyboardCallback(unsigned char key, int x, int y)
1057 sBulletProfilerToggle = !sBulletProfilerToggle;
1063 void BulletSAPCompleteBoxPruningTest::MouseCallback(int button, int state, int x, int y)
1067 void BulletSAPCompleteBoxPruningTest::MotionCallback(int x, int y)