2 Bullet Continuous Collision Detection and Physics Library
\r
3 Copyright (c) 2003-2006 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 ///create 125 (5x5x5) dynamic object
\r
18 #define ARRAY_SIZE_X 5
\r
19 #define ARRAY_SIZE_Y 5
\r
20 #define ARRAY_SIZE_Z 5
\r
22 //maximum number of objects (and allow user to shoot additional boxes)
\r
23 #define MAX_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z + 1024)
\r
25 ///scaling of the objects (0.1 = 20 centimeter boxes )
\r
27 #define START_POS_X -5
\r
28 #define START_POS_Y -5
\r
29 #define START_POS_Z -3
\r
31 #include "RollingFrictionDemo.h"
\r
32 #include "GlutStuff.h"
\r
33 ///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
\r
34 #include "btBulletDynamicsCommon.h"
\r
35 #include "GLDebugDrawer.h"
\r
36 static GLDebugDrawer sDebugDraw;
\r
37 #include <stdio.h> //printf debugging
\r
40 void RollingFrictionDemo::clientMoveAndDisplay()
\r
42 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
\r
44 //simple dynamics world doesn't handle fixed-time-stepping
\r
45 float ms = getDeltaTimeMicroseconds();
\r
47 ///step the simulation
\r
48 if (m_dynamicsWorld)
\r
50 m_dynamicsWorld->stepSimulation(ms / 1000000.f);
\r
51 //optional but useful: debug drawing
\r
52 m_dynamicsWorld->debugDrawWorld();
\r
65 void RollingFrictionDemo::displayCallback(void) {
\r
67 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
\r
71 //optional but useful: debug drawing to detect problems
\r
72 if (m_dynamicsWorld)
\r
73 m_dynamicsWorld->debugDrawWorld();
\r
83 void RollingFrictionDemo::initPhysics()
\r
88 setCameraDistance(btScalar(SCALING*26.));
\r
90 ///collision configuration contains default setup for memory, collision setup
\r
91 m_collisionConfiguration = new btDefaultCollisionConfiguration();
\r
92 //m_collisionConfiguration->setConvexConvexMultipointIterations();
\r
94 ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
\r
95 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
\r
97 m_broadphase = new btDbvtBroadphase();
\r
99 ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
\r
100 btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
\r
103 m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
\r
104 m_dynamicsWorld->setDebugDrawer(&sDebugDraw);
\r
105 // m_dynamicsWorld->getSolverInfo().m_singleAxisRollingFrictionThreshold = 0.f;//faster but lower quality
\r
106 m_dynamicsWorld->setGravity(btVector3(0,-10,0));
\r
110 ///create a few basic rigid bodies
\r
111 btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(20.),btScalar(50.),btScalar(10.)));
\r
113 // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);
\r
115 m_collisionShapes.push_back(groundShape);
\r
117 btTransform groundTransform;
\r
118 groundTransform.setIdentity();
\r
119 groundTransform.setOrigin(btVector3(0,-50,0));
\r
120 groundTransform.setRotation(btQuaternion(btVector3(0,0,1),SIMD_PI*0.03));
\r
121 //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
\r
124 //rigidbody is dynamic if and only if mass is non zero, otherwise static
\r
125 bool isDynamic = (mass != 0.f);
\r
127 btVector3 localInertia(0,0,0);
\r
129 groundShape->calculateLocalInertia(mass,localInertia);
\r
131 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
\r
132 btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
\r
133 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
\r
134 btRigidBody* body = new btRigidBody(rbInfo);
\r
135 body->setFriction(1);
\r
136 body->setRollingFriction(1);
\r
137 //add the body to the dynamics world
\r
138 m_dynamicsWorld->addRigidBody(body);
\r
143 ///create a few basic rigid bodies
\r
144 btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(100.),btScalar(50.),btScalar(100.)));
\r
146 m_collisionShapes.push_back(groundShape);
\r
148 btTransform groundTransform;
\r
149 groundTransform.setIdentity();
\r
150 groundTransform.setOrigin(btVector3(0,-54,0));
\r
151 //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
\r
154 //rigidbody is dynamic if and only if mass is non zero, otherwise static
\r
155 bool isDynamic = (mass != 0.f);
\r
157 btVector3 localInertia(0,0,0);
\r
159 groundShape->calculateLocalInertia(mass,localInertia);
\r
161 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
\r
162 btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
\r
163 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
\r
164 btRigidBody* body = new btRigidBody(rbInfo);
\r
165 body->setFriction(1);
\r
166 body->setRollingFriction(1);
\r
167 //add the body to the dynamics world
\r
168 m_dynamicsWorld->addRigidBody(body);
\r
172 //create a few dynamic rigidbodies
\r
173 // Re-using the same collision is better for memory usage and performance
\r
174 #define NUM_SHAPES 10
\r
175 btCollisionShape* colShapes[NUM_SHAPES] = {
\r
176 new btSphereShape(btScalar(1.)),
\r
177 new btCapsuleShape(0.5,1),
\r
178 new btCapsuleShapeX(0.5,1),
\r
179 new btCapsuleShapeZ(0.5,1),
\r
180 new btConeShape(0.5,1),
\r
181 new btConeShapeX(0.5,1),
\r
182 new btConeShapeZ(0.5,1),
\r
183 new btCylinderShape(btVector3(0.5,1,0.5)),
\r
184 new btCylinderShapeX(btVector3(1,0.5,0.5)),
\r
185 new btCylinderShapeZ(btVector3(0.5,0.5,1)),
\r
187 for (int i=0;i<NUM_SHAPES;i++)
\r
188 m_collisionShapes.push_back(colShapes[i]);
\r
190 /// Create Dynamic Objects
\r
191 btTransform startTransform;
\r
192 startTransform.setIdentity();
\r
194 btScalar mass(1.f);
\r
196 //rigidbody is dynamic if and only if mass is non zero, otherwise static
\r
198 float start_x = START_POS_X - ARRAY_SIZE_X/2;
\r
199 float start_y = START_POS_Y;
\r
200 float start_z = START_POS_Z - ARRAY_SIZE_Z/2;
\r
203 int shapeIndex = 0;
\r
204 for (int k=0;k<ARRAY_SIZE_Y;k++)
\r
206 for (int i=0;i<ARRAY_SIZE_X;i++)
\r
208 for(int j = 0;j<ARRAY_SIZE_Z;j++)
\r
210 startTransform.setOrigin(SCALING*btVector3(
\r
211 btScalar(2.0*i + start_x),
\r
212 btScalar(20+2.0*k + start_y),
\r
213 btScalar(2.0*j + start_z)));
\r
217 btCollisionShape* colShape = colShapes[shapeIndex%NUM_SHAPES];
\r
218 bool isDynamic = (mass != 0.f);
\r
219 btVector3 localInertia(0,0,0);
\r
222 colShape->calculateLocalInertia(mass,localInertia);
\r
224 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
\r
225 btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
\r
226 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
\r
227 btRigidBody* body = new btRigidBody(rbInfo);
\r
228 body->setFriction(1.f);
\r
229 body->setRollingFriction(.3);
\r
230 body->setAnisotropicFriction(colShape->getAnisotropicRollingFrictionDirection(),btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
\r
233 m_dynamicsWorld->addRigidBody(body);
\r
242 void RollingFrictionDemo::clientResetScene()
\r
249 void RollingFrictionDemo::exitPhysics()
\r
252 //cleanup in the reverse order of creation/initialization
\r
254 //remove the rigidbodies from the dynamics world and delete them
\r
256 for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
\r
258 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
\r
259 btRigidBody* body = btRigidBody::upcast(obj);
\r
260 if (body && body->getMotionState())
\r
262 delete body->getMotionState();
\r
264 m_dynamicsWorld->removeCollisionObject( obj );
\r
268 //delete collision shapes
\r
269 for (int j=0;j<m_collisionShapes.size();j++)
\r
271 btCollisionShape* shape = m_collisionShapes[j];
\r
274 m_collisionShapes.clear();
\r
276 delete m_dynamicsWorld;
\r
280 delete m_broadphase;
\r
282 delete m_dispatcher;
\r
284 delete m_collisionConfiguration;
\r