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.
18 #define CUBE_HALF_EXTENTS 1
20 #define EXTRA_HEIGHT 1.f
22 #include "CcdPhysicsDemo.h"
23 #include "GlutStuff.h"
24 #include "GLDebugFont.h"
26 ///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
27 #include "btBulletDynamicsCommon.h"
29 #include <stdio.h> //printf debugging
30 #include "GLDebugDrawer.h"
33 extern btAlignedObjectArray<btVector3> debugContacts;
34 extern btAlignedObjectArray<btVector3> debugNormals;
37 static GLDebugDrawer sDebugDrawer;
40 CcdPhysicsDemo::CcdPhysicsDemo()
43 setDebugMode(btIDebugDraw::DBG_DrawText+btIDebugDraw::DBG_NoHelpText);
44 setCameraDistance(btScalar(40.));
48 void CcdPhysicsDemo::clientMoveAndDisplay()
50 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
52 //simple dynamics world doesn't handle fixed-time-stepping
53 //float ms = getDeltaTimeMicroseconds();
55 ///step the simulation
58 m_dynamicsWorld->stepSimulation(1./60.,0);//ms / 1000000.f);
59 //optional but useful: debug drawing
60 m_dynamicsWorld->debugDrawWorld();
67 for (int i=0;i<debugContacts.size();i++)
69 getDynamicsWorld()->getDebugDrawer()->drawContactPoint(debugContacts[i],debugNormals[i],0,0,btVector3(1,0,0));
80 void CcdPhysicsDemo::displayText()
83 int xStart = m_glutScreenWidth - lineWidth;
86 if((getDebugMode() & btIDebugDraw::DBG_DrawText)!=0)
88 setOrthographicProjection();
89 glDisable(GL_LIGHTING);
93 glRasterPos3f(xStart, yStart, 0);
98 sprintf(buf,"Predictive contacts and motion clamping");
103 sprintf(buf,"CCD handling disabled");
108 sprintf(buf,"unknown CCD setting");
112 GLDebugDrawString(xStart,20,buf);
113 glRasterPos3f(xStart, yStart, 0);
114 sprintf(buf,"Press 'p' to change CCD mode");
116 GLDebugDrawString(xStart,yStart,buf);
117 glRasterPos3f(xStart, yStart, 0);
118 sprintf(buf,"Press '.' or right mouse to shoot bullets");
120 GLDebugDrawString(xStart,yStart,buf);
121 glRasterPos3f(xStart, yStart, 0);
122 sprintf(buf,"space to restart, h(elp), t(ext), w(ire)");
124 GLDebugDrawString(xStart,yStart,buf);
126 resetPerspectiveProjection();
127 glEnable(GL_LIGHTING);
134 void CcdPhysicsDemo::displayCallback(void) {
136 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
142 //optional but useful: debug drawing to detect problems
145 m_dynamicsWorld->debugDrawWorld();
148 for (int i=0;i<debugContacts.size();i++)
150 getDynamicsWorld()->getDebugDrawer()->drawContactPoint(debugContacts[i],debugNormals[i],0,0,btVector3(1,0,0));
162 void CcdPhysicsDemo::initPhysics()
167 m_ShootBoxInitialSpeed = 4000.f;
169 m_defaultContactProcessingThreshold = 0.f;
171 ///collision configuration contains default setup for memory, collision setup
172 m_collisionConfiguration = new btDefaultCollisionConfiguration();
173 // m_collisionConfiguration->setConvexConvexMultipointIterations();
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));
179 m_broadphase = new btDbvtBroadphase();
181 ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
182 btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
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;
190 m_dynamicsWorld ->setDebugDrawer(&sDebugDrawer);
192 //m_dynamicsWorld->getSolverInfo().m_splitImpulse=false;
196 if (m_ccdMode==USE_CCD)
198 m_dynamicsWorld->getDispatchInfo().m_useContinuous=true;
201 m_dynamicsWorld->getDispatchInfo().m_useContinuous=false;
204 m_dynamicsWorld->setGravity(btVector3(0,-10,0));
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;
211 // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);
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)));
217 btTransform groundTransform;
218 groundTransform.setIdentity();
219 //groundTransform.setOrigin(btVector3(5,5,5));
221 //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
225 //rigidbody is dynamic if and only if mass is non zero, otherwise static
226 bool isDynamic = (mass != 0.f);
228 btVector3 localInertia(0,0,0);
230 groundShape->calculateLocalInertia(mass,localInertia);
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);
244 //create a few dynamic rigidbodies
245 // Re-using the same collision is better for memory usage and performance
247 btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
249 //btCollisionShape* colShape = new btSphereShape(btScalar(1.));
250 m_collisionShapes.push_back(colShape);
252 /// Create Dynamic Objects
253 btTransform startTransform;
254 startTransform.setIdentity();
258 //rigidbody is dynamic if and only if mass is non zero, otherwise static
259 bool isDynamic = (mass != 0.f);
261 btVector3 localInertia(0,0,0);
263 colShape->calculateLocalInertia(mass,localInertia);
265 int gNumObjects = 120;//120;
267 for (i=0;i<gNumObjects;i++)
269 btCollisionShape* shape = m_collisionShapes[1];
276 int row = (i*CUBE_HALF_EXTENTS*2)/(colsize*2*CUBE_HALF_EXTENTS);
278 int col = (i)%(colsize)-colsize/2;
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);
290 trans.setOrigin(pos);
294 btRigidBody* body = localCreateRigidBody(mass,trans,shape);
295 body->setAnisotropicFriction(shape->getAnisotropicRollingFrictionDirection(),btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
296 body->setFriction(0.5);
298 //body->setRollingFriction(.3);
299 ///when using m_ccdMode
300 if (m_ccdMode==USE_CCD)
302 body->setCcdMotionThreshold(CUBE_HALF_EXTENTS);
303 body->setCcdSweptSphereRadius(0.9*CUBE_HALF_EXTENTS);
310 void CcdPhysicsDemo::clientResetScene()
316 void CcdPhysicsDemo::keyboardCallback(unsigned char key, int x, int y)
324 m_ccdMode = USE_NO_CCD;
336 DemoApplication::keyboardCallback(key,x,y);
341 void CcdPhysicsDemo::shootBox(const btVector3& destination)
347 btTransform startTransform;
348 startTransform.setIdentity();
349 btVector3 camPos = getCameraPosition();
350 startTransform.setOrigin(camPos);
355 btRigidBody* body = this->localCreateRigidBody(mass, startTransform,m_shootBoxShape);
356 body->setLinearFactor(btVector3(1,1,1));
357 //body->setRestitution(1);
359 btVector3 linVel(destination[0]-camPos[0],destination[1]-camPos[1],destination[2]-camPos[2]);
361 linVel*=m_ShootBoxInitialSpeed;
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);
369 ///when using m_ccdMode, disable regular CCD
370 if (m_ccdMode==USE_CCD)
372 body->setCcdMotionThreshold(CUBE_HALF_EXTENTS);
373 body->setCcdSweptSphereRadius(0.4f);
382 void CcdPhysicsDemo::exitPhysics()
385 //cleanup in the reverse order of creation/initialization
387 //remove the rigidbodies from the dynamics world and delete them
389 for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
391 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
392 btRigidBody* body = btRigidBody::upcast(obj);
393 if (body && body->getMotionState())
395 delete body->getMotionState();
397 m_dynamicsWorld->removeCollisionObject( obj );
401 //delete collision shapes
402 for (int j=0;j<m_collisionShapes.size();j++)
404 btCollisionShape* shape = m_collisionShapes[j];
407 m_collisionShapes.clear();
409 delete m_dynamicsWorld;
417 delete m_collisionConfiguration;