Initialize libbullet git in 2.0_beta.
[platform/upstream/libbullet.git] / Demos / FractureDemo / FractureDemo.cpp
1 /*\r
2 Bullet Continuous Collision Detection and Physics Library\r
3 Copyright (c) 2003-2011 Erwin Coumans  http://continuousphysics.com/Bullet/\r
4 \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
10 \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
14 */\r
15 \r
16 \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
22 \r
23 \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
27 #define SCALING 1.\r
28 #define START_POS_X -5\r
29 #define START_POS_Y -5\r
30 #define START_POS_Z -3\r
31 \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
37 \r
38 \r
39 #include <stdio.h> //printf debugging\r
40 \r
41 \r
42 int sFrameNumber = 0;\r
43 \r
44 #include "btFractureBody.h"\r
45 #include "btFractureDynamicsWorld.h"\r
46 \r
47 \r
48 \r
49 \r
50 \r
51 void    FractureDemo::initPhysics()\r
52 {\r
53 \r
54         setTexturing(true);\r
55         setShadows(true);\r
56 \r
57         setDebugMode(btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_NoHelpText);\r
58 \r
59         setCameraDistance(btScalar(SCALING*20.));\r
60 \r
61         ///collision configuration contains default setup for memory, collision setup\r
62         m_collisionConfiguration = new btDefaultCollisionConfiguration();\r
63         //m_collisionConfiguration->setConvexConvexMultipointIterations();\r
64 \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
67 \r
68         m_broadphase = new btDbvtBroadphase();\r
69 \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
72         m_solver = sol;\r
73 \r
74         //m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);\r
75 \r
76         btFractureDynamicsWorld* fractureWorld = new btFractureDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);\r
77         m_dynamicsWorld = fractureWorld;\r
78 \r
79         m_ShootBoxInitialSpeed=100; \r
80 \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
83 \r
84         {\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
93         }\r
94 \r
95         {\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
99                 btTransform tr;\r
100                 tr.setIdentity();\r
101                 tr.setOrigin(btVector3(5,2,0));\r
102                 localCreateRigidBody(0.f,tr,shape);\r
103         }\r
104 \r
105 \r
106 \r
107         {\r
108                 //create a few dynamic rigidbodies\r
109                 // Re-using the same collision is better for memory usage and performance\r
110 \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
115 \r
116                 /// Create Dynamic Objects\r
117                 btTransform startTransform;\r
118                 startTransform.setIdentity();\r
119 \r
120                 btScalar        mass(1.f);\r
121 \r
122                 //rigidbody is dynamic if and only if mass is non zero, otherwise static\r
123                 bool isDynamic = (mass != 0.f);\r
124 \r
125                 btVector3 localInertia(0,0,0);\r
126                 if (isDynamic)\r
127                         colShape->calculateLocalInertia(mass,localInertia);\r
128 \r
129 \r
130                 int gNumObjects = 10;\r
131 \r
132                 for (int i=0;i<gNumObjects;i++)\r
133                 {\r
134                         btTransform trans;\r
135                         trans.setIdentity();\r
136 \r
137                         btVector3 pos(i*2*CUBE_HALF_EXTENTS ,20,0);\r
138                         trans.setOrigin(pos);\r
139 \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
145 \r
146                         m_dynamicsWorld->addRigidBody(body);\r
147 \r
148 \r
149                 }\r
150 \r
151         }\r
152 \r
153 \r
154 \r
155         fractureWorld->stepSimulation(1./60.,0);\r
156         fractureWorld->glueCallback();\r
157 \r
158 \r
159 \r
160 }\r
161 \r
162 void    FractureDemo::clientResetScene()\r
163 {\r
164         exitPhysics();\r
165         initPhysics();\r
166 }\r
167 \r
168 \r
169 void FractureDemo::clientMoveAndDisplay()\r
170 {\r
171         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); \r
172 \r
173         //simple dynamics world doesn't handle fixed-time-stepping\r
174         float ms = getDeltaTimeMicroseconds();\r
175 \r
176         ///step the simulation\r
177         if (m_dynamicsWorld)\r
178         {\r
179                 m_dynamicsWorld->stepSimulation(ms / 1000000.f);\r
180                 //optional but useful: debug drawing\r
181                 m_dynamicsWorld->debugDrawWorld();\r
182         }\r
183 \r
184 \r
185 \r
186         renderme(); \r
187 \r
188         showMessage();\r
189 \r
190         glFlush();\r
191 \r
192         swapBuffers();\r
193 \r
194 }\r
195 \r
196 void FractureDemo::showMessage()\r
197 {\r
198         if((getDebugMode() & btIDebugDraw::DBG_DrawText))\r
199         {\r
200                 setOrthographicProjection();\r
201                 glDisable(GL_LIGHTING);\r
202                 glColor3f(0, 0, 0);\r
203                 char buf[124];\r
204 \r
205                 int lineWidth=380;\r
206                 int xStart = m_glutScreenWidth - lineWidth;\r
207                 int yStart = 20;\r
208 \r
209                 btFractureDynamicsWorld* world = (btFractureDynamicsWorld*)m_dynamicsWorld;\r
210                 if (world->getFractureMode())\r
211                 {\r
212                         sprintf(buf,"Fracture mode");\r
213                 } else\r
214                 {\r
215                         sprintf(buf,"Glue mode");\r
216                 }\r
217                 GLDebugDrawString(xStart,yStart,buf);\r
218                 sprintf(buf,"f to toggle fracture/glue mode");          \r
219                 yStart+=20;\r
220                 GLDebugDrawString(xStart,yStart,buf);\r
221                 sprintf(buf,"space to restart, mouse to pick/shoot");\r
222                 yStart+=20;\r
223                 GLDebugDrawString(xStart,yStart,buf);\r
224 \r
225                 resetPerspectiveProjection();\r
226                 glEnable(GL_LIGHTING);\r
227         }\r
228 \r
229 }\r
230 \r
231 \r
232 void FractureDemo::displayCallback(void) {\r
233 \r
234         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); \r
235 \r
236         renderme();\r
237 \r
238         showMessage();\r
239 \r
240         //optional but useful: debug drawing to detect problems\r
241         if (m_dynamicsWorld)\r
242                 m_dynamicsWorld->debugDrawWorld();\r
243 \r
244         glFlush();\r
245         swapBuffers();\r
246 }\r
247 \r
248 \r
249 void FractureDemo::keyboardUpCallback(unsigned char key, int x, int y)\r
250 {\r
251         if (key=='f')\r
252         {\r
253                 btFractureDynamicsWorld* world = (btFractureDynamicsWorld*)m_dynamicsWorld;\r
254                 world->setFractureMode(!world->getFractureMode());\r
255         }\r
256 \r
257         PlatformDemoApplication::keyboardUpCallback(key,x,y);\r
258 \r
259 }\r
260 \r
261 \r
262 void    FractureDemo::shootBox(const btVector3& destination)\r
263 {\r
264 \r
265         if (m_dynamicsWorld)\r
266         {\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
272 \r
273                 setShootBoxShape ();\r
274 \r
275                 btAssert((!m_shootBoxShape || m_shootBoxShape->getShapeType() != INVALID_SHAPE_PROXYTYPE));\r
276 \r
277                 //rigidbody is dynamic if and only if mass is non zero, otherwise static\r
278                 bool isDynamic = (mass != 0.f);\r
279 \r
280                 btVector3 localInertia(0,0,0);\r
281                 if (isDynamic)\r
282                         m_shootBoxShape->calculateLocalInertia(mass,localInertia);\r
283 \r
284                 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects\r
285 \r
286                 btFractureBody* body = new btFractureBody(mass,0,m_shootBoxShape,localInertia,&mass,1,m_dynamicsWorld);\r
287 \r
288                 body->setWorldTransform(startTransform);\r
289 \r
290                 m_dynamicsWorld->addRigidBody(body);\r
291 \r
292 \r
293                 body->setLinearFactor(btVector3(1,1,1));\r
294                 //body->setRestitution(1);\r
295 \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
299 \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
306 \r
307         }\r
308 }\r
309 \r
310 \r
311 \r
312 \r
313 \r
314 \r
315 void    FractureDemo::exitPhysics()\r
316 {\r
317 \r
318         //cleanup in the reverse order of creation/initialization\r
319 \r
320         //remove the rigidbodies from the dynamics world and delete them\r
321         int i;\r
322         for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)\r
323         {\r
324                 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];\r
325                 btRigidBody* body = btRigidBody::upcast(obj);\r
326                 if (body && body->getMotionState())\r
327                 {\r
328                         delete body->getMotionState();\r
329                 }\r
330                 m_dynamicsWorld->removeCollisionObject( obj );\r
331                 delete obj;\r
332         }\r
333 \r
334         //delete collision shapes\r
335         for (int j=0;j<m_collisionShapes.size();j++)\r
336         {\r
337                 btCollisionShape* shape = m_collisionShapes[j];\r
338                 delete shape;\r
339         }\r
340 \r
341         m_collisionShapes.clear();\r
342 \r
343         delete m_dynamicsWorld;\r
344         m_dynamicsWorld=0;\r
345 \r
346         delete m_solver;\r
347         m_solver=0;\r
348 \r
349         delete m_broadphase;\r
350         m_broadphase=0;\r
351 \r
352         delete m_dispatcher;\r
353         m_dispatcher=0;\r
354 \r
355         delete m_collisionConfiguration;\r
356         m_collisionConfiguration=0;\r
357 \r
358 }\r
359 \r
360 \r
361 \r
362 \r