2
Bullet Continuous Collision Detection and Physics Library
3
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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:
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.
19
#define COLLISION_RADIUS 0.0f
21
#include "BenchmarkDemo.h"
22
#ifdef USE_GRAPHICAL_BENCHMARK
23
#include "GlutStuff.h"
24
#endif //USE_GRAPHICAL_BENCHMARK
26
///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
27
#include "btBulletDynamicsCommon.h"
28
#include <stdio.h> //printf debugging
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"
38
#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
41
#ifdef USE_PARALLEL_DISPATCHER_BENCHMARK
43
#include "BulletMultiThreaded/Win32ThreadSupport.h"
44
#elif defined (USE_PTHREADS)
45
#include "BulletMultiThreaded/PosixThreadSupport.h"
47
#include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h"
48
#include "BulletMultiThreaded/btParallelConstraintSolver.h"
53
btThreadSupportInterface* createSolverThreadSupport(int maxNumThreads)
57
SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads",SolverThreadFunc,SolverlsMemoryFunc);
58
SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci);
59
threadSupport->startSPU();
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);
70
PosixThreadSupport* threadSupport = new PosixThreadSupport(solverConstructionInfo);
73
SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads",SolverThreadFunc,SolverlsMemoryFunc);
74
SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci);
75
threadSupport->startSPU();
87
btVector3 source[NUMRAYS];
88
btVector3 dest[NUMRAYS];
89
btVector3 direction[NUMRAYS];
90
btVector3 hit[NUMRAYS];
91
btVector3 normal[NUMRAYS];
102
#endif //USE_BT_CLOCK
121
btRaycastBar2 (btScalar ray_length, btScalar z,btScalar max_y)
134
btScalar dalpha = 2*SIMD_2_PI/NUMRAYS;
135
for (int i = 0; i < NUMRAYS; i++)
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;
145
source[i] = btVector3(min_x, max_y, z);
146
dest[i] = source[i] + direction[i];
148
normal[i] = btVector3(1.0, 0.0, 0.0);
152
void move (btScalar dt)
154
if (dt > btScalar(1.0/60.0))
155
dt = btScalar(1.0/60.0);
156
for (int i = 0; i < NUMRAYS; i++)
158
source[i][0] += dx * dt * sign;
159
dest[i][0] += dx * dt * sign;
161
if (source[0][0] < min_x)
163
else if (source[0][0] > max_x)
167
void cast (btCollisionWorld* cw)
170
frame_timer.reset ();
171
#endif //USE_BT_CLOCK
173
#ifdef BATCH_RAYCASTER
174
if (!gBatchRaycaster)
177
gBatchRaycaster->clearRays ();
178
for (int i = 0; i < NUMRAYS; i++)
180
gBatchRaycaster->addRay (source[i], dest[i]);
182
gBatchRaycaster->performBatchRaycast ();
183
for (int i = 0; i < gBatchRaycaster->getNumRays (); i++)
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 ();
191
for (int i = 0; i < NUMRAYS; i++)
193
btCollisionWorld::ClosestRayResultCallback cb(source[i], dest[i]);
195
cw->rayTest (source[i], dest[i], cb);
198
hit[i] = cb.m_hitPointWorld;
199
normal[i] = cb.m_hitNormalWorld;
200
normal[i].normalize ();
203
normal[i] = btVector3(1.0, 0.0, 0.0);
208
ms += frame_timer.getTimeMilliseconds ();
209
#endif //USE_BT_CLOCK
211
if (frame_counter > 50)
213
min_ms = ms < min_ms ? ms : min_ms;
214
max_ms = ms > max_ms ? ms : max_ms;
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);
227
#ifdef USE_GRAPHICAL_BENCHMARK
228
glDisable (GL_LIGHTING);
229
glColor3f (0.0, 1.0, 0.0);
233
for (i = 0; i < NUMRAYS; i++)
235
glVertex3f (source[i][0], source[i][1], source[i][2]);
236
glVertex3f (hit[i][0], hit[i][1], hit[i][2]);
239
glColor3f (1.0, 1.0, 1.0);
241
for (i = 0; i < NUMRAYS; i++)
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]);
247
glColor3f (0.0, 1.0, 1.0);
249
for ( i = 0; i < NUMRAYS; i++)
251
glVertex3f (hit[i][0], hit[i][1], hit[i][2]);
254
glEnable (GL_LIGHTING);
255
#endif //USE_GRAPHICAL_BENCHMARK
261
static btRaycastBar2 raycastBar;
264
void BenchmarkDemo::clientMoveAndDisplay()
266
#ifdef USE_GRAPHICAL_BENCHMARK
267
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
268
#endif //USE_GRAPHICAL_BENCHMARK
270
//simple dynamics world doesn't handle fixed-time-stepping
271
//float ms = getDeltaTimeMicroseconds();
273
///step the simulation
276
m_dynamicsWorld->stepSimulation(btScalar(1./60.));
277
//optional but useful: debug drawing
278
m_dynamicsWorld->debugDrawWorld();
291
#ifdef USE_GRAPHICAL_BENCHMARK
295
#endif //USE_GRAPHICAL_BENCHMARK
301
void BenchmarkDemo::displayCallback(void)
304
#ifdef USE_GRAPHICAL_BENCHMARK
305
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
309
//optional but useful: debug drawing to detect problems
311
m_dynamicsWorld->debugDrawWorld();
315
#endif //USE_GRAPHICAL_BENCHMARK
321
void BenchmarkDemo::initPhysics()
324
setCameraDistance(btScalar(100.));
326
///collision configuration contains default setup for memory, collision setup
327
btDefaultCollisionConstructionInfo cci;
328
cci.m_defaultMaxPersistentManifoldPoolSize = 32768;
329
m_collisionConfiguration = new btDefaultCollisionConfiguration(cci);
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);
334
m_dispatcher->setDispatcherFlags(btCollisionDispatcher::CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION);
336
#if USE_PARALLEL_DISPATCHER_BENCHMARK
338
int maxNumOutstandingTasks = 4;
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);
345
//SequentialThreadSupport::SequentialThreadConstructionInfo sci("spuCD", processCollisionTask, createCollisionLocalStoreMemory);
346
//SequentialThreadSupport* seq = new SequentialThreadSupport(sci);
347
m_dispatcher = new SpuGatheringCollisionDispatcher(threadSupportCollision,1,m_collisionConfiguration);
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);
356
btHashedOverlappingPairCache* pairCache = new btHashedOverlappingPairCache();
357
m_overlappingPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,3500,pairCache);
358
// m_overlappingPairCache = new btSimpleBroadphase();
359
// m_overlappingPairCache = new btDbvtBroadphase();
362
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
363
#ifdef USE_PARALLEL_DISPATCHER_BENCHMARK
365
btThreadSupportInterface* thread = createSolverThreadSupport(4);
366
btConstraintSolver* sol = new btParallelConstraintSolver(thread);
368
btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
369
#endif //USE_PARALLEL_DISPATCHER_BENCHMARK
374
btDiscreteDynamicsWorld* dynamicsWorld;
375
m_dynamicsWorld = dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_solver,m_collisionConfiguration);
377
#ifdef USE_PARALLEL_DISPATCHER_BENCHMARK
378
dynamicsWorld->getSimulationIslandManager()->setSplitIslands(false);
379
#endif //USE_PARALLEL_DISPATCHER_BENCHMARK
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(...);
387
m_dynamicsWorld->setGravity(btVector3(0,-10,0));
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);
395
m_collisionShapes.push_back(groundShape);
397
btTransform groundTransform;
398
groundTransform.setIdentity();
399
groundTransform.setOrigin(btVector3(0,-50,0));
401
//We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
405
//rigidbody is dynamic if and only if mass is non zero, otherwise static
406
bool isDynamic = (mass != 0.f);
408
btVector3 localInertia(0,0,0);
410
groundShape->calculateLocalInertia(mass,localInertia);
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);
417
//add the body to the dynamics world
418
m_dynamicsWorld->addRigidBody(body);
471
void BenchmarkDemo::createTest1()
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;
480
btBoxShape* blockShape = new btBoxShape(btVector3(cubeSize-COLLISION_RADIUS,cubeSize-COLLISION_RADIUS,cubeSize-COLLISION_RADIUS));
481
btVector3 localInertia(0,0,0);
483
blockShape->calculateLocalInertia(mass,localInertia);
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);
494
trans.setOrigin(pos);
496
cmbody= localCreateRigidBody(mass,trans,blockShape);
499
offset -= 0.05f * spacing * (size-1);
501
pos[1] += (cubeSize * 2.0f + spacing);
506
///////////////////////////////////////////////////////////////////////////////
509
void BenchmarkDemo::createWall(const btVector3& offsetPosition,int stackSize,const btVector3& boxSize)
512
btBoxShape* blockShape = new btBoxShape(btVector3(boxSize[0]-COLLISION_RADIUS,boxSize[1]-COLLISION_RADIUS,boxSize[2]-COLLISION_RADIUS));
515
btVector3 localInertia(0,0,0);
516
blockShape->calculateLocalInertia(mass,localInertia);
518
// btScalar diffX = boxSize[0] * 1.0f;
519
btScalar diffY = boxSize[1] * 1.0f;
520
btScalar diffZ = boxSize[2] * 1.0f;
522
btScalar offset = -stackSize * (diffZ * 2.0f) * 0.5f;
523
btVector3 pos(0.0f, diffY, 0.0f);
529
for(int i=0;i<stackSize;i++) {
530
pos[2] = offset + (float)i * (diffZ * 2.0f);
532
trans.setOrigin(offsetPosition + pos);
533
localCreateRigidBody(mass,trans,blockShape);
537
pos[1] += (diffY * 2.0f);
542
void BenchmarkDemo::createPyramid(const btVector3& offsetPosition,int stackSize,const btVector3& boxSize)
544
btScalar space = 0.0001f;
546
btVector3 pos(0.0f, boxSize[1], 0.0f);
548
btBoxShape* blockShape = new btBoxShape(btVector3(boxSize[0]-COLLISION_RADIUS,boxSize[1]-COLLISION_RADIUS,boxSize[2]-COLLISION_RADIUS));
553
btVector3 localInertia(0,0,0);
554
blockShape->calculateLocalInertia(mass,localInertia);
557
btScalar diffX = boxSize[0]*1.02f;
558
btScalar diffY = boxSize[1]*1.02f;
559
btScalar diffZ = boxSize[2]*1.02f;
561
btScalar offsetX = -stackSize * (diffX * 2.0f + space) * 0.5f;
562
btScalar offsetZ = -stackSize * (diffZ * 2.0f + space) * 0.5f;
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);
576
pos[1] += (diffY * 2.0f + space);
582
const btVector3 rotate( const btQuaternion& quat, const btVector3 & vec )
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() ) );
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() ) )
596
void BenchmarkDemo::createTowerCircle(const btVector3& offsetPosition,int stackSize,int rotSize,const btVector3& boxSize)
599
btBoxShape* blockShape = new btBoxShape(btVector3(boxSize[0]-COLLISION_RADIUS,boxSize[1]-COLLISION_RADIUS,boxSize[2]-COLLISION_RADIUS));
605
btVector3 localInertia(0,0,0);
606
blockShape->calculateLocalInertia(mass,localInertia);
609
float radius = 1.3f * rotSize * boxSize[0] / SIMD_PI;
611
// create active boxes
612
btQuaternion rotY(0,1,0,0);
613
float posY = boxSize[1];
615
for(int i=0;i<stackSize;i++) {
616
for(int j=0;j<rotSize;j++) {
619
trans.setOrigin(offsetPosition+ rotate(rotY,btVector3(0.0f , posY, radius)));
620
trans.setRotation(rotY);
621
localCreateRigidBody(mass,trans,blockShape);
623
rotY *= btQuaternion(btVector3(0,1,0),SIMD_PI/(rotSize*btScalar(0.5)));
626
posY += boxSize[1] * 2.0f;
627
rotY *= btQuaternion(btVector3(0,1,0),SIMD_PI/(float)rotSize);
632
void BenchmarkDemo::createTest2()
634
setCameraDistance(btScalar(50.));
635
const float cubeSize = 1.0f;
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));
648
// Enrico: Shouldn't these three variables be real constants and not defines?
651
#define M_PI btScalar(3.14159265358979323846)
655
#define M_PI_2 btScalar(1.57079632679489661923)
659
#define M_PI_4 btScalar(0.785398163397448309616)
670
BODYPART_LEFT_UPPER_LEG,
671
BODYPART_LEFT_LOWER_LEG,
673
BODYPART_RIGHT_UPPER_LEG,
674
BODYPART_RIGHT_LOWER_LEG,
676
BODYPART_LEFT_UPPER_ARM,
677
BODYPART_LEFT_LOWER_ARM,
679
BODYPART_RIGHT_UPPER_ARM,
680
BODYPART_RIGHT_LOWER_ARM,
687
JOINT_PELVIS_SPINE = 0,
699
JOINT_RIGHT_SHOULDER,
705
btDynamicsWorld* m_ownerWorld;
706
btCollisionShape* m_shapes[BODYPART_COUNT];
707
btRigidBody* m_bodies[BODYPART_COUNT];
708
btTypedConstraint* m_joints[JOINT_COUNT];
710
btRigidBody* localCreateRigidBody (btScalar mass, const btTransform& startTransform, btCollisionShape* shape)
712
bool isDynamic = (mass != 0.f);
714
btVector3 localInertia(0,0,0);
716
shape->calculateLocalInertia(mass,localInertia);
718
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
720
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia);
721
btRigidBody* body = new btRigidBody(rbInfo);
723
m_ownerWorld->addRigidBody(body);
729
RagDoll (btDynamicsWorld* ownerWorld, const btVector3& positionOffset,btScalar scale)
730
: m_ownerWorld (ownerWorld)
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);
745
// Setup all the rigid bodies
746
btTransform offset; offset.setIdentity();
747
offset.setOrigin(positionOffset);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
798
// Setup some damping on the m_bodies
799
for (int i = 0; i < BODYPART_COUNT; ++i)
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));
806
// Now setup the constraints
807
btHingeConstraint* hingeC;
808
btConeTwistConstraint* coneC;
810
btTransform localA, localB;
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
903
// Remove all constraints
904
for ( i = 0; i < JOINT_COUNT; ++i)
906
m_ownerWorld->removeConstraint(m_joints[i]);
907
delete m_joints[i]; m_joints[i] = 0;
910
// Remove all bodies and shapes
911
for ( i = 0; i < BODYPART_COUNT; ++i)
913
m_ownerWorld->removeRigidBody(m_bodies[i]);
915
delete m_bodies[i]->getMotionState();
917
delete m_bodies[i]; m_bodies[i] = 0;
918
delete m_shapes[i]; m_shapes[i] = 0;
923
void BenchmarkDemo::createTest3()
925
setCameraDistance(btScalar(50.));
935
btVector3 pos(0.0f, sizeY, 0.0f);
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);
941
RagDoll* ragDoll = new RagDoll (m_dynamicsWorld,pos,scale);
942
m_ragdolls.push_back(ragDoll);
946
pos[1] += (sizeY * 7.0f);
947
pos[2] -= sizeX * 2.0f;
952
void BenchmarkDemo::createTest4()
954
setCameraDistance(btScalar(50.));
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;
962
btConvexHullShape* convexHullShape = new btConvexHullShape();
966
convexHullShape->setLocalScaling(btVector3(scaling,scaling,scaling));
968
for (int i=0;i<TaruVtxCount;i++)
970
btVector3 vtx(TaruVtx[i*3],TaruVtx[i*3+1],TaruVtx[i*3+2]);
971
convexHullShape->addPoint(vtx*btScalar(1./scaling));
974
//this will enable polyhedral contact clipping, better quality, slightly slower
975
//convexHullShape->initializePolyhedralFeatures();
981
btVector3 localInertia(0,0,0);
982
convexHullShape->calculateLocalInertia(mass,localInertia);
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);
993
offset -= 0.05f * spacing * (size-1);
995
pos[1] += (cubeSize * 2.0f + spacing);
1000
///////////////////////////////////////////////////////////////////////////////
1003
int LandscapeVtxCount[] = {
1004
Landscape01VtxCount,
1005
Landscape02VtxCount,
1006
Landscape03VtxCount,
1007
Landscape04VtxCount,
1008
Landscape05VtxCount,
1009
Landscape06VtxCount,
1010
Landscape07VtxCount,
1011
Landscape08VtxCount,
1014
int LandscapeIdxCount[] = {
1015
Landscape01IdxCount,
1016
Landscape02IdxCount,
1017
Landscape03IdxCount,
1018
Landscape04IdxCount,
1019
Landscape05IdxCount,
1020
Landscape06IdxCount,
1021
Landscape07IdxCount,
1022
Landscape08IdxCount,
1025
btScalar *LandscapeVtx[] = {
1036
btScalar *LandscapeNml[] = {
1047
btScalar* LandscapeTex[] = {
1058
unsigned short *LandscapeIdx[] = {
1069
void BenchmarkDemo::createLargeMeshBody()
1072
trans.setIdentity();
1074
for(int i=0;i<8;i++) {
1076
btTriangleIndexVertexArray* meshInterface = new btTriangleIndexVertexArray();
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;
1087
meshInterface->addIndexedMesh(part,PHY_SHORT);
1089
bool useQuantizedAabbCompression = true;
1090
btBvhTriangleMeshShape* trimeshShape = new btBvhTriangleMeshShape(meshInterface,useQuantizedAabbCompression);
1091
btVector3 localInertia(0,0,0);
1092
trans.setOrigin(btVector3(0,-25,0));
1094
btRigidBody* body = localCreateRigidBody(0,trans,trimeshShape);
1095
body->setFriction (btScalar(0.9));
1102
void BenchmarkDemo::createTest5()
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;
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;
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;
1132
trans.setIdentity();
1133
trans.setOrigin(bpos);
1136
case 0:case 1:case 2:
1138
float r = 0.5f * (idx+1);
1139
btBoxShape* boxShape = new btBoxShape(boxSize*r);
1140
localCreateRigidBody(boxMass*r,trans,boxShape);
1144
case 3:case 4:case 5:
1146
float r = 0.5f * (idx-3+1);
1147
btSphereShape* sphereShape = new btSphereShape(sphereRadius*r);
1148
localCreateRigidBody(sphereMass*r,trans,sphereShape);
1152
case 6:case 7:case 8:
1154
float r = 0.5f * (idx-6+1);
1155
btCapsuleShape* capsuleShape = new btCapsuleShape(capsuleRadius*r,capsuleHalf*r);
1156
localCreateRigidBody(capsuleMass*r,trans,capsuleShape);
1164
offset -= 0.05f * spacing * (size-1);
1166
pos[1] += (cubeSize * 2.0f + spacing);
1170
createLargeMeshBody();
1172
void BenchmarkDemo::createTest6()
1174
setCameraDistance(btScalar(250.));
1176
btVector3 boxSize(1.5f,1.5f,1.5f);
1178
btConvexHullShape* convexHullShape = new btConvexHullShape();
1180
for (int i=0;i<TaruVtxCount;i++)
1182
btVector3 vtx(TaruVtx[i*3],TaruVtx[i*3+1],TaruVtx[i*3+2]);
1183
convexHullShape->addPoint(vtx);
1187
trans.setIdentity();
1190
btVector3 localInertia(0,0,0);
1191
convexHullShape->calculateLocalInertia(mass,localInertia);
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;
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);
1212
localCreateRigidBody(mass,trans,convexHullShape);
1215
offset -= 0.05f * spacing * (size-1);
1217
pos[1] += (cubeSize * 2.0f + spacing);
1222
createLargeMeshBody();
1228
void BenchmarkDemo::initRays()
1230
raycastBar = btRaycastBar2 (2500.0, 0,50.0);
1233
void BenchmarkDemo::castRays()
1235
raycastBar.cast (m_dynamicsWorld);
1238
void BenchmarkDemo::createTest7()
1242
setCameraDistance(btScalar(150.));
1246
void BenchmarkDemo::exitPhysics()
1250
for (i=0;i<m_ragdolls.size();i++)
1252
RagDoll* doll = m_ragdolls[i];
1257
//cleanup in the reverse order of creation/initialization
1258
if (m_dynamicsWorld)
1260
//remove the rigidbodies from the dynamics world and delete them
1261
for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
1263
btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
1264
btRigidBody* body = btRigidBody::upcast(obj);
1265
if (body && body->getMotionState())
1267
delete body->getMotionState();
1269
m_dynamicsWorld->removeCollisionObject( obj );
1274
//delete collision shapes
1275
for (int j=0;j<m_collisionShapes.size();j++)
1277
btCollisionShape* shape = m_collisionShapes[j];
1280
m_collisionShapes.clear();
1282
//delete dynamics world
1283
delete m_dynamicsWorld;
1291
delete m_overlappingPairCache;
1292
m_overlappingPairCache=0;
1295
delete m_dispatcher;
1298
delete m_collisionConfiguration;
1299
m_collisionConfiguration=0;
1306
#ifndef USE_GRAPHICAL_BENCHMARK
1308
btRigidBody* DemoApplication::localCreateRigidBody(float mass, const btTransform& startTransform,btCollisionShape* shape)
1310
btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
1312
//rigidbody is dynamic if and only if mass is non zero, otherwise static
1313
bool isDynamic = (mass != 0.f);
1315
btVector3 localInertia(0,0,0);
1317
shape->calculateLocalInertia(mass,localInertia);
1319
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
1321
btRigidBody* body = new btRigidBody(mass,0,shape,localInertia);
1322
body->setWorldTransform(startTransform);
1323
body->setContactProcessingThreshold(m_defaultContactProcessingThreshold);
1324
m_dynamicsWorld->addRigidBody(body);
1328
#endif //USE_GRAPHICAL_BENCHMARK