Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Demos / CcdPhysicsDemo / CcdPhysicsDemo.cpp
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 #define CUBE_HALF_EXTENTS 1
19
20 #define EXTRA_HEIGHT 1.f
21
22 #include "CcdPhysicsDemo.h"
23 #include "GlutStuff.h"
24 #include "GLDebugFont.h"
25
26 ///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
27 #include "btBulletDynamicsCommon.h"
28
29 #include <stdio.h> //printf debugging
30 #include "GLDebugDrawer.h"
31
32 #if 0
33 extern btAlignedObjectArray<btVector3> debugContacts;
34 extern btAlignedObjectArray<btVector3> debugNormals;
35 #endif 
36
37 static GLDebugDrawer    sDebugDrawer;
38
39
40 CcdPhysicsDemo::CcdPhysicsDemo()
41 :m_ccdMode(USE_CCD)
42 {
43         setDebugMode(btIDebugDraw::DBG_DrawText+btIDebugDraw::DBG_NoHelpText);
44         setCameraDistance(btScalar(40.));
45 }
46
47
48 void CcdPhysicsDemo::clientMoveAndDisplay()
49 {
50         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
51
52         //simple dynamics world doesn't handle fixed-time-stepping
53         //float ms = getDeltaTimeMicroseconds();
54         
55         ///step the simulation
56         if (m_dynamicsWorld)
57         {
58                 m_dynamicsWorld->stepSimulation(1./60.,0);//ms / 1000000.f);
59                 //optional but useful: debug drawing
60                 m_dynamicsWorld->debugDrawWorld();
61         }
62                 
63         renderme(); 
64
65         displayText();
66 #if 0
67         for (int i=0;i<debugContacts.size();i++)
68         {
69                 getDynamicsWorld()->getDebugDrawer()->drawContactPoint(debugContacts[i],debugNormals[i],0,0,btVector3(1,0,0));
70         }
71 #endif
72
73         glFlush();
74
75         swapBuffers();
76
77 }
78
79
80 void CcdPhysicsDemo::displayText()
81 {
82         int lineWidth=440;
83         int xStart = m_glutScreenWidth - lineWidth;
84         int yStart = 20;
85
86         if((getDebugMode() & btIDebugDraw::DBG_DrawText)!=0)
87         {
88                 setOrthographicProjection();
89                 glDisable(GL_LIGHTING);
90                 glColor3f(0, 0, 0);
91                 char buf[124];
92                 
93                 glRasterPos3f(xStart, yStart, 0);
94                 switch (m_ccdMode)
95                 {
96                 case USE_CCD:
97                         {
98                                 sprintf(buf,"Predictive contacts and motion clamping");
99                                 break;
100                         }
101                 case USE_NO_CCD:
102                         {
103                                 sprintf(buf,"CCD handling disabled");
104                                 break;
105                         }
106                 default:
107                         {
108                                 sprintf(buf,"unknown CCD setting");
109                         };
110                 };
111
112                 GLDebugDrawString(xStart,20,buf);
113                 glRasterPos3f(xStart, yStart, 0);
114                 sprintf(buf,"Press 'p' to change CCD mode");
115                 yStart+=20;
116                 GLDebugDrawString(xStart,yStart,buf);
117                 glRasterPos3f(xStart, yStart, 0);
118                 sprintf(buf,"Press '.' or right mouse to shoot bullets");
119                 yStart+=20;
120                 GLDebugDrawString(xStart,yStart,buf);
121                 glRasterPos3f(xStart, yStart, 0);
122                 sprintf(buf,"space to restart, h(elp), t(ext), w(ire)");
123                 yStart+=20;
124                 GLDebugDrawString(xStart,yStart,buf);
125                 
126                 resetPerspectiveProjection();
127                 glEnable(GL_LIGHTING);
128         }       
129
130 }
131
132
133
134 void CcdPhysicsDemo::displayCallback(void) {
135
136         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
137         
138         renderme();
139
140         displayText();
141
142         //optional but useful: debug drawing to detect problems
143         if (m_dynamicsWorld)
144         {
145                 m_dynamicsWorld->debugDrawWorld();
146         }
147 #if 0
148         for (int i=0;i<debugContacts.size();i++)
149         {
150                 getDynamicsWorld()->getDebugDrawer()->drawContactPoint(debugContacts[i],debugNormals[i],0,0,btVector3(1,0,0));
151         }
152 #endif
153
154         glFlush();
155         swapBuffers();
156 }
157
158
159
160
161
162 void    CcdPhysicsDemo::initPhysics()
163 {
164         setTexturing(true);
165         setShadows(true);
166         
167         m_ShootBoxInitialSpeed = 4000.f;
168
169         m_defaultContactProcessingThreshold = 0.f;
170
171         ///collision configuration contains default setup for memory, collision setup
172         m_collisionConfiguration = new btDefaultCollisionConfiguration();
173 //      m_collisionConfiguration->setConvexConvexMultipointIterations();
174
175         ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
176         m_dispatcher = new      btCollisionDispatcher(m_collisionConfiguration);
177         //m_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,m_collisionConfiguration->getCollisionAlgorithmCreateFunc(CONVEX_SHAPE_PROXYTYPE,CONVEX_SHAPE_PROXYTYPE));
178
179         m_broadphase = new btDbvtBroadphase();
180
181         ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
182         btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
183         m_solver = sol;
184
185         m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
186         m_dynamicsWorld->getSolverInfo().m_solverMode |=SOLVER_USE_2_FRICTION_DIRECTIONS|SOLVER_RANDMIZE_ORDER;
187         
188         
189
190         m_dynamicsWorld ->setDebugDrawer(&sDebugDrawer);
191
192         //m_dynamicsWorld->getSolverInfo().m_splitImpulse=false;
193         
194
195
196         if (m_ccdMode==USE_CCD)
197         {
198                 m_dynamicsWorld->getDispatchInfo().m_useContinuous=true;
199         } else
200         {
201                 m_dynamicsWorld->getDispatchInfo().m_useContinuous=false;
202         }
203
204         m_dynamicsWorld->setGravity(btVector3(0,-10,0));
205
206         ///create a few basic rigid bodies
207         btBoxShape* box = new btBoxShape(btVector3(btScalar(110.),btScalar(1.),btScalar(110.)));
208 //      box->initializePolyhedralFeatures();
209         btCollisionShape* groundShape = box;
210
211 //      btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);
212         
213         m_collisionShapes.push_back(groundShape);
214         //m_collisionShapes.push_back(new btCylinderShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS)));
215         m_collisionShapes.push_back(new btBoxShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS)));
216
217         btTransform groundTransform;
218         groundTransform.setIdentity();
219         //groundTransform.setOrigin(btVector3(5,5,5));
220
221         //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
222         {
223                 btScalar mass(0.);
224
225                 //rigidbody is dynamic if and only if mass is non zero, otherwise static
226                 bool isDynamic = (mass != 0.f);
227
228                 btVector3 localInertia(0,0,0);
229                 if (isDynamic)
230                         groundShape->calculateLocalInertia(mass,localInertia);
231
232                 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
233                 btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
234                 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
235                 btRigidBody* body = new btRigidBody(rbInfo);
236                 body->setFriction(0.5);
237                 //body->setRollingFriction(0.3);
238                 //add the body to the dynamics world
239                 m_dynamicsWorld->addRigidBody(body);
240         }
241
242
243         {
244                 //create a few dynamic rigidbodies
245                 // Re-using the same collision is better for memory usage and performance
246
247                 btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
248
249                 //btCollisionShape* colShape = new btSphereShape(btScalar(1.));
250                 m_collisionShapes.push_back(colShape);
251
252                 /// Create Dynamic Objects
253                 btTransform startTransform;
254                 startTransform.setIdentity();
255
256                 btScalar        mass(1.f);
257
258                 //rigidbody is dynamic if and only if mass is non zero, otherwise static
259                 bool isDynamic = (mass != 0.f);
260
261                 btVector3 localInertia(0,0,0);
262                 if (isDynamic)
263                         colShape->calculateLocalInertia(mass,localInertia);
264
265                 int gNumObjects = 120;//120;
266                 int i;
267                 for (i=0;i<gNumObjects;i++)
268                 {
269                         btCollisionShape* shape = m_collisionShapes[1];
270                         
271                         btTransform trans;
272                         trans.setIdentity();
273
274                         //stack them
275                         int colsize = 10;
276                         int row = (i*CUBE_HALF_EXTENTS*2)/(colsize*2*CUBE_HALF_EXTENTS);
277                         int row2 = row;
278                         int col = (i)%(colsize)-colsize/2;
279
280
281                         if (col>3)
282                         {
283                                 col=11;
284                                 row2 |=1;
285                         }
286
287                         btVector3 pos(col*2*CUBE_HALF_EXTENTS + (row2%2)*CUBE_HALF_EXTENTS,
288                                 row*2*CUBE_HALF_EXTENTS+CUBE_HALF_EXTENTS+EXTRA_HEIGHT,0);
289
290                         trans.setOrigin(pos);
291         
292                         float mass = 1.f;
293
294                         btRigidBody* body = localCreateRigidBody(mass,trans,shape);
295                         body->setAnisotropicFriction(shape->getAnisotropicRollingFrictionDirection(),btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
296                         body->setFriction(0.5);
297
298                         //body->setRollingFriction(.3); 
299                         ///when using m_ccdMode
300                         if (m_ccdMode==USE_CCD)
301                         {
302                                 body->setCcdMotionThreshold(CUBE_HALF_EXTENTS);
303                                 body->setCcdSweptSphereRadius(0.9*CUBE_HALF_EXTENTS);
304                         }
305                 }
306         }
307
308 }
309
310 void    CcdPhysicsDemo::clientResetScene()
311 {
312         exitPhysics();
313         initPhysics();
314 }
315
316 void CcdPhysicsDemo::keyboardCallback(unsigned char key, int x, int y)
317 {
318         if (key=='p')
319         {
320                 switch (m_ccdMode)
321                 {
322                         case USE_CCD:
323                         {
324                                 m_ccdMode = USE_NO_CCD;
325                                 break;
326                         }
327                         case USE_NO_CCD:
328                         default:
329                         {
330                                 m_ccdMode = USE_CCD;
331                         }
332                 };
333                 clientResetScene();
334         } else
335         {
336                 DemoApplication::keyboardCallback(key,x,y);
337         }
338 }
339
340
341 void    CcdPhysicsDemo::shootBox(const btVector3& destination)
342 {
343
344         if (m_dynamicsWorld)
345         {
346                 float mass = 1.f;
347                 btTransform startTransform;
348                 startTransform.setIdentity();
349                 btVector3 camPos = getCameraPosition();
350                 startTransform.setOrigin(camPos);
351
352                 setShootBoxShape ();
353
354
355                 btRigidBody* body = this->localCreateRigidBody(mass, startTransform,m_shootBoxShape);
356                 body->setLinearFactor(btVector3(1,1,1));
357                 //body->setRestitution(1);
358
359                 btVector3 linVel(destination[0]-camPos[0],destination[1]-camPos[1],destination[2]-camPos[2]);
360                 linVel.normalize();
361                 linVel*=m_ShootBoxInitialSpeed;
362
363                 body->getWorldTransform().setOrigin(camPos);
364                 body->getWorldTransform().setRotation(btQuaternion(0,0,0,1));
365                 body->setLinearVelocity(linVel);
366                 body->setAngularVelocity(btVector3(0,0,0));
367                 body->setContactProcessingThreshold(1e30);
368
369                 ///when using m_ccdMode, disable regular CCD
370                 if (m_ccdMode==USE_CCD)
371                 {
372                         body->setCcdMotionThreshold(CUBE_HALF_EXTENTS);
373                         body->setCcdSweptSphereRadius(0.4f);
374                 }
375                 
376         }
377 }
378
379
380
381
382 void    CcdPhysicsDemo::exitPhysics()
383 {
384
385         //cleanup in the reverse order of creation/initialization
386
387         //remove the rigidbodies from the dynamics world and delete them
388         int i;
389         for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
390         {
391                 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
392                 btRigidBody* body = btRigidBody::upcast(obj);
393                 if (body && body->getMotionState())
394                 {
395                         delete body->getMotionState();
396                 }
397                 m_dynamicsWorld->removeCollisionObject( obj );
398                 delete obj;
399         }
400
401         //delete collision shapes
402         for (int j=0;j<m_collisionShapes.size();j++)
403         {
404                 btCollisionShape* shape = m_collisionShapes[j];
405                 delete shape;
406         }
407         m_collisionShapes.clear();
408
409         delete m_dynamicsWorld;
410         
411         delete m_solver;
412         
413         delete m_broadphase;
414         
415         delete m_dispatcher;
416
417         delete m_collisionConfiguration;
418
419         
420 }
421
422
423
424