resetting manifest requested domain to floor
[platform/upstream/libbullet.git] / Extras / CDTestFramework / BulletSAPCompleteBoxPruningTest.cpp
1 /*
2 BulletSAPCompleteBoxPruningTest, Copyright (c) 2008 Erwin Coumans
3 Part of:
4 CDTestFramework http://codercorner.com
5 Copyright (c) 2007-2008 Pierre Terdiman,  pierre@codercorner.com
6
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:
12
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.
16 */
17
18 //This file was added by Erwin Coumans, to test Bullet SAP performance
19
20 #include "stdafx.h"
21 #include "BulletSAPCompleteBoxPruningTest.h"
22 #include "RenderingHelpers.h"
23 #include "GLFontRenderer.h"
24 #include "btBulletCollisionCommon.h"
25 #include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
26 #include "Camera.h"
27 #ifdef USE_CUDA_BROADPHASE
28 #include "../CUDA/btCudaBroadphase.h"
29 #endif
30 #include "LinearMath/btQuickprof.h"
31
32 int numParts =2;
33
34 bool    enableCulling   =       true;
35 bool    cullFarPlane    =       false;
36 bool    showCulling             =       false;
37 bool    enableOcclusion =       false;
38 bool    showOcclusion   =       true;
39 int             visiblecount    =       0;
40
41 static bool sBulletProfilerToggle = false;
42
43 struct OcclusionBuffer
44 {
45 struct WriteOCL
46         {
47         static inline bool Process(btScalar& q,btScalar v) { if(q<v) q=v;return(false); }
48         };
49 struct QueryOCL
50         {
51         static inline bool Process(btScalar& q,btScalar v) { return(q<=v); }
52         };
53 bool                                                    initialized;
54 btAlignedObjectArray<btScalar>  buffer;
55 int                                                             sizes[2];
56 btScalar                                                scales[2];
57 btScalar                                                offsets[2];
58 btScalar                                                wtrs[16];
59 btVector3                                               eye;
60 btVector3                                               neardist;
61 btScalar                                                ocarea;
62 btScalar                                                qrarea;
63 GLuint                                                  texture;
64                         OcclusionBuffer()
65         {
66         initialized=false;
67         neardist=btVector3(2,2,2);
68         ocarea=(btScalar)0;
69         qrarea=(btScalar)0;
70         }
71 void            setup(int w,int h)
72         {
73         initialized=true;
74         sizes[0]=w;
75         sizes[1]=h;
76         scales[0]=w/2;
77         scales[1]=h/2;
78         offsets[0]=scales[0]+0.5;
79         offsets[1]=scales[1]+0.5;
80         glGenTextures(1,&texture);
81         clear();
82         }
83 void            clear()
84         {
85         buffer.resize(0);
86         buffer.resize(sizes[0]*sizes[1],0);
87         }
88 void            initialize()
89         {
90         if(!initialized)
91                 {
92                 setup(128,128);
93                 }
94         GLint           v[4];
95         GLdouble        m[16],p[16];
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];
100         clear();
101         }
102 void            drawBuffer(     btScalar l,btScalar t,
103                                                 btScalar r,btScalar b)
104         {
105         btAlignedObjectArray<GLubyte>   data;
106         data.resize(buffer.size());
107         for(int i=0;i<data.size();++i)
108                 {
109                 data[i]=int(32/buffer[i])%255;
110                 }
111         glBindTexture(GL_TEXTURE_2D,texture);
112         glDisable(GL_BLEND);
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]);
119         glBegin(GL_QUADS);
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);
125         glEnd();
126         glDisable(GL_TEXTURE_2D);
127         }
128 btVector4       transform(const btVector3& x) const
129         {
130         btVector4       t;
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];
135         return(t);
136         }
137 static bool     project(btVector4* p,int n)
138         {
139         for(int i=0;i<n;++i)
140                 {
141                 const btScalar  iw=1/p[i][3];
142                 p[i][2]=1/p[i][3];
143                 p[i][0]*=p[i][2];
144                 p[i][1]*=p[i][2];
145                 }
146         return(true);
147         }
148 template <const int NP>
149 static int      clip(const btVector4* pi,btVector4* po)
150         {
151         btScalar        s[NP];
152         int                     m=0;
153         for(int i=0;i<NP;++i)
154                 {
155                 s[i]=pi[i][2]+pi[i][3];
156                 if(s[i]<0) m+=1<<i;
157                 }
158         if(m==((1<<NP)-1)) return(0);
159         if(m!=0)
160                 {
161                 int n=0;
162                 for(int i=NP-1,j=0;j<NP;i=j++)
163                         {
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]);
167                         if((t>0)&&(t<1))
168                                 {
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;
173                                 ++n;
174                                 }
175                         if(s[j]>0) po[n++]=b;
176                         }
177                 return(n);
178                 }
179         for(int i=0;i<NP;++i) po[i]=pi[i];
180         return(NP);
181         }
182 template <typename POLICY>
183 inline bool     draw(   const btVector4& a,
184                                         const btVector4& b,
185                                         const btVector4& c,
186                                         const btScalar minarea)
187         {
188         const btScalar          a2=(b-a).cross(c-a)[2];
189         if(a2>0)
190                 {
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;
205                 if((width*height)>0)
206                         {
207                         const int               dx[]={  y[0]-y[1],
208                                                                         y[1]-y[2],
209                                                                         y[2]-y[0]};
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)
223                                 {
224                                 for(int ix=mix;ix<mxx;++ix)
225                                         {
226                                         if((c[0]>=0)&&(c[1]>=0)&&(c[2]>=0))
227                                                 {
228                                                 if(POLICY::Process(scan[ix],v)) return(true);
229                                                 }
230                                         c[0]+=dx[0];c[1]+=dx[1];c[2]+=dx[2];v+=dzx;
231                                         }
232                                 c[0]+=dy[0];c[1]+=dy[1];c[2]+=dy[2];v+=dzy;
233                                 scan+=sizes[0];
234                                 }
235                         }
236                 }
237         return(false);
238         }
239 template <const int NP,typename POLICY>
240 inline bool     clipDraw(       const btVector4* p,
241                                                 btScalar minarea)
242         {
243         btVector4       o[NP*2];
244         const int       n=clip<NP>(p,o);
245         bool            earlyexit=false;
246         project(o,n);
247         for(int i=2;i<n;++i)
248                 {
249                 earlyexit|=draw<POLICY>(o[0],o[i-1],o[i],minarea);
250                 }
251         return(earlyexit);
252         }
253 void            appendOccluder( const btVector3& a,
254                                                         const btVector3& b,
255                                                         const btVector3& c)
256         {
257         const btVector4 p[]={transform(a),transform(b),transform(c)};
258         clipDraw<3,WriteOCL>(p,ocarea);
259         }
260 void            appendOccluder( const btVector3& a,
261                                                         const btVector3& b,
262                                                         const btVector3& c,
263                                                         const btVector3& d)
264         {       
265         const btVector4 p[]={transform(a),transform(b),transform(c),transform(d)};
266         clipDraw<4,WriteOCL>(p,ocarea);
267         }
268 void            appendOccluder( const btVector3& c,
269                                                         const btVector3& e)
270         {
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,
280                                                                 4,5,6,7,
281                                                                 4,7,3,0,
282                                                                 6,5,1,2,
283                                                                 7,6,2,3,
284                                                                 5,4,0,1};
285         for(int i=0;i<(sizeof(d)/sizeof(d[0]));)
286                 {
287                 const btVector4 p[]={   x[d[i++]],
288                                                                 x[d[i++]],
289                                                                 x[d[i++]],
290                                                                 x[d[i++]]};
291                 clipDraw<4,WriteOCL>(p,ocarea);
292                 }       
293         }
294 inline bool     queryOccluder(  const btVector3& a,
295                                                         const btVector3& b,
296                                                         const btVector3& c)
297         {       
298         const btVector4 p[]={transform(a),transform(b),transform(c)};
299         return(clipDraw<3,QueryOCL>(p,qrarea));
300         }
301 inline bool     queryOccluder(  const btVector3& a,
302                                                         const btVector3& b,
303                                                         const btVector3& c,
304                                                         const btVector3& d)
305         {
306         const btVector4 p[]={transform(a),transform(b),transform(c),transform(d)};
307         return(clipDraw<4,QueryOCL>(p,qrarea));
308         }
309 inline bool     queryOccluder(  const btVector3& c,
310                                                         const btVector3& e)
311         {
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]))};
320         for(int i=0;i<8;++i)
321                 {
322                 if((x[i][2]+x[i][3])<=0) return(true);
323                 }
324         static const int        d[]={   1,0,3,2,
325                                                                 4,5,6,7,
326                                                                 4,7,3,0,
327                                                                 6,5,1,2,
328                                                                 7,6,2,3,
329                                                                 5,4,0,1};
330         for(int i=0;i<(sizeof(d)/sizeof(d[0]));)
331                 {
332                 const btVector4 p[]={   x[d[i++]],
333                                                                 x[d[i++]],
334                                                                 x[d[i++]],
335                                                                 x[d[i++]]};
336                 if(clipDraw<4,QueryOCL>(p,qrarea)) return(true);
337                 }
338         return(false);
339         }
340 };
341
342 OcclusionBuffer         ocb;
343
344 BulletSAPCompleteBoxPruningTest::BulletSAPCompleteBoxPruningTest(int numBoxes,int method) :
345         mBar                    (null),
346         mNbBoxes                (numBoxes),
347         mBoxes                  (null),
348         mBoxPtrs                (null),
349         mBoxTime                (null),
350         mAmplitude              (100.0f),
351         m_method(method)
352 {
353         btVector3 aabbMin(-200,-200,-200);
354         btVector3 aabbMax(200,200,200);
355
356         int maxNumBoxes = numBoxes;
357         m_isdbvt=false;
358         bool disableRaycastAccelerator = true;
359         switch (method)
360         {
361         case 1:
362                 m_broadphase = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,0,disableRaycastAccelerator);
363                 methodname      =       "btAxisSweep3";
364                 break;
365         case 2:
366                 m_broadphase = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,new btNullPairCache(),disableRaycastAccelerator);
367                 methodname      =       "btAxisSweep3+btNullPairCache";
368                 break;
369         case 3:
370                 m_broadphase = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,new btSortedOverlappingPairCache(),disableRaycastAccelerator);
371                 methodname      =       "btAxisSweep3+btSortedOverlappingPairCache";
372                 break;
373         case 4:
374                 m_broadphase = new btSimpleBroadphase(maxNumBoxes,new btSortedOverlappingPairCache());
375                 methodname      =       "btSimpleBroadphase+btSortedOverlappingPairCache";
376                 break;
377         case 5:
378                 m_broadphase = new btSimpleBroadphase(maxNumBoxes,new btNullPairCache());
379                 methodname      =       "btSimpleBroadphase+btNullPairCache";
380                 break;
381
382 /*      case 6:
383                 {
384                 methodname      =       "btMultiSapBroadphase";
385                         btMultiSapBroadphase* multiSap = new btMultiSapBroadphase(maxNumBoxes);
386                         m_broadphase = multiSap;
387
388                         btVector3 tmpAabbMin,tmpAabbMax;
389         
390                         float numP = (float) numParts;
391
392                         for (int i=0;i<numParts;i++)
393                         {
394                                 tmpAabbMin[0] = aabbMin[0] + i*(aabbMax[0]-aabbMin[0])/numP;
395                                 tmpAabbMax[0] = aabbMin[0] + (i+1)*(aabbMax[0]-aabbMin[0])/numP;
396
397                                 for (int j=0;j<numParts;j++)
398                                 {
399                                         tmpAabbMin[1] = aabbMin[1] + j*(aabbMax[1]-aabbMin[1])/numP;
400                                         tmpAabbMax[1] = aabbMin[1] + (j+1)*(aabbMax[1]-aabbMin[1])/numP;
401
402                                         for (int k=0;k<numParts;k++)
403                                         {
404                                                 tmpAabbMin[2] = aabbMin[2] + k*(aabbMax[2]-aabbMin[2])/numP;
405                                                 tmpAabbMax[2] = aabbMin[2] + (k+1)*(aabbMax[2]-aabbMin[2])/numP;
406
407                                                 btAxisSweep3* childBp = new btAxisSweep3(tmpAabbMin,tmpAabbMax,maxNumBoxes,multiSap->getOverlappingPairCache(),disableRaycastAccelerator);
408                                                 multiSap->getBroadphaseArray().push_back(childBp);
409                                         }
410                                 }
411                         }
412                 
413         //              btAxisSweep3* childBp = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,multiSap->getOverlappingPairCache());
414         //      multiSap->getBroadphaseArray().push_back(childBp);
415                         multiSap->buildTree(aabbMin,aabbMax);
416         
417                 }
418                 break;
419                 */
420         case    7:
421                 {
422                 btDbvtBroadphase*       pbp=new btDbvtBroadphase();
423                 m_broadphase                    =       pbp;
424                 pbp->m_deferedcollide   =       true;   /* Faster initialization, set to false after.   */ 
425                 m_isdbvt                                =       true;
426                 methodname                              =       "dynamic AABB tree, btDbvtBroadphase";
427                 }
428                 break;
429         case 8:
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";
439                 break;
440
441         case 9:
442                 m_broadphase = new bt3DGridBroadphase(aabbMin, aabbMax, 24, 24, 24,maxNumBoxes , maxNumBoxes, 64, 16);
443                 methodname      =       "bt3DGridBroadphase";
444                 break;
445 #endif //USE_CUDA_BROADPHASE
446
447         default:
448                 {
449
450                         btDbvtBroadphase*       pbp=new btDbvtBroadphase();
451                         m_broadphase                    =       pbp;
452                         pbp->m_deferedcollide   =       true;   /* Faster initialization, set to false after.   */ 
453                         m_isdbvt                                =       true;
454                         methodname                              =       "dynamic AABB tree, btDbvtBroadphase";
455
456                         //m_broadphase = new btAxisSweep3(aabbMin,aabbMax,numBoxes,new btNullPairCache());
457                         //methodname    =       "btAxisSweep3+btNullPairCache";
458                 }
459         }
460 }
461
462 BulletSAPCompleteBoxPruningTest::~BulletSAPCompleteBoxPruningTest()
463 {
464         DELETEARRAY(mBoxTime);
465         DELETEARRAY(mBoxPtrs);
466         DELETEARRAY(mBoxes);
467         delete m_broadphase;
468 }
469
470 void BulletSAPCompleteBoxPruningTest::Init()
471 {
472         btClock         clock;
473         m_firstTime = true;     
474         SRand(0);
475
476
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++)
482         {
483                 Point Center, Extents;
484
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;
491
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);
496                 int shapeType =0;
497                 void* userPtr = 0;
498                 btBroadphaseProxy* proxy = m_broadphase->createProxy(aabbMin,aabbMax,shapeType,&mBoxes[i],1,1,0,0);//m_dispatcher);
499                 m_proxies.push_back( proxy );
500
501                 mBoxTime[i] = 2000.0f*UnitRandomFloat();
502         }
503         printf("Initialization of %s with %u boxes: %ums\r\n",methodname,mNbBoxes,clock.getTimeMilliseconds());
504 }
505
506 void BulletSAPCompleteBoxPruningTest::Release()
507 {
508         DELETEARRAY(mBoxTime);
509         DELETEARRAY(mBoxes);
510 }
511
512 extern int              doTree;
513 extern int              percentUpdate;
514 extern float    objectSpeed;
515 extern bool             enableDraw;
516
517 static void TW_CALL NormalMode(void* pdata)
518 {
519 btDbvtBroadphase*       pb=(btDbvtBroadphase*)pdata;
520 pb->m_deferedcollide    =       true;
521 }
522
523 static void TW_CALL SlowSpeedMode(void* pdata)
524 {
525 btDbvtBroadphase*       pb=(btDbvtBroadphase*)pdata;
526 pb->m_deferedcollide    =       false;
527 }
528
529 void BulletSAPCompleteBoxPruningTest::Select()
530 {
531         // Create a tweak bar
532         {
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");
536                 if(m_isdbvt)
537                         {
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,"");
559                         }
560         }
561         printf("SubMethod: %s\r\n",methodname);
562 }
563
564 void BulletSAPCompleteBoxPruningTest::Deselect()
565 {
566         if(mBar)
567         {
568                 TwDeleteBar(mBar);
569                 mBar = null;
570         }
571 }
572
573 bool BulletSAPCompleteBoxPruningTest::UpdateBoxes(int numBoxes)
574 {
575         static bool once=true;
576
577         for(udword i=0;i<(udword)numBoxes;i++)
578         {
579                 mBoxTime[i] += objectSpeed;
580
581                 Point Center,Extents;
582                 mBoxes[i].GetExtents(Extents);
583
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;
587
588                 mBoxes[i].SetCenterExtents(Center, Extents);
589         }
590         return true;
591 }
592
593 void BulletSAPCompleteBoxPruningTest::PerformTest()
594 {
595         int numUpdatedBoxes = (mNbBoxes*percentUpdate)/100;
596         if (m_firstTime)
597         {
598                 numUpdatedBoxes = mNbBoxes;
599         }
600         mProfiler.Start();
601         UpdateBoxes(numUpdatedBoxes);
602         
603
604         mPairs.ResetPairs();
605         
606         //CompleteBoxPruning(mNbBoxes, mBoxPtrs, mPairs, Axes(AXES_XZY));
607         ///add batch query?
608         
609
610         for (int i=0;i<numUpdatedBoxes;i++)
611         {
612                 Point Center;
613                 Point Extents;
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);
619         }
620
621 #ifndef BT_NO_PROFILE
622         if(sBulletProfilerToggle)
623         {
624                 CProfileManager::Reset();
625         }
626 #endif //BT_NO_PROFILE
627
628         m_broadphase->calculateOverlappingPairs(0);
629
630 #ifndef BT_NO_PROFILE
631         if(sBulletProfilerToggle)
632         {
633                 CProfileManager::Increment_Frame_Counter();
634                 CProfileManager::dumpAll();
635         }
636 #endif //BT_NO_PROFILE
637         
638
639         mProfiler.End();
640         mProfiler.Accum();
641
642         if (m_firstTime)
643         {
644                 //initialization messes up timings
645                 m_firstTime = false;
646                 if(m_isdbvt)
647                         {
648                         ((btDbvtBroadphase*)m_broadphase)->m_deferedcollide=false;
649                         }
650                 mProfiler.Reset();              
651         }
652         
653         #if 0
654                 {
655                 int     missedpairs=0;
656                 for(int i=0;i<m_proxies.size();++i)
657                         {
658                         btDbvtProxy*    pa((btDbvtProxy*)m_proxies[i]);
659                         for(int j=i+1;j<m_proxies.size();++j)
660                                 {
661                                 btDbvtProxy*    pb((btDbvtProxy*)m_proxies[j]);                         
662                                 if(Intersect(pa->aabb,pb->aabb))
663                                         {
664                                         btDbvtProxy*    spa=pa;
665                                         btDbvtProxy*    spb=pb;
666                                         if(spa>spb) btSwap(spa,spb);
667                                         if(!m_broadphase->getOverlappingPairCache()->findPair(spa,spb))
668                                                 {
669                                                 ++missedpairs;
670                                                 printf("Cannot find %i,%i\r\n",i,j);
671                                                 }
672                                         }
673                                 }
674                         }
675                 if(missedpairs>0) printf("Missed pairs: %u\r\n",missedpairs);
676                 }
677         #endif
678         
679 //      printf("%d pairs colliding\r     ", mPairs.GetNbPairs());
680
681         ZeroMemory(mFlags,sizeof(bool)*mNbBoxes);
682
683         btOverlappingPairCache* pairCache = m_broadphase->getOverlappingPairCache();
684         const btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
685
686         for(udword i=0;i<(udword)pairCache->getNumOverlappingPairs();i++)
687         {
688 //              Flags[pairPtr[i].m_pProxy0->getUid()-1] = true;
689 //              Flags[pairPtr[i].m_pProxy1->getUid()-1] = true;
690                 int     j;
691                 j=((AABB*)pairPtr[i].m_pProxy0->m_clientObject)-mBoxes;
692                 mFlags[j] = true;
693                 j=((AABB*)pairPtr[i].m_pProxy1->m_clientObject)-mBoxes;
694                 mFlags[j] = true;
695         }
696         
697         if(enableDraw)
698                 {
699                 btVector3 aabbMin(-200,-200,-200);
700                 btVector3 aabbMax(200,200,200);
701
702                 btVector3 tmpAabbMin,tmpAabbMax;        
703                 glDisable(GL_DEPTH_TEST);
704
705
706                                 float numP = (float) numParts;
707                 
708                                 for (int i=0;i<numParts;i++)
709                                 {
710                                         tmpAabbMin[0] = aabbMin[0] + i*(aabbMax[0]-aabbMin[0])/numP;
711                                         tmpAabbMax[0] = aabbMin[0] + (i+1)*(aabbMax[0]-aabbMin[0])/numP;
712
713                                         for (int j=0;j<numParts;j++)
714                                         {
715                                                 tmpAabbMin[1] = aabbMin[1] + j*(aabbMax[1]-aabbMin[1])/numP;
716                                                 tmpAabbMax[1] = aabbMin[1] + (j+1)*(aabbMax[1]-aabbMin[1])/numP;
717
718                                                 for (int k=0;k<numParts;k++)
719                                                 {
720                                                         tmpAabbMin[2] = aabbMin[2] + k*(aabbMax[2]-aabbMin[2])/numP;
721                                                         tmpAabbMax[2] = aabbMin[2] + (k+1)*(aabbMax[2]-aabbMin[2])/numP;
722
723                                 
724                                         OBB CurrentBox;
725                                         CurrentBox.mRot.Identity();
726                                         
727                                         {
728                                                 Point mmin(tmpAabbMin[0],tmpAabbMin[1],tmpAabbMin[2]);
729                                                 Point mmax(tmpAabbMax[0],tmpAabbMax[1],tmpAabbMax[2]);
730
731                                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
732                                                 glEnable(GL_BLEND);
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;
736                                         
737                                                 DrawOBB(CurrentBox);
738
739                                         }
740                                 }
741                         }
742
743                 }
744
745                         
746
747                 glEnable(GL_DEPTH_TEST);
748                 //glDisable(GL_DEPTH_TEST);
749
750                 glDisable(GL_BLEND);
751                 Render();
752                 }
753         
754         char Buffer[4096];
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());
757
758 //      m_broadphase)->printStats();
759
760         GLFontRenderer::print(10.0f, 10.0f, 0.02f, Buffer);
761 }
762
763 //
764 static void     DrawVolume(const btDbvtVolume& volume,const btVector3& color)
765 {
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());
771
772 glVertex3f(maxs.x(),mins.y(),mins.z());
773 glVertex3f(maxs.x(),maxs.y(),mins.z());
774
775 glVertex3f(maxs.x(),maxs.y(),mins.z());
776 glVertex3f(mins.x(),maxs.y(),mins.z());
777
778 glVertex3f(mins.x(),maxs.y(),mins.z());
779 glVertex3f(mins.x(),mins.y(),mins.z());
780
781 glVertex3f(mins.x(),mins.y(),maxs.z());
782 glVertex3f(maxs.x(),mins.y(),maxs.z());
783
784 glVertex3f(maxs.x(),mins.y(),maxs.z());
785 glVertex3f(maxs.x(),maxs.y(),maxs.z());
786
787 glVertex3f(maxs.x(),maxs.y(),maxs.z());
788 glVertex3f(mins.x(),maxs.y(),maxs.z());
789
790 glVertex3f(mins.x(),maxs.y(),maxs.z());
791 glVertex3f(mins.x(),mins.y(),maxs.z());
792
793 glVertex3f(mins.x(),mins.y(),mins.z());
794 glVertex3f(mins.x(),mins.y(),maxs.z());
795
796 glVertex3f(maxs.x(),mins.y(),mins.z());
797 glVertex3f(maxs.x(),mins.y(),maxs.z());
798
799 glVertex3f(maxs.x(),maxs.y(),mins.z());
800 glVertex3f(maxs.x(),maxs.y(),maxs.z());
801
802 glVertex3f(mins.x(),maxs.y(),mins.z());
803 glVertex3f(mins.x(),maxs.y(),maxs.z());
804 }
805
806 //
807 void BulletSAPCompleteBoxPruningTest::RenderAll()
808 {
809 OBB CurrentBox;
810 CurrentBox.mRot.Identity();
811 for(udword i=0;i<mNbBoxes;i++)
812         {
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);
817         DrawOBB(CurrentBox);
818         }
819 }
820
821 //
822 void BulletSAPCompleteBoxPruningTest::Render()
823 {
824 visiblecount=mNbBoxes;
825 if((!m_isdbvt)||(!enableCulling))
826         {       
827         RenderAll();
828         }
829         else
830         {
831         btDbvtBroadphase*       pbp=(btDbvtBroadphase*)m_broadphase;
832         const int                       margin=0;
833         const int                       lc=margin;
834         const int                       rc=glutGet(GLUT_WINDOW_WIDTH)-(1+margin);
835         const int                       tc=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);
849         
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;
856         
857         ocb.initialize();
858         ocb.eye=eye;
859         
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();
869         planes_n[4]     =       -dir;
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]));
872         
873         struct  SceneRenderer : btDbvt::ICollide
874                 {
875                 int                                                                     drawn;
876                 BulletSAPCompleteBoxPruningTest*        self;
877                 OBB                                                                     box;
878                 OcclusionBuffer*                                        ocb;
879                                 SceneRenderer()
880                         {
881                         drawn=0;
882                         box.mRot.Identity();
883                         }
884                 bool    Descent(const btDbvtNode* node)
885                         {
886                         return(ocb->queryOccluder(node->volume.Center(),node->volume.Extents()));
887                         }
888                 void    Process(const btDbvtNode* node,btScalar depth)
889                         {
890                         Process(node);
891                         }
892                 void    Process(const btDbvtNode* leaf)
893                         {       
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++;
901                         if(ocb)
902                                 {
903                                 ocb->appendOccluder(btVector3(box.mCenter.x,box.mCenter.y,box.mCenter.z),
904                                                                         btVector3(box.mExtents.x,box.mExtents.y,box.mExtents.z));
905                                 }
906                         }
907                 }       srenderer;
908         srenderer.self=this;
909         srenderer.ocb=0;
910         if(enableOcclusion)
911                 {
912                 srenderer.ocb=&ocb;
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);             
915                 }
916                 else
917                 {
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);                
920                 }
921         visiblecount=srenderer.drawn;
922         if(showOcclusion&&enableOcclusion)
923                 {
924                 const btScalar          ratio=((float)glutGet(GLUT_WINDOW_HEIGHT))/((float)glutGet(GLUT_WINDOW_WIDTH)); 
925                 glMatrixMode(GL_PROJECTION);
926                 glLoadIdentity();
927                 glOrtho(-1,1,-1,1,-1,1);
928                 glMatrixMode(GL_MODELVIEW);
929                 glLoadIdentity();
930                 const float     mm[]={  1,0,0,0,
931                                                         0,1,0,0,
932                                                         0,0,0,1,
933                                                         0,0,0,1};
934                 glMultMatrixf(mm);
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);
945                 }
946         if(showCulling)
947                 {
948                 const btScalar          ratio=((float)glutGet(GLUT_WINDOW_HEIGHT))/((float)glutGet(GLUT_WINDOW_WIDTH)); 
949                 static const float      scale=0.004;
950                 
951                 glMatrixMode(GL_PROJECTION);
952                 glLoadIdentity();
953                 glOrtho(-1,1,-1*ratio,1*ratio,-1,1);
954                 glMatrixMode(GL_MODELVIEW);
955                 glLoadIdentity();
956                 const float     mm[]={  1,0,0,0,
957                                                         0,0,1,0,
958                                                         0,1,0,0,
959                                                         0,0,0,1};
960                 glMultMatrixf(mm);
961                 glScalef(scale,scale,scale);
962                 
963                 glDisable(GL_DEPTH_TEST);       
964                 glDisable(GL_LIGHTING); 
965                 
966                 glBegin(GL_LINES);
967                 glColor4f(1,1,1,1);     
968                 
969                 struct  DebugRenderer : btDbvt::ICollide
970                 {
971                 OcclusionBuffer*        ocb;
972                 int                                     sid;
973                 bool    AllLeafs(const btDbvtNode* node)
974                         {
975                         Process(node);
976                         return(false);
977                         }
978                 bool    Descent(const btDbvtNode* node)
979                         {
980                         return(ocb->queryOccluder(node->volume.Center(),node->volume.Extents()));
981                         }
982                 void    Process(const btDbvtNode* node,btScalar depth)
983                         {
984                         Process(node);
985                         }
986                 void    Process(const btDbvtNode* node)
987                         {
988                         if(ocb)
989                                 {
990                                 ocb->appendOccluder(node->volume.Center(),node->volume.Extents());
991                                 }
992                         if(sid>=0)
993                                 {
994                                 const float f=sid/1023.;
995                                 DrawVolume(node->volume,btVector3(1,f,f));
996                                 sid=(sid+1)%1024;
997                                 }
998                                 else
999                                 {
1000                                 if(node->isinternal())
1001                                         DrawVolume(node->volume,btVector3(0,1,0));
1002                                         else
1003                                         DrawVolume(node->volume,btVector3(1,0,1));
1004                                 }
1005                         }
1006                 }       drenderer;
1007                 if(enableOcclusion)
1008                         {
1009                         drenderer.ocb=&ocb;
1010                         drenderer.sid=0;
1011                         ocb.clear();
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);                     
1014                         }
1015                         else
1016                         {
1017                         drenderer.ocb=0;
1018                         drenderer.sid=-1;
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);                        
1021                         }
1022                 glEnd();
1023                 
1024                 glBegin(GL_LINES);
1025                 glColor4f(1,1,1,1);
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());
1034                 
1035                 glVertex3f(x00.x(),x00.y(),x00.z());
1036                 glVertex3f(x10.x(),x10.y(),x10.z());
1037                 
1038                 glVertex3f(x10.x(),x10.y(),x10.z());
1039                 glVertex3f(x11.x(),x11.y(),x11.z());
1040                 
1041                 glVertex3f(x11.x(),x11.y(),x11.z());
1042                 glVertex3f(x01.x(),x01.y(),x01.z());
1043                 
1044                 glVertex3f(x01.x(),x01.y(),x01.z());
1045                 glVertex3f(x00.x(),x00.y(),x00.z());    
1046                 glEnd();
1047                 }
1048         }
1049 }
1050
1051 void BulletSAPCompleteBoxPruningTest::KeyboardCallback(unsigned char key, int x, int y)
1052 {
1053         switch (key)
1054         {
1055                 case 'p':
1056                 case 'P':
1057                         sBulletProfilerToggle = !sBulletProfilerToggle;
1058                         break;
1059                 default : break;
1060         }
1061 }
1062
1063 void BulletSAPCompleteBoxPruningTest::MouseCallback(int button, int state, int x, int y)
1064 {
1065 }
1066
1067 void BulletSAPCompleteBoxPruningTest::MotionCallback(int x, int y)
1068 {
1069 }