2 Bullet Continuous Collision Detection and Physics Library
\r
3 Copyright (c) 2003-2011 Erwin Coumans http://continuousphysics.com/Bullet/
\r
5 This software is provided 'as-is', without any express or implied warranty.
\r
6 In no event will the authors be held liable for any damages arising from the use of this software.
\r
7 Permission is granted to anyone to use this software for any purpose,
\r
8 including commercial applications, and to alter it and redistribute it freely,
\r
9 subject to the following restrictions:
\r
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.
\r
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
\r
13 3. This notice may not be removed or altered from any source distribution.
\r
17 ///FractureDemo shows how to break objects.
\r
18 ///It assumes a btCompoundShaps (where the childshapes are the pre-fractured pieces)
\r
19 ///The btFractureBody is a class derived from btRigidBody, dealing with the collision impacts.
\r
20 ///Press the F key to toggle between fracture and glue mode
\r
21 ///This is preliminary work
\r
24 #define CUBE_HALF_EXTENTS 1.f
\r
25 #define EXTRA_HEIGHT 1.f
\r
26 ///scaling of the objects (0.1 = 20 centimeter boxes )
\r
28 #define START_POS_X -5
\r
29 #define START_POS_Y -5
\r
30 #define START_POS_Z -3
\r
32 #include "FractureDemo.h"
\r
33 #include "GlutStuff.h"
\r
34 #include "GLDebugFont.h"
\r
35 ///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
\r
36 #include "btBulletDynamicsCommon.h"
\r
39 #include <stdio.h> //printf debugging
\r
42 int sFrameNumber = 0;
\r
44 #include "btFractureBody.h"
\r
45 #include "btFractureDynamicsWorld.h"
\r
51 void FractureDemo::initPhysics()
\r
57 setDebugMode(btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_NoHelpText);
\r
59 setCameraDistance(btScalar(SCALING*20.));
\r
61 ///collision configuration contains default setup for memory, collision setup
\r
62 m_collisionConfiguration = new btDefaultCollisionConfiguration();
\r
63 //m_collisionConfiguration->setConvexConvexMultipointIterations();
\r
65 ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
\r
66 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
\r
68 m_broadphase = new btDbvtBroadphase();
\r
70 ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
\r
71 btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
\r
74 //m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
\r
76 btFractureDynamicsWorld* fractureWorld = new btFractureDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
\r
77 m_dynamicsWorld = fractureWorld;
\r
79 m_ShootBoxInitialSpeed=100;
\r
81 //m_splitImpulse removes the penetration resolution from the applied impulse, otherwise objects might fracture due to deep penetrations.
\r
82 m_dynamicsWorld->getSolverInfo().m_splitImpulse = true;
\r
85 ///create a few basic rigid bodies
\r
86 btCollisionShape* groundShape = new btBoxShape(btVector3(50,1,50));
\r
87 /// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),0);
\r
88 m_collisionShapes.push_back(groundShape);
\r
89 btTransform groundTransform;
\r
90 groundTransform.setIdentity();
\r
91 groundTransform.setOrigin(btVector3(0,0,0));
\r
92 localCreateRigidBody(0.f,groundTransform,groundShape);
\r
96 ///create a few basic rigid bodies
\r
97 btCollisionShape* shape = new btBoxShape(btVector3(1,1,1));
\r
98 m_collisionShapes.push_back(shape);
\r
101 tr.setOrigin(btVector3(5,2,0));
\r
102 localCreateRigidBody(0.f,tr,shape);
\r
108 //create a few dynamic rigidbodies
\r
109 // Re-using the same collision is better for memory usage and performance
\r
111 btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1));
\r
112 //btCollisionShape* colShape = new btCapsuleShape(SCALING*0.4,SCALING*1);
\r
113 //btCollisionShape* colShape = new btSphereShape(btScalar(1.));
\r
114 m_collisionShapes.push_back(colShape);
\r
116 /// Create Dynamic Objects
\r
117 btTransform startTransform;
\r
118 startTransform.setIdentity();
\r
120 btScalar mass(1.f);
\r
122 //rigidbody is dynamic if and only if mass is non zero, otherwise static
\r
123 bool isDynamic = (mass != 0.f);
\r
125 btVector3 localInertia(0,0,0);
\r
127 colShape->calculateLocalInertia(mass,localInertia);
\r
130 int gNumObjects = 10;
\r
132 for (int i=0;i<gNumObjects;i++)
\r
135 trans.setIdentity();
\r
137 btVector3 pos(i*2*CUBE_HALF_EXTENTS ,20,0);
\r
138 trans.setOrigin(pos);
\r
140 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
\r
141 btDefaultMotionState* myMotionState = new btDefaultMotionState(trans);
\r
142 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
\r
143 btFractureBody* body = new btFractureBody(rbInfo, m_dynamicsWorld);
\r
144 body->setLinearVelocity(btVector3(0,-10,0));
\r
146 m_dynamicsWorld->addRigidBody(body);
\r
155 fractureWorld->stepSimulation(1./60.,0);
\r
156 fractureWorld->glueCallback();
\r
162 void FractureDemo::clientResetScene()
\r
169 void FractureDemo::clientMoveAndDisplay()
\r
171 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
\r
173 //simple dynamics world doesn't handle fixed-time-stepping
\r
174 float ms = getDeltaTimeMicroseconds();
\r
176 ///step the simulation
\r
177 if (m_dynamicsWorld)
\r
179 m_dynamicsWorld->stepSimulation(ms / 1000000.f);
\r
180 //optional but useful: debug drawing
\r
181 m_dynamicsWorld->debugDrawWorld();
\r
196 void FractureDemo::showMessage()
\r
198 if((getDebugMode() & btIDebugDraw::DBG_DrawText))
\r
200 setOrthographicProjection();
\r
201 glDisable(GL_LIGHTING);
\r
202 glColor3f(0, 0, 0);
\r
206 int xStart = m_glutScreenWidth - lineWidth;
\r
209 btFractureDynamicsWorld* world = (btFractureDynamicsWorld*)m_dynamicsWorld;
\r
210 if (world->getFractureMode())
\r
212 sprintf(buf,"Fracture mode");
\r
215 sprintf(buf,"Glue mode");
\r
217 GLDebugDrawString(xStart,yStart,buf);
\r
218 sprintf(buf,"f to toggle fracture/glue mode");
\r
220 GLDebugDrawString(xStart,yStart,buf);
\r
221 sprintf(buf,"space to restart, mouse to pick/shoot");
\r
223 GLDebugDrawString(xStart,yStart,buf);
\r
225 resetPerspectiveProjection();
\r
226 glEnable(GL_LIGHTING);
\r
232 void FractureDemo::displayCallback(void) {
\r
234 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
\r
240 //optional but useful: debug drawing to detect problems
\r
241 if (m_dynamicsWorld)
\r
242 m_dynamicsWorld->debugDrawWorld();
\r
249 void FractureDemo::keyboardUpCallback(unsigned char key, int x, int y)
\r
253 btFractureDynamicsWorld* world = (btFractureDynamicsWorld*)m_dynamicsWorld;
\r
254 world->setFractureMode(!world->getFractureMode());
\r
257 PlatformDemoApplication::keyboardUpCallback(key,x,y);
\r
262 void FractureDemo::shootBox(const btVector3& destination)
\r
265 if (m_dynamicsWorld)
\r
267 btScalar mass = 1.f;
\r
268 btTransform startTransform;
\r
269 startTransform.setIdentity();
\r
270 btVector3 camPos = getCameraPosition();
\r
271 startTransform.setOrigin(camPos);
\r
273 setShootBoxShape ();
\r
275 btAssert((!m_shootBoxShape || m_shootBoxShape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
\r
277 //rigidbody is dynamic if and only if mass is non zero, otherwise static
\r
278 bool isDynamic = (mass != 0.f);
\r
280 btVector3 localInertia(0,0,0);
\r
282 m_shootBoxShape->calculateLocalInertia(mass,localInertia);
\r
284 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
\r
286 btFractureBody* body = new btFractureBody(mass,0,m_shootBoxShape,localInertia,&mass,1,m_dynamicsWorld);
\r
288 body->setWorldTransform(startTransform);
\r
290 m_dynamicsWorld->addRigidBody(body);
\r
293 body->setLinearFactor(btVector3(1,1,1));
\r
294 //body->setRestitution(1);
\r
296 btVector3 linVel(destination[0]-camPos[0],destination[1]-camPos[1],destination[2]-camPos[2]);
\r
297 linVel.normalize();
\r
298 linVel*=m_ShootBoxInitialSpeed;
\r
300 body->getWorldTransform().setOrigin(camPos);
\r
301 body->getWorldTransform().setRotation(btQuaternion(0,0,0,1));
\r
302 body->setLinearVelocity(linVel);
\r
303 body->setAngularVelocity(btVector3(0,0,0));
\r
304 body->setCcdMotionThreshold(1.);
\r
305 body->setCcdSweptSphereRadius(0.2f);
\r
315 void FractureDemo::exitPhysics()
\r
318 //cleanup in the reverse order of creation/initialization
\r
320 //remove the rigidbodies from the dynamics world and delete them
\r
322 for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
\r
324 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
\r
325 btRigidBody* body = btRigidBody::upcast(obj);
\r
326 if (body && body->getMotionState())
\r
328 delete body->getMotionState();
\r
330 m_dynamicsWorld->removeCollisionObject( obj );
\r
334 //delete collision shapes
\r
335 for (int j=0;j<m_collisionShapes.size();j++)
\r
337 btCollisionShape* shape = m_collisionShapes[j];
\r
341 m_collisionShapes.clear();
\r
343 delete m_dynamicsWorld;
\r
349 delete m_broadphase;
\r
352 delete m_dispatcher;
\r
355 delete m_collisionConfiguration;
\r
356 m_collisionConfiguration=0;
\r