Initialize libbullet git in 2.0_beta.
[platform/upstream/libbullet.git] / Extras / CDTestFramework / CDTestFramework.cpp
1 /*
2 CDTestFramework http://codercorner.com
3 Copyright (c) 2007-2008 Pierre Terdiman,  pierre@codercorner.com
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose, 
8 including commercial applications, and to alter it and redistribute it freely, 
9 subject to the following restrictions:
10
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15
16 #include "stdafx.h"
17
18 #include "CollisionTest.h"
19 #include "SphereMeshQuery.h"
20 #include "OBBMeshQuery.h"
21 #include "CapsuleMeshQuery.h"
22 #include "CompleteBoxPruning.h"
23 #include "BulletSAPCompleteBoxPruningTest.h"
24 #include "BulletSAPCompleteBoxPruningTest.h"
25 #include "BipartiteBoxPruning.h"
26 #include "OpcodeArraySAPTest.h"
27 #include "RenderingHelpers.h"
28 #include "Terrain.h"
29 #include "Camera.h"
30 #include "GLFontRenderer.h"
31 #include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
32 #include "LinearMath/btQuickprof.h"
33
34 #define NUM_SAP_BOXES 8192
35 //#define NUM_SAP_BOXES 16384
36 //#define NUM_SAP_BOXES 1024
37
38 int             percentUpdate   =       100;
39 //float objectSpeed             =       0.005f;
40 float   objectSpeed             =       0.01f;
41 bool    enableDraw              =       true;
42
43 //Broadphase comparison
44 //Static case (updating 10% of objects to same position ( -> no swaps)
45 //number of objects //OPCODE BoxPruning / Bullet SAP / Bullet MultiSAP
46 //1024                     0.35ms, 0.03ms, 0.15ms
47 //8192                       21ms, 0.2ms, 5ms
48 //16384                   92ms , 0.5ms, 28ms
49
50 //Dynamic case, 10% objects are moving as fast as this testbed allows (0.01?)
51 //number of objects //OPCODE BoxPruning / Bullet SAP / Bullet MultiSAP
52 //1024                                          0.35ms, 0.2ms, 0.25ms
53 //8192                        21ms , 15ms , 13ms
54 //16384                    92ms,  80ms,  49ms
55
56
57 #define WINDOW_WIDTH    1024
58 #define WINDOW_HEIGHT   768
59
60 static int gMouseX = 0;
61 static int gMouseY = 0;
62 static int gButton = 0;
63
64 static TwBar* gMainBar = null;
65 enum TestIndex
66 {
67 //      TEST_SPHERE_MESH_QUERY,
68 //      TEST_OBB_MESH_QUERY,
69 //      TEST_CAPSULE_MESH_QUERY,
70 //      TEST_COMPLETE_BOX_PRUNING=0,
71         TEST_COMPLETE_BOX_PRUNING_8192,
72 //      TEST_BULLET_SAP_1024,
73 //      TEST_BULLET_SAP_8192,
74 //      TEST_BULLET_SAP_SORTEDPAIRS_8192,
75 //      TEST_BULLET_MULTISAP_8192,
76 //      TEST_BIPARTITE_BOX_PRUNING,
77         TEST_DBVT_8192,
78         TEST_BULLET_CUDA_8192,
79         TEST_BULLET_3DGRID_8192,
80         TEST_OPCODE_ARRAY_SAP,
81         MAX_NB_TESTS
82 };
83
84 //static int gTest = TEST_DBVT_8192;//TEST_BULLET_MULTISAP_8192;
85 //static int gSelectedTest = TEST_DBVT_8192;//TEST_BULLET_MULTISAP_8192;
86 static int gTest = TEST_BULLET_CUDA_8192;
87 static int gSelectedTest = TEST_BULLET_CUDA_8192;
88 static CollisionTest* gCollisionTests[MAX_NB_TESTS];
89
90 static GLFontRenderer gFnt;
91
92 /////////////////
93
94 static void KeyboardCallback(unsigned char key, int x, int y)
95 {
96         switch (key)
97         {
98                 case 27:        exit(0); break;
99
100                 case '+':
101                 {
102                         if(gTest!=MAX_NB_TESTS-1)
103                         {
104                                 gCollisionTests[gTest]->Deselect();
105                                 gTest++;
106                                 gSelectedTest++;
107                                 gCollisionTests[gTest]->Select();
108                         }
109                 }
110                 break;
111
112                 case '-':
113                 {
114                         if(gTest)
115                         {
116                                 gCollisionTests[gTest]->Deselect();
117                                 gTest--;
118                                 gSelectedTest--;
119                                 gCollisionTests[gTest]->Select();
120                         }
121                 }
122                 break;
123
124                 case 101:       MoveCameraForward();                                                                    break;
125                 case 103:       MoveCameraBackward();                                                                   break;
126                 case 100:       MoveCameraRight();                                                                              break;
127                 case 102:       MoveCameraLeft();                                                                               break;
128                 default:        gCollisionTests[gTest]->KeyboardCallback(key, x, y);    break;
129         }
130
131         TwEventKeyboardGLUT(key, x, y);
132 }
133
134 static void ArrowKeyCallback(int key, int x, int y)
135 {
136         KeyboardCallback(key, x, y);
137
138         TwEventSpecialGLUT(key, x, y);
139 }
140         
141 static void MouseCallback(int button, int state, int x, int y)
142 {
143         gButton = button;
144         gMouseX = x;
145         gMouseY = y;
146
147         if(!TwEventMouseButtonGLUT(button, state, x, y))
148         {
149                 gCollisionTests[gTest]->MouseCallback(button, state, x, y);
150         }
151 }
152
153 static void MotionCallback(int x, int y)
154 {
155         if(!TwEventMouseMotionGLUT(x, y))
156         {
157                 if(gButton==2)
158                 {
159                         int dx = gMouseX - x;
160                         int dy = gMouseY - y;
161                         
162                         RotateCamera(dx, dy);
163
164                         gMouseX = x;
165                         gMouseY = y;
166                 }
167                 else
168                         gCollisionTests[gTest]->MotionCallback(x, y);
169         }
170 }
171
172 static void RenderCallback()
173 {
174         // Clear buffers
175         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
176     
177         // Setup camera
178         glMatrixMode(GL_PROJECTION);
179         SetupCameraMatrix();
180
181         glMatrixMode(GL_MODELVIEW);
182         glLoadIdentity();
183
184         glEnable(GL_LIGHTING);
185
186         if(0 /*gRenderWireframe*/)
187                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
188         else
189                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
190
191         gCollisionTests[gTest]->PerformTest();
192
193         // Draw tweak bars
194         TwDraw();
195
196         glutSwapBuffers();
197         glutPostRedisplay();
198
199         if(gSelectedTest!=gTest)
200         {
201                 gCollisionTests[gTest]->Deselect();
202                 gTest = gSelectedTest;
203                 gCollisionTests[gTest]->Select();
204         }
205 }
206
207 static void ReshapeCallback(int width, int height)
208 {
209         glViewport(0, 0, width, height);
210
211         // Send the new window size to AntTweakBar
212         TwWindowSize(width, height);
213 }
214
215 static void IdleCallback()
216 {
217         glutPostRedisplay();
218 }
219
220 static void Terminate()
221 {
222         ReleaseTerrain();
223
224         for(int i=0;i<MAX_NB_TESTS;i++)
225         {
226                 gCollisionTests[i]->Release();
227                 DELETESINGLE(gCollisionTests[i]);
228         }
229
230         if(gMainBar)
231         {
232                 TwDeleteBar(gMainBar);
233                 gMainBar = null;
234         }
235
236         TwTerminate();
237 }
238
239 int main(int argc, char** argv)
240 {
241         {
242         ::SetPriorityClass(::GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
243         /*btDbvt::benchmark();
244         exit(0);*/
245         }
246         // Initialize AntTweakBar
247         // (note that AntTweakBar could also be intialize after GLUT, no matter)
248         if(!TwInit(TW_OPENGL, NULL))
249         {
250                 // A fatal error occured        
251                 fprintf(stderr, "AntTweakBar initialization failed: %s\n", TwGetLastError());
252         }
253
254         // Initialize Glut
255         glutInit(&argc, argv);
256         glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
257         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
258         int mainHandle = glutCreateWindow("CD Test Framework");
259
260 /*      HWND hWnd;
261         hWnd = FindWindow("GLUT", "CD Test Framework");
262         RECT Rect;
263         GetWindowRect(hWnd, &Rect);
264 */
265         glutCreateMenu(NULL);
266         glutSetWindow(mainHandle);
267         glutDisplayFunc(RenderCallback);
268         glutReshapeFunc(ReshapeCallback);
269         glutIdleFunc(IdleCallback);
270         glutKeyboardFunc(KeyboardCallback);
271         glutSpecialFunc(ArrowKeyCallback);
272         glutMouseFunc(MouseCallback);
273         glutMotionFunc(MotionCallback);
274         atexit(Terminate);      // Called after glutMainLoop ends
275
276         glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT);
277         TwGLUTModifiersFunc(glutGetModifiers);
278
279         // Setup default render states
280         glClearColor(0.3f, 0.4f, 0.5f, 1.0);
281         glEnable(GL_DEPTH_TEST);
282         glEnable(GL_COLOR_MATERIAL);
283         glEnable(GL_CULL_FACE);
284         glDepthFunc(GL_LEQUAL);
285
286         // Setup lighting
287         glEnable(GL_LIGHTING);
288         float AmbientColor[] = { 0.0f, 0.1f, 0.2f, 0.0f };              glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientColor);
289         float DiffuseColor[] = { 1.0f, 1.0f, 1.0f, 0.0f };              glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseColor);
290         float SpecularColor[] = { 0.0f, 0.0f, 0.0f, 0.0f };             glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularColor);
291         float Position[] = { -10.0f, 1000.0f, -4.0f, 1.0f };    glLightfv(GL_LIGHT0, GL_POSITION, Position);
292         glEnable(GL_LIGHT0);
293
294         gFnt.init();
295         gFnt.setScreenResolution(WINDOW_WIDTH, WINDOW_HEIGHT);
296         gFnt.setColor(1.0f, 1.0f, 1.0f, 1.0f);
297
298         CreateTerrain();
299
300         // Create main tweak bar
301         {
302                 gMainBar = TwNewBar("CollisionTests");
303                 TwEnumVal testEV[MAX_NB_TESTS] = {
304 //                      {TEST_SPHERE_MESH_QUERY, "Sphere-mesh query"},
305 //                      {TEST_OBB_MESH_QUERY, "OBB-mesh query"},
306 //                      {TEST_CAPSULE_MESH_QUERY, "Capsule-mesh query"},
307 //                      {TEST_COMPLETE_BOX_PRUNING, "OPCODE SAP 1024"},
308                         {TEST_COMPLETE_BOX_PRUNING_8192, "OPCODE BOX PRUNING 8192"},
309 //                      {TEST_BULLET_SAP_1024, "Bullet SAP HASHPAIR 1024"},
310 //                      {TEST_BULLET_SAP_8192, "Bullet SAP HASHPAIR 8192"},
311 //                      {TEST_BULLET_SAP_SORTEDPAIRS_8192, "Bullet SAP SORTEDPAIR 8192"},
312 //                      {TEST_BULLET_MULTISAP_8192, "Bullet MultiSAP 8192"},
313 //                      {TEST_BIPARTITE_BOX_PRUNING, "Bipartite box pruning"},
314                         {TEST_DBVT_8192, "Bullet DBVT 8192"},
315                         {TEST_BULLET_CUDA_8192, "Bullet CUDA 8192"},
316                         {TEST_BULLET_3DGRID_8192, "Bullet 3D Grid 8192"},
317                         {TEST_OPCODE_ARRAY_SAP, "OPCODE ARRAY SAP"},
318                 };
319                 TwType testType = TwDefineEnum("CollisionTest", testEV, MAX_NB_TESTS);
320                 TwAddVarRW(gMainBar, "CollisionTests", testType, &gSelectedTest, "");           
321                 TwAddVarRW(gMainBar, "% of updates",TW_TYPE_INT32,&percentUpdate,"min=0 max=100");
322                 TwAddVarRW(gMainBar, "Draw",TW_TYPE_BOOLCPP,&enableDraw,"");
323         }
324
325         // Create tests
326         gTest = 0;
327 //      gCollisionTests[TEST_SPHERE_MESH_QUERY] = new SphereMeshQuery;
328 //      gCollisionTests[TEST_OBB_MESH_QUERY]    = new OBBMeshQuery;
329 //      gCollisionTests[TEST_CAPSULE_MESH_QUERY]        = new CapsuleMeshQuery;
330 //      gCollisionTests[TEST_COMPLETE_BOX_PRUNING]      = new CompleteBoxPruningTest(NUM_SAP_BOXES);
331  //     gCollisionTests[TEST_COMPLETE_BOX_PRUNING_8192] = new CompleteBoxPruningTest(NUM_SAP_BOXES);
332         gCollisionTests[TEST_COMPLETE_BOX_PRUNING_8192] = new CompleteBoxPruningTest(NUM_SAP_BOXES);
333 //      gCollisionTests[TEST_BULLET_SAP_1024]   = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,1);
334 //      gCollisionTests[TEST_BULLET_SAP_8192]   = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,1);
335 //      gCollisionTests[TEST_BULLET_SAP_SORTEDPAIRS_8192]       = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,3);
336 //      gCollisionTests[TEST_BULLET_MULTISAP_8192]      = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,6);
337 //      gCollisionTests[TEST_BIPARTITE_BOX_PRUNING]     = new BipartiteBoxPruningTest;
338         gCollisionTests[TEST_DBVT_8192] = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,7);
339         gCollisionTests[TEST_BULLET_CUDA_8192]  = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,8);
340         gCollisionTests[TEST_BULLET_3DGRID_8192]        = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,9);
341         gCollisionTests[TEST_OPCODE_ARRAY_SAP]  = new OpcodeArraySAPTest(NUM_SAP_BOXES);
342
343         for(int i=0;i<MAX_NB_TESTS;i++)
344                 gCollisionTests[i]->Init();
345         gCollisionTests[gTest]->Select();
346
347         //
348         MotionCallback(0,0);
349
350         // Run
351         glutMainLoop();
352
353         return 0;
354 }
355
356
357 #ifdef OLDIES
358
359 #include "btBulletCollisionCommon.h"
360
361 class BulletMeshInterface : public btStridingMeshInterface
362 {
363         public:
364                 /// get read and write access to a subpart of a triangle mesh
365                 /// this subpart has a continuous array of vertices and indices
366                 /// in this way the mesh can be handled as chunks of memory with striding
367                 /// very similar to OpenGL vertexarray support
368                 /// make a call to unLockVertexBase when the read and write access is finished  
369                 virtual void    getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)
370                 {
371                         numverts = gTerrainData->nbVerts;
372                         (*vertexbase) = (unsigned char *)gTerrainData->verts;
373                         type = PHY_FLOAT;
374                         stride = sizeof(Point);
375
376                         numfaces = gTerrainData->nbFaces;
377                         (*indexbase) = (unsigned char *)gTerrainData->faces;
378                         indicestype = PHY_INTEGER;
379                         indexstride = 3*sizeof(udword); // ??
380                 }
381                 
382                 virtual void    getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const
383                 {
384                         numverts = gTerrainData->nbVerts;
385                         (*vertexbase) = (unsigned char *)gTerrainData->verts;
386                         type = PHY_FLOAT;
387                         stride = sizeof(Point);
388
389                         numfaces = gTerrainData->nbFaces;
390                         (*indexbase) = (unsigned char *)gTerrainData->faces;
391                         indicestype = PHY_INTEGER;
392                         indexstride = 3*sizeof(udword); // ??
393                 }
394         
395                 /// unLockVertexBase finishes the access to a subpart of the triangle mesh
396                 /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
397                 virtual void    unLockVertexBase(int subpart)
398                 {
399                 }
400
401                 virtual void    unLockReadOnlyVertexBase(int subpart) const
402                 {
403                 }
404
405
406                 /// getNumSubParts returns the number of seperate subparts
407                 /// each subpart has a continuous array of vertices and indices
408                 virtual int             getNumSubParts() const
409                 {
410                         return 1;
411                 }
412
413                 virtual void    preallocateVertices(int numverts)
414                 {
415                 }
416                 virtual void    preallocateIndices(int numindices)
417                 {
418                 }
419 };
420
421 void BuildBulletTree()
422 {
423 /*      BulletMeshInterface btMeshInterface;
424
425         btOptimizedBvh* btTree = new btOptimizedBvh;
426         btTree->build(&btMeshInterface, true);
427
428
429         struct MyNodeOverlapCallback : public btNodeOverlapCallback
430         {
431                 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
432                 {
433                 }
434         };
435
436         MyNodeOverlapCallback   myNodeCallback(callback,m_meshInterface);
437
438         m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
439 */
440
441
442 }
443
444 #endif