1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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
17
18 // Collision Radius
19 #define COLLISION_RADIUS 0.0f
20
21 #include "BenchmarkDemo.h"
22 #ifdef USE_GRAPHICAL_BENCHMARK
23 #include "GlutStuff.h"
24 #endif //USE_GRAPHICAL_BENCHMARK
25
26 ///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
27 #include "btBulletDynamicsCommon.h"
28 #include <stdio.h> //printf debugging
29 #include "Taru.mdl"
30 #include "landscape.mdl"
31 #include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
32 #ifdef USE_PARALLEL_DISPATCHER_BENCHMARK
33 #include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h"
34 #include "BulletMultiThreaded/SequentialThreadSupport.h"
35 #include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
36 #endif
37
38 #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
39
40
41 #ifdef USE_PARALLEL_DISPATCHER_BENCHMARK
42 #ifdef _WIN32
43 #include "BulletMultiThreaded/Win32ThreadSupport.h"
44 #elif defined (USE_PTHREADS)
45 #include "BulletMultiThreaded/PosixThreadSupport.h"
46 #endif
47 #include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h"
48 #include "BulletMultiThreaded/btParallelConstraintSolver.h"
49
50
51
52
createSolverThreadSupport(int maxNumThreads)53 btThreadSupportInterface* createSolverThreadSupport(int maxNumThreads)
54 {
55 //#define SEQUENTIAL
56 #ifdef SEQUENTIAL
57 SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads",SolverThreadFunc,SolverlsMemoryFunc);
58 SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci);
59 threadSupport->startSPU();
60 #else
61
62 #ifdef _WIN32
63 Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("solverThreads",SolverThreadFunc,SolverlsMemoryFunc,maxNumThreads);
64 Win32ThreadSupport* threadSupport = new Win32ThreadSupport(threadConstructionInfo);
65 threadSupport->startSPU();
66 #elif defined (USE_PTHREADS)
67 PosixThreadSupport::ThreadConstructionInfo solverConstructionInfo("solver", SolverThreadFunc,
68 SolverlsMemoryFunc, maxNumThreads);
69
70 PosixThreadSupport* threadSupport = new PosixThreadSupport(solverConstructionInfo);
71
72 #else
73 SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads",SolverThreadFunc,SolverlsMemoryFunc);
74 SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci);
75 threadSupport->startSPU();
76 #endif
77
78 #endif
79
80 return threadSupport;
81 }
82 #endif
83
84 class btRaycastBar2
85 {
86 public:
87 btVector3 source[NUMRAYS];
88 btVector3 dest[NUMRAYS];
89 btVector3 direction[NUMRAYS];
90 btVector3 hit[NUMRAYS];
91 btVector3 normal[NUMRAYS];
92
93 int frame_counter;
94 int ms;
95 int sum_ms;
96 int sum_ms_samples;
97 int min_ms;
98 int max_ms;
99
100 #ifdef USE_BT_CLOCK
101 btClock frame_timer;
102 #endif //USE_BT_CLOCK
103
104 btScalar dx;
105 btScalar min_x;
106 btScalar max_x;
107 btScalar max_y;
108 btScalar sign;
109
btRaycastBar2()110 btRaycastBar2 ()
111 {
112 ms = 0;
113 max_ms = 0;
114 min_ms = 9999;
115 sum_ms_samples = 0;
116 sum_ms = 0;
117 }
118
119
120
btRaycastBar2(btScalar ray_length,btScalar z,btScalar max_y)121 btRaycastBar2 (btScalar ray_length, btScalar z,btScalar max_y)
122 {
123 frame_counter = 0;
124 ms = 0;
125 max_ms = 0;
126 min_ms = 9999;
127 sum_ms_samples = 0;
128 sum_ms = 0;
129 dx = 10.0;
130 min_x = 0;
131 max_x = 0;
132 this->max_y = max_y;
133 sign = 1.0;
134 btScalar dalpha = 2*SIMD_2_PI/NUMRAYS;
135 for (int i = 0; i < NUMRAYS; i++)
136 {
137 btScalar alpha = dalpha * i;
138 // rotate around by alpha degrees y
139 btQuaternion q(btVector3(0.0, 1.0, 0.0), alpha);
140 direction[i] = btVector3(1.0, 0.0, 0.0);
141 direction[i] = quatRotate(q , direction[i]);
142 direction[i] = direction[i] * ray_length;
143
144
145 source[i] = btVector3(min_x, max_y, z);
146 dest[i] = source[i] + direction[i];
147 dest[i][1]=-1000;
148 normal[i] = btVector3(1.0, 0.0, 0.0);
149 }
150 }
151
move(btScalar dt)152 void move (btScalar dt)
153 {
154 if (dt > btScalar(1.0/60.0))
155 dt = btScalar(1.0/60.0);
156 for (int i = 0; i < NUMRAYS; i++)
157 {
158 source[i][0] += dx * dt * sign;
159 dest[i][0] += dx * dt * sign;
160 }
161 if (source[0][0] < min_x)
162 sign = 1.0;
163 else if (source[0][0] > max_x)
164 sign = -1.0;
165 }
166
cast(btCollisionWorld * cw)167 void cast (btCollisionWorld* cw)
168 {
169 #ifdef USE_BT_CLOCK
170 frame_timer.reset ();
171 #endif //USE_BT_CLOCK
172
173 #ifdef BATCH_RAYCASTER
174 if (!gBatchRaycaster)
175 return;
176
177 gBatchRaycaster->clearRays ();
178 for (int i = 0; i < NUMRAYS; i++)
179 {
180 gBatchRaycaster->addRay (source[i], dest[i]);
181 }
182 gBatchRaycaster->performBatchRaycast ();
183 for (int i = 0; i < gBatchRaycaster->getNumRays (); i++)
184 {
185 const SpuRaycastTaskWorkUnitOut& out = (*gBatchRaycaster)[i];
186 hit[i].setInterpolate3(source[i],dest[i],out.hitFraction);
187 normal[i] = out.hitNormal;
188 normal[i].normalize ();
189 }
190 #else
191 for (int i = 0; i < NUMRAYS; i++)
192 {
193 btCollisionWorld::ClosestRayResultCallback cb(source[i], dest[i]);
194
195 cw->rayTest (source[i], dest[i], cb);
196 if (cb.hasHit ())
197 {
198 hit[i] = cb.m_hitPointWorld;
199 normal[i] = cb.m_hitNormalWorld;
200 normal[i].normalize ();
201 } else {
202 hit[i] = dest[i];
203 normal[i] = btVector3(1.0, 0.0, 0.0);
204 }
205
206 }
207 #ifdef USE_BT_CLOCK
208 ms += frame_timer.getTimeMilliseconds ();
209 #endif //USE_BT_CLOCK
210 frame_counter++;
211 if (frame_counter > 50)
212 {
213 min_ms = ms < min_ms ? ms : min_ms;
214 max_ms = ms > max_ms ? ms : max_ms;
215 sum_ms += ms;
216 sum_ms_samples++;
217 btScalar mean_ms = (btScalar)sum_ms/(btScalar)sum_ms_samples;
218 //printf("%d rays in %d ms %d %d %f\n", NUMRAYS * frame_counter, ms, min_ms, max_ms, mean_ms);
219 ms = 0;
220 frame_counter = 0;
221 }
222 #endif
223 }
224
draw()225 void draw ()
226 {
227 #ifdef USE_GRAPHICAL_BENCHMARK
228 glDisable (GL_LIGHTING);
229 glColor3f (0.0, 1.0, 0.0);
230 glBegin (GL_LINES);
231 int i;
232
233 for (i = 0; i < NUMRAYS; i++)
234 {
235 glVertex3f (source[i][0], source[i][1], source[i][2]);
236 glVertex3f (hit[i][0], hit[i][1], hit[i][2]);
237 }
238 glEnd ();
239 glColor3f (1.0, 1.0, 1.0);
240 glBegin (GL_LINES);
241 for (i = 0; i < NUMRAYS; i++)
242 {
243 glVertex3f (hit[i][0], hit[i][1], hit[i][2]);
244 glVertex3f (hit[i][0] + normal[i][0], hit[i][1] + normal[i][1], hit[i][2] + normal[i][2]);
245 }
246 glEnd ();
247 glColor3f (0.0, 1.0, 1.0);
248 glBegin (GL_POINTS);
249 for ( i = 0; i < NUMRAYS; i++)
250 {
251 glVertex3f (hit[i][0], hit[i][1], hit[i][2]);
252 }
253 glEnd ();
254 glEnable (GL_LIGHTING);
255 #endif //USE_GRAPHICAL_BENCHMARK
256
257 }
258 };
259
260
261 static btRaycastBar2 raycastBar;
262
263
clientMoveAndDisplay()264 void BenchmarkDemo::clientMoveAndDisplay()
265 {
266 #ifdef USE_GRAPHICAL_BENCHMARK
267 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
268 #endif //USE_GRAPHICAL_BENCHMARK
269
270 //simple dynamics world doesn't handle fixed-time-stepping
271 //float ms = getDeltaTimeMicroseconds();
272
273 ///step the simulation
274 if (m_dynamicsWorld)
275 {
276 m_dynamicsWorld->stepSimulation(btScalar(1./60.));
277 //optional but useful: debug drawing
278 m_dynamicsWorld->debugDrawWorld();
279 }
280
281 if (m_benchmark==7)
282 {
283 castRays();
284
285 raycastBar.draw();
286
287 }
288
289 renderme();
290
291 #ifdef USE_GRAPHICAL_BENCHMARK
292 glFlush();
293
294 swapBuffers();
295 #endif //USE_GRAPHICAL_BENCHMARK
296
297 }
298
299
300
displayCallback(void)301 void BenchmarkDemo::displayCallback(void)
302 {
303
304 #ifdef USE_GRAPHICAL_BENCHMARK
305 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
306
307 renderme();
308
309 //optional but useful: debug drawing to detect problems
310 if (m_dynamicsWorld)
311 m_dynamicsWorld->debugDrawWorld();
312
313 glFlush();
314 swapBuffers();
315 #endif //USE_GRAPHICAL_BENCHMARK
316 }
317
318
319
320
initPhysics()321 void BenchmarkDemo::initPhysics()
322 {
323
324 setCameraDistance(btScalar(100.));
325
326 ///collision configuration contains default setup for memory, collision setup
327 btDefaultCollisionConstructionInfo cci;
328 cci.m_defaultMaxPersistentManifoldPoolSize = 32768;
329 m_collisionConfiguration = new btDefaultCollisionConfiguration(cci);
330
331 ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
332 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
333
334 m_dispatcher->setDispatcherFlags(btCollisionDispatcher::CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION);
335
336 #if USE_PARALLEL_DISPATCHER_BENCHMARK
337
338 int maxNumOutstandingTasks = 4;
339 #ifdef _WIN32
340 Win32ThreadSupport* threadSupportCollision = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( "collision",processCollisionTask, createCollisionLocalStoreMemory,maxNumOutstandingTasks));
341 #elif defined (USE_PTHREADS)
342 PosixThreadSupport::ThreadConstructionInfo collisionConstructionInfo( "collision",processCollisionTask, createCollisionLocalStoreMemory,maxNumOutstandingTasks);
343 PosixThreadSupport* threadSupportCollision = new PosixThreadSupport(collisionConstructionInfo);
344 #endif
345 //SequentialThreadSupport::SequentialThreadConstructionInfo sci("spuCD", processCollisionTask, createCollisionLocalStoreMemory);
346 //SequentialThreadSupport* seq = new SequentialThreadSupport(sci);
347 m_dispatcher = new SpuGatheringCollisionDispatcher(threadSupportCollision,1,m_collisionConfiguration);
348 #endif
349
350
351 ///the maximum size of the collision world. Make sure objects stay within these boundaries
352 ///Don't make the world AABB size too large, it will harm simulation quality and performance
353 btVector3 worldAabbMin(-1000,-1000,-1000);
354 btVector3 worldAabbMax(1000,1000,1000);
355
356 btHashedOverlappingPairCache* pairCache = new btHashedOverlappingPairCache();
357 m_overlappingPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,3500,pairCache);
358 // m_overlappingPairCache = new btSimpleBroadphase();
359 // m_overlappingPairCache = new btDbvtBroadphase();
360
361
362 ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
363 #ifdef USE_PARALLEL_DISPATCHER_BENCHMARK
364
365 btThreadSupportInterface* thread = createSolverThreadSupport(4);
366 btConstraintSolver* sol = new btParallelConstraintSolver(thread);
367 #else
368 btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
369 #endif //USE_PARALLEL_DISPATCHER_BENCHMARK
370
371
372 m_solver = sol;
373
374 btDiscreteDynamicsWorld* dynamicsWorld;
375 m_dynamicsWorld = dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_solver,m_collisionConfiguration);
376
377 #ifdef USE_PARALLEL_DISPATCHER_BENCHMARK
378 dynamicsWorld->getSimulationIslandManager()->setSplitIslands(false);
379 #endif //USE_PARALLEL_DISPATCHER_BENCHMARK
380
381 ///the following 3 lines increase the performance dramatically, with a little bit of loss of quality
382 m_dynamicsWorld->getSolverInfo().m_solverMode |=SOLVER_ENABLE_FRICTION_DIRECTION_CACHING; //don't recalculate friction values each frame
383 dynamicsWorld->getSolverInfo().m_numIterations = 5; //few solver iterations
384 m_defaultContactProcessingThreshold = 0.f;//used when creating bodies: body->setContactProcessingThreshold(...);
385
386
387 m_dynamicsWorld->setGravity(btVector3(0,-10,0));
388
389 if (m_benchmark<5)
390 {
391 ///create a few basic rigid bodies
392 btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(250.),btScalar(50.),btScalar(250.)));
393 // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),0);
394
395 m_collisionShapes.push_back(groundShape);
396
397 btTransform groundTransform;
398 groundTransform.setIdentity();
399 groundTransform.setOrigin(btVector3(0,-50,0));
400
401 //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
402 {
403 btScalar mass(0.);
404
405 //rigidbody is dynamic if and only if mass is non zero, otherwise static
406 bool isDynamic = (mass != 0.f);
407
408 btVector3 localInertia(0,0,0);
409 if (isDynamic)
410 groundShape->calculateLocalInertia(mass,localInertia);
411
412 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
413 btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
414 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
415 btRigidBody* body = new btRigidBody(rbInfo);
416
417 //add the body to the dynamics world
418 m_dynamicsWorld->addRigidBody(body);
419 }
420 }
421
422 switch (m_benchmark)
423 {
424 case 1:
425 {
426 createTest1();
427 break;
428 }
429 case 2:
430 {
431 createTest2();
432 break;
433 }
434 case 3:
435 {
436 createTest3();
437 break;
438 }
439 case 4:
440 {
441 createTest4();
442 break;
443 }
444 case 5:
445 {
446 createTest5();
447 break;
448 }
449 case 6:
450 {
451 createTest6();
452 break;
453 }
454 case 7:
455 {
456 createTest7();
457 break;
458 }
459
460
461 default:
462 {
463 }
464 }
465
466
467 clientResetScene();
468 }
469
470
createTest1()471 void BenchmarkDemo::createTest1()
472 {
473 // 3000
474 int size = 8;
475 const float cubeSize = 1.0f;
476 float spacing = cubeSize;
477 btVector3 pos(0.0f, cubeSize * 2,0.f);
478 float offset = -size * (cubeSize * 2.0f + spacing) * 0.5f;
479
480 btBoxShape* blockShape = new btBoxShape(btVector3(cubeSize-COLLISION_RADIUS,cubeSize-COLLISION_RADIUS,cubeSize-COLLISION_RADIUS));
481 btVector3 localInertia(0,0,0);
482 float mass = 2.f;
483 blockShape->calculateLocalInertia(mass,localInertia);
484
485 btTransform trans;
486 trans.setIdentity();
487
488 for(int k=0;k<47;k++) {
489 for(int j=0;j<size;j++) {
490 pos[2] = offset + (float)j * (cubeSize * 2.0f + spacing);
491 for(int i=0;i<size;i++) {
492 pos[0] = offset + (float)i * (cubeSize * 2.0f + spacing);
493
494 trans.setOrigin(pos);
495 btRigidBody* cmbody;
496 cmbody= localCreateRigidBody(mass,trans,blockShape);
497 }
498 }
499 offset -= 0.05f * spacing * (size-1);
500 // spacing *= 1.01f;
501 pos[1] += (cubeSize * 2.0f + spacing);
502 }
503 }
504
505
506 ///////////////////////////////////////////////////////////////////////////////
507 // Pyramid 3
508
createWall(const btVector3 & offsetPosition,int stackSize,const btVector3 & boxSize)509 void BenchmarkDemo::createWall(const btVector3& offsetPosition,int stackSize,const btVector3& boxSize)
510 {
511
512 btBoxShape* blockShape = new btBoxShape(btVector3(boxSize[0]-COLLISION_RADIUS,boxSize[1]-COLLISION_RADIUS,boxSize[2]-COLLISION_RADIUS));
513
514 float mass = 1.f;
515 btVector3 localInertia(0,0,0);
516 blockShape->calculateLocalInertia(mass,localInertia);
517
518 // btScalar diffX = boxSize[0] * 1.0f;
519 btScalar diffY = boxSize[1] * 1.0f;
520 btScalar diffZ = boxSize[2] * 1.0f;
521
522 btScalar offset = -stackSize * (diffZ * 2.0f) * 0.5f;
523 btVector3 pos(0.0f, diffY, 0.0f);
524
525 btTransform trans;
526 trans.setIdentity();
527
528 while(stackSize) {
529 for(int i=0;i<stackSize;i++) {
530 pos[2] = offset + (float)i * (diffZ * 2.0f);
531
532 trans.setOrigin(offsetPosition + pos);
533 localCreateRigidBody(mass,trans,blockShape);
534
535 }
536 offset += diffZ;
537 pos[1] += (diffY * 2.0f);
538 stackSize--;
539 }
540 }
541
createPyramid(const btVector3 & offsetPosition,int stackSize,const btVector3 & boxSize)542 void BenchmarkDemo::createPyramid(const btVector3& offsetPosition,int stackSize,const btVector3& boxSize)
543 {
544 btScalar space = 0.0001f;
545
546 btVector3 pos(0.0f, boxSize[1], 0.0f);
547
548 btBoxShape* blockShape = new btBoxShape(btVector3(boxSize[0]-COLLISION_RADIUS,boxSize[1]-COLLISION_RADIUS,boxSize[2]-COLLISION_RADIUS));
549 btTransform trans;
550 trans.setIdentity();
551
552 btScalar mass = 1.f;
553 btVector3 localInertia(0,0,0);
554 blockShape->calculateLocalInertia(mass,localInertia);
555
556
557 btScalar diffX = boxSize[0]*1.02f;
558 btScalar diffY = boxSize[1]*1.02f;
559 btScalar diffZ = boxSize[2]*1.02f;
560
561 btScalar offsetX = -stackSize * (diffX * 2.0f + space) * 0.5f;
562 btScalar offsetZ = -stackSize * (diffZ * 2.0f + space) * 0.5f;
563 while(stackSize) {
564 for(int j=0;j<stackSize;j++) {
565 pos[2] = offsetZ + (float)j * (diffZ * 2.0f + space);
566 for(int i=0;i<stackSize;i++) {
567 pos[0] = offsetX + (float)i * (diffX * 2.0f + space);
568 trans.setOrigin(offsetPosition + pos);
569 this->localCreateRigidBody(mass,trans,blockShape);
570
571
572 }
573 }
574 offsetX += diffX;
575 offsetZ += diffZ;
576 pos[1] += (diffY * 2.0f + space);
577 stackSize--;
578 }
579
580 }
581
rotate(const btQuaternion & quat,const btVector3 & vec)582 const btVector3 rotate( const btQuaternion& quat, const btVector3 & vec )
583 {
584 float tmpX, tmpY, tmpZ, tmpW;
585 tmpX = ( ( ( quat.getW() * vec.getX() ) + ( quat.getY() * vec.getZ() ) ) - ( quat.getZ() * vec.getY() ) );
586 tmpY = ( ( ( quat.getW() * vec.getY() ) + ( quat.getZ() * vec.getX() ) ) - ( quat.getX() * vec.getZ() ) );
587 tmpZ = ( ( ( quat.getW() * vec.getZ() ) + ( quat.getX() * vec.getY() ) ) - ( quat.getY() * vec.getX() ) );
588 tmpW = ( ( ( quat.getX() * vec.getX() ) + ( quat.getY() * vec.getY() ) ) + ( quat.getZ() * vec.getZ() ) );
589 return btVector3(
590 ( ( ( ( tmpW * quat.getX() ) + ( tmpX * quat.getW() ) ) - ( tmpY * quat.getZ() ) ) + ( tmpZ * quat.getY() ) ),
591 ( ( ( ( tmpW * quat.getY() ) + ( tmpY * quat.getW() ) ) - ( tmpZ * quat.getX() ) ) + ( tmpX * quat.getZ() ) ),
592 ( ( ( ( tmpW * quat.getZ() ) + ( tmpZ * quat.getW() ) ) - ( tmpX * quat.getY() ) ) + ( tmpY * quat.getX() ) )
593 );
594 }
595
createTowerCircle(const btVector3 & offsetPosition,int stackSize,int rotSize,const btVector3 & boxSize)596 void BenchmarkDemo::createTowerCircle(const btVector3& offsetPosition,int stackSize,int rotSize,const btVector3& boxSize)
597 {
598
599 btBoxShape* blockShape = new btBoxShape(btVector3(boxSize[0]-COLLISION_RADIUS,boxSize[1]-COLLISION_RADIUS,boxSize[2]-COLLISION_RADIUS));
600
601 btTransform trans;
602 trans.setIdentity();
603
604 float mass = 1.f;
605 btVector3 localInertia(0,0,0);
606 blockShape->calculateLocalInertia(mass,localInertia);
607
608
609 float radius = 1.3f * rotSize * boxSize[0] / SIMD_PI;
610
611 // create active boxes
612 btQuaternion rotY(0,1,0,0);
613 float posY = boxSize[1];
614
615 for(int i=0;i<stackSize;i++) {
616 for(int j=0;j<rotSize;j++) {
617
618
619 trans.setOrigin(offsetPosition+ rotate(rotY,btVector3(0.0f , posY, radius)));
620 trans.setRotation(rotY);
621 localCreateRigidBody(mass,trans,blockShape);
622
623 rotY *= btQuaternion(btVector3(0,1,0),SIMD_PI/(rotSize*btScalar(0.5)));
624 }
625
626 posY += boxSize[1] * 2.0f;
627 rotY *= btQuaternion(btVector3(0,1,0),SIMD_PI/(float)rotSize);
628 }
629
630 }
631
createTest2()632 void BenchmarkDemo::createTest2()
633 {
634 setCameraDistance(btScalar(50.));
635 const float cubeSize = 1.0f;
636
637 createPyramid(btVector3(-20.0f,0.0f,0.0f),12,btVector3(cubeSize,cubeSize,cubeSize));
638 createWall(btVector3(-2.0f,0.0f,0.0f),12,btVector3(cubeSize,cubeSize,cubeSize));
639 createWall(btVector3(4.0f,0.0f,0.0f),12,btVector3(cubeSize,cubeSize,cubeSize));
640 createWall(btVector3(10.0f,0.0f,0.0f),12,btVector3(cubeSize,cubeSize,cubeSize));
641 createTowerCircle(btVector3(25.0f,0.0f,0.0f),8,24,btVector3(cubeSize,cubeSize,cubeSize));
642
643 }
644
645
646
647
648 // Enrico: Shouldn't these three variables be real constants and not defines?
649
650 #ifndef M_PI
651 #define M_PI btScalar(3.14159265358979323846)
652 #endif
653
654 #ifndef M_PI_2
655 #define M_PI_2 btScalar(1.57079632679489661923)
656 #endif
657
658 #ifndef M_PI_4
659 #define M_PI_4 btScalar(0.785398163397448309616)
660 #endif
661
662 class RagDoll
663 {
664 enum
665 {
666 BODYPART_PELVIS = 0,
667 BODYPART_SPINE,
668 BODYPART_HEAD,
669
670 BODYPART_LEFT_UPPER_LEG,
671 BODYPART_LEFT_LOWER_LEG,
672
673 BODYPART_RIGHT_UPPER_LEG,
674 BODYPART_RIGHT_LOWER_LEG,
675
676 BODYPART_LEFT_UPPER_ARM,
677 BODYPART_LEFT_LOWER_ARM,
678
679 BODYPART_RIGHT_UPPER_ARM,
680 BODYPART_RIGHT_LOWER_ARM,
681
682 BODYPART_COUNT
683 };
684
685 enum
686 {
687 JOINT_PELVIS_SPINE = 0,
688 JOINT_SPINE_HEAD,
689
690 JOINT_LEFT_HIP,
691 JOINT_LEFT_KNEE,
692
693 JOINT_RIGHT_HIP,
694 JOINT_RIGHT_KNEE,
695
696 JOINT_LEFT_SHOULDER,
697 JOINT_LEFT_ELBOW,
698
699 JOINT_RIGHT_SHOULDER,
700 JOINT_RIGHT_ELBOW,
701
702 JOINT_COUNT
703 };
704
705 btDynamicsWorld* m_ownerWorld;
706 btCollisionShape* m_shapes[BODYPART_COUNT];
707 btRigidBody* m_bodies[BODYPART_COUNT];
708 btTypedConstraint* m_joints[JOINT_COUNT];
709
localCreateRigidBody(btScalar mass,const btTransform & startTransform,btCollisionShape * shape)710 btRigidBody* localCreateRigidBody (btScalar mass, const btTransform& startTransform, btCollisionShape* shape)
711 {
712 bool isDynamic = (mass != 0.f);
713
714 btVector3 localInertia(0,0,0);
715 if (isDynamic)
716 shape->calculateLocalInertia(mass,localInertia);
717
718 btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
719
720 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia);
721 btRigidBody* body = new btRigidBody(rbInfo);
722
723 m_ownerWorld->addRigidBody(body);
724
725 return body;
726 }
727
728 public:
RagDoll(btDynamicsWorld * ownerWorld,const btVector3 & positionOffset,btScalar scale)729 RagDoll (btDynamicsWorld* ownerWorld, const btVector3& positionOffset,btScalar scale)
730 : m_ownerWorld (ownerWorld)
731 {
732 // Setup the geometry
733 m_shapes[BODYPART_PELVIS] = new btCapsuleShape(btScalar(0.15)*scale, btScalar(0.20)*scale);
734 m_shapes[BODYPART_SPINE] = new btCapsuleShape(btScalar(0.15)*scale, btScalar(0.28)*scale);
735 m_shapes[BODYPART_HEAD] = new btCapsuleShape(btScalar(0.10)*scale, btScalar(0.05)*scale);
736 m_shapes[BODYPART_LEFT_UPPER_LEG] = new btCapsuleShape(btScalar(0.07)*scale, btScalar(0.45)*scale);
737 m_shapes[BODYPART_LEFT_LOWER_LEG] = new btCapsuleShape(btScalar(0.05)*scale, btScalar(0.37)*scale);
738 m_shapes[BODYPART_RIGHT_UPPER_LEG] = new btCapsuleShape(btScalar(0.07)*scale, btScalar(0.45)*scale);
739 m_shapes[BODYPART_RIGHT_LOWER_LEG] = new btCapsuleShape(btScalar(0.05)*scale, btScalar(0.37)*scale);
740 m_shapes[BODYPART_LEFT_UPPER_ARM] = new btCapsuleShape(btScalar(0.05)*scale, btScalar(0.33)*scale);
741 m_shapes[BODYPART_LEFT_LOWER_ARM] = new btCapsuleShape(btScalar(0.04)*scale, btScalar(0.25)*scale);
742 m_shapes[BODYPART_RIGHT_UPPER_ARM] = new btCapsuleShape(btScalar(0.05)*scale, btScalar(0.33)*scale);
743 m_shapes[BODYPART_RIGHT_LOWER_ARM] = new btCapsuleShape(btScalar(0.04)*scale, btScalar(0.25)*scale);
744
745 // Setup all the rigid bodies
746 btTransform offset; offset.setIdentity();
747 offset.setOrigin(positionOffset);
748
749 btTransform transform;
750 transform.setIdentity();
751 transform.setOrigin(scale*btVector3(btScalar(0.), btScalar(1.), btScalar(0.)));
752 m_bodies[BODYPART_PELVIS] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_PELVIS]);
753
754 transform.setIdentity();
755 transform.setOrigin(scale*btVector3(btScalar(0.), btScalar(1.2), btScalar(0.)));
756 m_bodies[BODYPART_SPINE] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_SPINE]);
757
758 transform.setIdentity();
759 transform.setOrigin(scale*btVector3(btScalar(0.), btScalar(1.6), btScalar(0.)));
760 m_bodies[BODYPART_HEAD] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_HEAD]);
761
762 transform.setIdentity();
763 transform.setOrigin(scale*btVector3(btScalar(-0.18), btScalar(0.65), btScalar(0.)));
764 m_bodies[BODYPART_LEFT_UPPER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_UPPER_LEG]);
765
766 transform.setIdentity();
767 transform.setOrigin(scale*btVector3(btScalar(-0.18), btScalar(0.2), btScalar(0.)));
768 m_bodies[BODYPART_LEFT_LOWER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_LOWER_LEG]);
769
770 transform.setIdentity();
771 transform.setOrigin(scale*btVector3(btScalar(0.18), btScalar(0.65), btScalar(0.)));
772 m_bodies[BODYPART_RIGHT_UPPER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_UPPER_LEG]);
773
774 transform.setIdentity();
775 transform.setOrigin(scale*btVector3(btScalar(0.18), btScalar(0.2), btScalar(0.)));
776 m_bodies[BODYPART_RIGHT_LOWER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_LOWER_LEG]);
777
778 transform.setIdentity();
779 transform.setOrigin(scale*btVector3(btScalar(-0.35), btScalar(1.45), btScalar(0.)));
780 transform.getBasis().setEulerZYX(0,0,M_PI_2);
781 m_bodies[BODYPART_LEFT_UPPER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_UPPER_ARM]);
782
783 transform.setIdentity();
784 transform.setOrigin(scale*btVector3(btScalar(-0.7), btScalar(1.45), btScalar(0.)));
785 transform.getBasis().setEulerZYX(0,0,M_PI_2);
786 m_bodies[BODYPART_LEFT_LOWER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_LOWER_ARM]);
787
788 transform.setIdentity();
789 transform.setOrigin(scale*btVector3(btScalar(0.35), btScalar(1.45), btScalar(0.)));
790 transform.getBasis().setEulerZYX(0,0,-M_PI_2);
791 m_bodies[BODYPART_RIGHT_UPPER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_UPPER_ARM]);
792
793 transform.setIdentity();
794 transform.setOrigin(scale*btVector3(btScalar(0.7), btScalar(1.45), btScalar(0.)));
795 transform.getBasis().setEulerZYX(0,0,-M_PI_2);
796 m_bodies[BODYPART_RIGHT_LOWER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_LOWER_ARM]);
797
798 // Setup some damping on the m_bodies
799 for (int i = 0; i < BODYPART_COUNT; ++i)
800 {
801 m_bodies[i]->setDamping(btScalar(0.05), btScalar(0.85));
802 m_bodies[i]->setDeactivationTime(btScalar(0.8));
803 m_bodies[i]->setSleepingThresholds(btScalar(1.6), btScalar(2.5));
804 }
805
806 // Now setup the constraints
807 btHingeConstraint* hingeC;
808 btConeTwistConstraint* coneC;
809
810 btTransform localA, localB;
811
812 localA.setIdentity(); localB.setIdentity();
813 localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.15), btScalar(0.)));
814 localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.15), btScalar(0.)));
815 hingeC = new btHingeConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_SPINE], localA, localB);
816 hingeC->setLimit(btScalar(-M_PI_4), btScalar(M_PI_2));
817 m_joints[JOINT_PELVIS_SPINE] = hingeC;
818 m_ownerWorld->addConstraint(m_joints[JOINT_PELVIS_SPINE], true);
819
820
821 localA.setIdentity(); localB.setIdentity();
822 localA.getBasis().setEulerZYX(0,0,M_PI_2); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.30), btScalar(0.)));
823 localB.getBasis().setEulerZYX(0,0,M_PI_2); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.14), btScalar(0.)));
824 coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_HEAD], localA, localB);
825 coneC->setLimit(M_PI_4, M_PI_4, M_PI_2);
826 m_joints[JOINT_SPINE_HEAD] = coneC;
827 m_ownerWorld->addConstraint(m_joints[JOINT_SPINE_HEAD], true);
828
829
830 localA.setIdentity(); localB.setIdentity();
831 localA.getBasis().setEulerZYX(0,0,-M_PI_4*5); localA.setOrigin(scale*btVector3(btScalar(-0.18), btScalar(-0.10), btScalar(0.)));
832 localB.getBasis().setEulerZYX(0,0,-M_PI_4*5); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.225), btScalar(0.)));
833 coneC = new btConeTwistConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_LEFT_UPPER_LEG], localA, localB);
834 coneC->setLimit(M_PI_4, M_PI_4, 0);
835 m_joints[JOINT_LEFT_HIP] = coneC;
836 m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_HIP], true);
837
838 localA.setIdentity(); localB.setIdentity();
839 localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.225), btScalar(0.)));
840 localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.185), btScalar(0.)));
841 hingeC = new btHingeConstraint(*m_bodies[BODYPART_LEFT_UPPER_LEG], *m_bodies[BODYPART_LEFT_LOWER_LEG], localA, localB);
842 hingeC->setLimit(btScalar(0), btScalar(M_PI_2));
843 m_joints[JOINT_LEFT_KNEE] = hingeC;
844 m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_KNEE], true);
845
846
847 localA.setIdentity(); localB.setIdentity();
848 localA.getBasis().setEulerZYX(0,0,M_PI_4); localA.setOrigin(scale*btVector3(btScalar(0.18), btScalar(-0.10), btScalar(0.)));
849 localB.getBasis().setEulerZYX(0,0,M_PI_4); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.225), btScalar(0.)));
850 coneC = new btConeTwistConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_RIGHT_UPPER_LEG], localA, localB);
851 coneC->setLimit(M_PI_4, M_PI_4, 0);
852 m_joints[JOINT_RIGHT_HIP] = coneC;
853 m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_HIP], true);
854
855 localA.setIdentity(); localB.setIdentity();
856 localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.225), btScalar(0.)));
857 localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.185), btScalar(0.)));
858 hingeC = new btHingeConstraint(*m_bodies[BODYPART_RIGHT_UPPER_LEG], *m_bodies[BODYPART_RIGHT_LOWER_LEG], localA, localB);
859 hingeC->setLimit(btScalar(0), btScalar(M_PI_2));
860 m_joints[JOINT_RIGHT_KNEE] = hingeC;
861 m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_KNEE], true);
862
863
864 localA.setIdentity(); localB.setIdentity();
865 localA.getBasis().setEulerZYX(0,0,M_PI); localA.setOrigin(scale*btVector3(btScalar(-0.2), btScalar(0.15), btScalar(0.)));
866 localB.getBasis().setEulerZYX(0,0,M_PI_2); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.18), btScalar(0.)));
867 coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_LEFT_UPPER_ARM], localA, localB);
868 coneC->setLimit(M_PI_2, M_PI_2, 0);
869 m_joints[JOINT_LEFT_SHOULDER] = coneC;
870 m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_SHOULDER], true);
871
872 localA.setIdentity(); localB.setIdentity();
873 localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.18), btScalar(0.)));
874 localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.14), btScalar(0.)));
875 hingeC = new btHingeConstraint(*m_bodies[BODYPART_LEFT_UPPER_ARM], *m_bodies[BODYPART_LEFT_LOWER_ARM], localA, localB);
876 hingeC->setLimit(btScalar(-M_PI_2), btScalar(0));
877 m_joints[JOINT_LEFT_ELBOW] = hingeC;
878 m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_ELBOW], true);
879
880
881
882 localA.setIdentity(); localB.setIdentity();
883 localA.getBasis().setEulerZYX(0,0,0); localA.setOrigin(scale*btVector3(btScalar(0.2), btScalar(0.15), btScalar(0.)));
884 localB.getBasis().setEulerZYX(0,0,M_PI_2); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.18), btScalar(0.)));
885 coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_RIGHT_UPPER_ARM], localA, localB);
886 coneC->setLimit(M_PI_2, M_PI_2, 0);
887 m_joints[JOINT_RIGHT_SHOULDER] = coneC;
888 m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_SHOULDER], true);
889
890 localA.setIdentity(); localB.setIdentity();
891 localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.18), btScalar(0.)));
892 localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.14), btScalar(0.)));
893 hingeC = new btHingeConstraint(*m_bodies[BODYPART_RIGHT_UPPER_ARM], *m_bodies[BODYPART_RIGHT_LOWER_ARM], localA, localB);
894 hingeC->setLimit(btScalar(-M_PI_2), btScalar(0));
895 m_joints[JOINT_RIGHT_ELBOW] = hingeC;
896 m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_ELBOW], true);
897 }
898
~RagDoll()899 virtual ~RagDoll ()
900 {
901 int i;
902
903 // Remove all constraints
904 for ( i = 0; i < JOINT_COUNT; ++i)
905 {
906 m_ownerWorld->removeConstraint(m_joints[i]);
907 delete m_joints[i]; m_joints[i] = 0;
908 }
909
910 // Remove all bodies and shapes
911 for ( i = 0; i < BODYPART_COUNT; ++i)
912 {
913 m_ownerWorld->removeRigidBody(m_bodies[i]);
914
915 delete m_bodies[i]->getMotionState();
916
917 delete m_bodies[i]; m_bodies[i] = 0;
918 delete m_shapes[i]; m_shapes[i] = 0;
919 }
920 }
921 };
922
createTest3()923 void BenchmarkDemo::createTest3()
924 {
925 setCameraDistance(btScalar(50.));
926
927 int size = 16;
928
929 float sizeX = 1.f;
930 float sizeY = 1.f;
931
932 //int rc=0;
933
934 btScalar scale(3.5);
935 btVector3 pos(0.0f, sizeY, 0.0f);
936 while(size) {
937 float offset = -size * (sizeX * 6.0f) * 0.5f;
938 for(int i=0;i<size;i++) {
939 pos[0] = offset + (float)i * (sizeX * 6.0f);
940
941 RagDoll* ragDoll = new RagDoll (m_dynamicsWorld,pos,scale);
942 m_ragdolls.push_back(ragDoll);
943 }
944
945 offset += sizeX;
946 pos[1] += (sizeY * 7.0f);
947 pos[2] -= sizeX * 2.0f;
948 size--;
949 }
950
951 }
createTest4()952 void BenchmarkDemo::createTest4()
953 {
954 setCameraDistance(btScalar(50.));
955
956 int size = 8;
957 const float cubeSize = 1.5f;
958 float spacing = cubeSize;
959 btVector3 pos(0.0f, cubeSize * 2, 0.0f);
960 float offset = -size * (cubeSize * 2.0f + spacing) * 0.5f;
961
962 btConvexHullShape* convexHullShape = new btConvexHullShape();
963
964 btScalar scaling(1);
965
966 convexHullShape->setLocalScaling(btVector3(scaling,scaling,scaling));
967
968 for (int i=0;i<TaruVtxCount;i++)
969 {
970 btVector3 vtx(TaruVtx[i*3],TaruVtx[i*3+1],TaruVtx[i*3+2]);
971 convexHullShape->addPoint(vtx*btScalar(1./scaling));
972 }
973
974 //this will enable polyhedral contact clipping, better quality, slightly slower
975 //convexHullShape->initializePolyhedralFeatures();
976
977 btTransform trans;
978 trans.setIdentity();
979
980 float mass = 1.f;
981 btVector3 localInertia(0,0,0);
982 convexHullShape->calculateLocalInertia(mass,localInertia);
983
984 for(int k=0;k<15;k++) {
985 for(int j=0;j<size;j++) {
986 pos[2] = offset + (float)j * (cubeSize * 2.0f + spacing);
987 for(int i=0;i<size;i++) {
988 pos[0] = offset + (float)i * (cubeSize * 2.0f + spacing);
989 trans.setOrigin(pos);
990 localCreateRigidBody(mass,trans,convexHullShape);
991 }
992 }
993 offset -= 0.05f * spacing * (size-1);
994 spacing *= 1.01f;
995 pos[1] += (cubeSize * 2.0f + spacing);
996 }
997 }
998
999
1000 ///////////////////////////////////////////////////////////////////////////////
1001 // LargeMesh
1002
1003 int LandscapeVtxCount[] = {
1004 Landscape01VtxCount,
1005 Landscape02VtxCount,
1006 Landscape03VtxCount,
1007 Landscape04VtxCount,
1008 Landscape05VtxCount,
1009 Landscape06VtxCount,
1010 Landscape07VtxCount,
1011 Landscape08VtxCount,
1012 };
1013
1014 int LandscapeIdxCount[] = {
1015 Landscape01IdxCount,
1016 Landscape02IdxCount,
1017 Landscape03IdxCount,
1018 Landscape04IdxCount,
1019 Landscape05IdxCount,
1020 Landscape06IdxCount,
1021 Landscape07IdxCount,
1022 Landscape08IdxCount,
1023 };
1024
1025 btScalar *LandscapeVtx[] = {
1026 Landscape01Vtx,
1027 Landscape02Vtx,
1028 Landscape03Vtx,
1029 Landscape04Vtx,
1030 Landscape05Vtx,
1031 Landscape06Vtx,
1032 Landscape07Vtx,
1033 Landscape08Vtx,
1034 };
1035
1036 btScalar *LandscapeNml[] = {
1037 Landscape01Nml,
1038 Landscape02Nml,
1039 Landscape03Nml,
1040 Landscape04Nml,
1041 Landscape05Nml,
1042 Landscape06Nml,
1043 Landscape07Nml,
1044 Landscape08Nml,
1045 };
1046
1047 btScalar* LandscapeTex[] = {
1048 Landscape01Tex,
1049 Landscape02Tex,
1050 Landscape03Tex,
1051 Landscape04Tex,
1052 Landscape05Tex,
1053 Landscape06Tex,
1054 Landscape07Tex,
1055 Landscape08Tex,
1056 };
1057
1058 unsigned short *LandscapeIdx[] = {
1059 Landscape01Idx,
1060 Landscape02Idx,
1061 Landscape03Idx,
1062 Landscape04Idx,
1063 Landscape05Idx,
1064 Landscape06Idx,
1065 Landscape07Idx,
1066 Landscape08Idx,
1067 };
1068
createLargeMeshBody()1069 void BenchmarkDemo::createLargeMeshBody()
1070 {
1071 btTransform trans;
1072 trans.setIdentity();
1073
1074 for(int i=0;i<8;i++) {
1075
1076 btTriangleIndexVertexArray* meshInterface = new btTriangleIndexVertexArray();
1077 btIndexedMesh part;
1078
1079 part.m_vertexBase = (const unsigned char*)LandscapeVtx[i];
1080 part.m_vertexStride = sizeof(btScalar) * 3;
1081 part.m_numVertices = LandscapeVtxCount[i];
1082 part.m_triangleIndexBase = (const unsigned char*)LandscapeIdx[i];
1083 part.m_triangleIndexStride = sizeof( short) * 3;
1084 part.m_numTriangles = LandscapeIdxCount[i]/3;
1085 part.m_indexType = PHY_SHORT;
1086
1087 meshInterface->addIndexedMesh(part,PHY_SHORT);
1088
1089 bool useQuantizedAabbCompression = true;
1090 btBvhTriangleMeshShape* trimeshShape = new btBvhTriangleMeshShape(meshInterface,useQuantizedAabbCompression);
1091 btVector3 localInertia(0,0,0);
1092 trans.setOrigin(btVector3(0,-25,0));
1093
1094 btRigidBody* body = localCreateRigidBody(0,trans,trimeshShape);
1095 body->setFriction (btScalar(0.9));
1096
1097 }
1098
1099 }
1100
1101
createTest5()1102 void BenchmarkDemo::createTest5()
1103 {
1104 setCameraDistance(btScalar(250.));
1105 btVector3 boxSize(1.5f,1.5f,1.5f);
1106 float boxMass = 1.0f;
1107 float sphereRadius = 1.5f;
1108 float sphereMass = 1.0f;
1109 float capsuleHalf = 2.0f;
1110 float capsuleRadius = 1.0f;
1111 float capsuleMass = 1.0f;
1112
1113 {
1114 int size = 10;
1115 int height = 10;
1116
1117 const float cubeSize = boxSize[0];
1118 float spacing = 2.0f;
1119 btVector3 pos(0.0f, 20.0f, 0.0f);
1120 float offset = -size * (cubeSize * 2.0f + spacing) * 0.5f;
1121
1122 int numBodies = 0;
1123
1124 for(int k=0;k<height;k++) {
1125 for(int j=0;j<size;j++) {
1126 pos[2] = offset + (float)j * (cubeSize * 2.0f + spacing);
1127 for(int i=0;i<size;i++) {
1128 pos[0] = offset + (float)i * (cubeSize * 2.0f + spacing);
1129 btVector3 bpos = btVector3(0,25,0) + btVector3(5.0f,1.0f,5.0f)*pos;
1130 int idx = rand() % 9;
1131 btTransform trans;
1132 trans.setIdentity();
1133 trans.setOrigin(bpos);
1134
1135 switch(idx) {
1136 case 0:case 1:case 2:
1137 {
1138 float r = 0.5f * (idx+1);
1139 btBoxShape* boxShape = new btBoxShape(boxSize*r);
1140 localCreateRigidBody(boxMass*r,trans,boxShape);
1141 }
1142 break;
1143
1144 case 3:case 4:case 5:
1145 {
1146 float r = 0.5f * (idx-3+1);
1147 btSphereShape* sphereShape = new btSphereShape(sphereRadius*r);
1148 localCreateRigidBody(sphereMass*r,trans,sphereShape);
1149 }
1150 break;
1151
1152 case 6:case 7:case 8:
1153 {
1154 float r = 0.5f * (idx-6+1);
1155 btCapsuleShape* capsuleShape = new btCapsuleShape(capsuleRadius*r,capsuleHalf*r);
1156 localCreateRigidBody(capsuleMass*r,trans,capsuleShape);
1157 }
1158 break;
1159 }
1160
1161 numBodies++;
1162 }
1163 }
1164 offset -= 0.05f * spacing * (size-1);
1165 spacing *= 1.1f;
1166 pos[1] += (cubeSize * 2.0f + spacing);
1167 }
1168 }
1169
1170 createLargeMeshBody();
1171 }
createTest6()1172 void BenchmarkDemo::createTest6()
1173 {
1174 setCameraDistance(btScalar(250.));
1175
1176 btVector3 boxSize(1.5f,1.5f,1.5f);
1177
1178 btConvexHullShape* convexHullShape = new btConvexHullShape();
1179
1180 for (int i=0;i<TaruVtxCount;i++)
1181 {
1182 btVector3 vtx(TaruVtx[i*3],TaruVtx[i*3+1],TaruVtx[i*3+2]);
1183 convexHullShape->addPoint(vtx);
1184 }
1185
1186 btTransform trans;
1187 trans.setIdentity();
1188
1189 float mass = 1.f;
1190 btVector3 localInertia(0,0,0);
1191 convexHullShape->calculateLocalInertia(mass,localInertia);
1192
1193
1194 {
1195 int size = 10;
1196 int height = 10;
1197
1198 const float cubeSize = boxSize[0];
1199 float spacing = 2.0f;
1200 btVector3 pos(0.0f, 20.0f, 0.0f);
1201 float offset = -size * (cubeSize * 2.0f + spacing) * 0.5f;
1202
1203
1204 for(int k=0;k<height;k++) {
1205 for(int j=0;j<size;j++) {
1206 pos[2] = offset + (float)j * (cubeSize * 2.0f + spacing);
1207 for(int i=0;i<size;i++) {
1208 pos[0] = offset + (float)i * (cubeSize * 2.0f + spacing);
1209 btVector3 bpos = btVector3(0,25,0) + btVector3(5.0f,1.0f,5.0f)*pos;
1210 trans.setOrigin(bpos);
1211
1212 localCreateRigidBody(mass,trans,convexHullShape);
1213 }
1214 }
1215 offset -= 0.05f * spacing * (size-1);
1216 spacing *= 1.1f;
1217 pos[1] += (cubeSize * 2.0f + spacing);
1218 }
1219 }
1220
1221
1222 createLargeMeshBody();
1223 }
1224
1225
1226
1227
initRays()1228 void BenchmarkDemo::initRays()
1229 {
1230 raycastBar = btRaycastBar2 (2500.0, 0,50.0);
1231 }
1232
castRays()1233 void BenchmarkDemo::castRays()
1234 {
1235 raycastBar.cast (m_dynamicsWorld);
1236 }
1237
createTest7()1238 void BenchmarkDemo::createTest7()
1239 {
1240
1241 createTest6();
1242 setCameraDistance(btScalar(150.));
1243 initRays();
1244 }
1245
exitPhysics()1246 void BenchmarkDemo::exitPhysics()
1247 {
1248 int i;
1249
1250 for (i=0;i<m_ragdolls.size();i++)
1251 {
1252 RagDoll* doll = m_ragdolls[i];
1253 delete doll;
1254 }
1255 m_ragdolls.clear();
1256
1257 //cleanup in the reverse order of creation/initialization
1258 if (m_dynamicsWorld)
1259 {
1260 //remove the rigidbodies from the dynamics world and delete them
1261 for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
1262 {
1263 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
1264 btRigidBody* body = btRigidBody::upcast(obj);
1265 if (body && body->getMotionState())
1266 {
1267 delete body->getMotionState();
1268 }
1269 m_dynamicsWorld->removeCollisionObject( obj );
1270 delete obj;
1271 }
1272 }
1273
1274 //delete collision shapes
1275 for (int j=0;j<m_collisionShapes.size();j++)
1276 {
1277 btCollisionShape* shape = m_collisionShapes[j];
1278 delete shape;
1279 }
1280 m_collisionShapes.clear();
1281
1282 //delete dynamics world
1283 delete m_dynamicsWorld;
1284 m_dynamicsWorld=0;
1285
1286 //delete solver
1287 delete m_solver;
1288 m_solver=0;
1289
1290 //delete broadphase
1291 delete m_overlappingPairCache;
1292 m_overlappingPairCache=0;
1293
1294 //delete dispatcher
1295 delete m_dispatcher;
1296 m_dispatcher=0;
1297
1298 delete m_collisionConfiguration;
1299 m_collisionConfiguration=0;
1300
1301
1302 }
1303
1304
1305
1306 #ifndef USE_GRAPHICAL_BENCHMARK
1307
localCreateRigidBody(float mass,const btTransform & startTransform,btCollisionShape * shape)1308 btRigidBody* DemoApplication::localCreateRigidBody(float mass, const btTransform& startTransform,btCollisionShape* shape)
1309 {
1310 btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
1311
1312 //rigidbody is dynamic if and only if mass is non zero, otherwise static
1313 bool isDynamic = (mass != 0.f);
1314
1315 btVector3 localInertia(0,0,0);
1316 if (isDynamic)
1317 shape->calculateLocalInertia(mass,localInertia);
1318
1319 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
1320
1321 btRigidBody* body = new btRigidBody(mass,0,shape,localInertia);
1322 body->setWorldTransform(startTransform);
1323 body->setContactProcessingThreshold(m_defaultContactProcessingThreshold);
1324 m_dynamicsWorld->addRigidBody(body);
1325
1326 return body;
1327 }
1328 #endif //USE_GRAPHICAL_BENCHMARK
1329
1330