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