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.
16 #include "btBulletDynamicsCommon.h"
17 #include "LinearMath/btIDebugDraw.h"
18 #include "GLDebugDrawer.h"
19 #include "MultiMaterialDemo.h"
20 #include "GL_ShapeDrawer.h"
21 #include "GlutStuff.h"
23 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
24 #include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h"
25 #include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h"
26 #include "BulletCollision/CollisionShapes/btMaterial.h"
27 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
29 // Create a custom material, just because we can
30 class CustomMaterial : public btMaterial
36 CustomMaterial(int a, int b) {foo1 = a; foo2 = b;}
39 // Storage for the vertex data
40 static btVector3* gVertices = 0;
41 // Storage for the face data
42 static int* gIndices = 0;
43 // Storage for the material data
44 static CustomMaterial* gMaterials = 0;
45 // Storage for the face -> material index data
46 static int* gFaceMaterialIndices = 0;
48 static btBvhTriangleMeshShape* trimeshShape =0;
49 static btRigidBody* staticBody = 0;
50 static float waveheight = 0.f;
52 const float TRIANGLE_SIZE=1.f;
55 ///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
56 inline btScalar calculateCombinedFriction(float friction0,float friction1)
58 btScalar friction = friction0 * friction1;
60 const btScalar MAX_FRICTION = 10.f;
61 if (friction < -MAX_FRICTION)
62 friction = -MAX_FRICTION;
63 if (friction > MAX_FRICTION)
64 friction = MAX_FRICTION;
69 inline btScalar calculateCombinedRestitution(float restitution0,float restitution1)
71 return restitution0 * restitution1;
76 static bool CustomMaterialCombinerCallback(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1)
79 // Apply material properties
80 if (colObj0Wrap->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE)
82 const btCollisionShape* parent0 = colObj0Wrap->getCollisionObject()->getCollisionShape();
83 if(parent0 != 0 && parent0->getShapeType() == MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE)
85 btMultimaterialTriangleMeshShape* shape = (btMultimaterialTriangleMeshShape*)parent0;
86 const btMaterial * props = shape->getMaterialProperties(partId0, index0);
87 cp.m_combinedFriction = calculateCombinedFriction(props->m_friction, colObj1Wrap->getCollisionObject()->getFriction());
88 cp.m_combinedRestitution = props->m_restitution * colObj1Wrap->getCollisionObject()->getRestitution();
91 else if (colObj1Wrap->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE)
93 const btCollisionShape* parent1 = colObj1Wrap->getCollisionObject()->getCollisionShape();
94 if(parent1 != 0 && parent1->getShapeType() == MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE)
96 btMultimaterialTriangleMeshShape* shape = (btMultimaterialTriangleMeshShape*)parent1;
97 const btMaterial * props = shape->getMaterialProperties(partId1, index1);
98 cp.m_combinedFriction = calculateCombinedFriction(props->m_friction, colObj0Wrap->getCollisionObject()->getFriction());
99 cp.m_combinedRestitution = props->m_restitution * colObj0Wrap->getCollisionObject()->getRestitution();
103 //this return value is currently ignored, but to be on the safe side: return false if you don't calculate friction
107 extern ContactAddedCallback gContactAddedCallback;
109 const int NUM_VERTS_X = 20;
110 const int NUM_VERTS_Y = 50;
111 const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y;
113 void MultiMaterialDemo::setVertexPositions(float waveheight, float offset)
118 for ( i=0;i<NUM_VERTS_X;i++)
120 for (j=0;j<NUM_VERTS_Y;j++)
122 gVertices[i+j*NUM_VERTS_X].setValue((i-NUM_VERTS_X*0.5f)*TRIANGLE_SIZE,
124 waveheight*sinf((float)i+offset)*cosf((float)j+offset),
125 (j-NUM_VERTS_Y*0.5f)*TRIANGLE_SIZE);
130 void MultiMaterialDemo::keyboardCallback(unsigned char key, int x, int y)
134 m_animatedMesh = !m_animatedMesh;
137 staticBody->setCollisionFlags( staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
138 staticBody->setActivationState(DISABLE_DEACTIVATION);
141 staticBody->setCollisionFlags( staticBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT);
142 staticBody->forceActivationState(ACTIVE_TAG);
146 DemoApplication::keyboardCallback(key,x,y);
150 void MultiMaterialDemo::initPhysics()
154 gContactAddedCallback = CustomMaterialCombinerCallback;
156 // The number of triangles
157 const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1);
158 // The number of materials
159 const int totalMaterials = 2;
161 int vertStride = sizeof(btVector3);
162 int indexStride = 3*sizeof(int);
163 // int materialStride = sizeof(CustomMaterial);
164 // int triangleMaterialStride = sizeof(int);
166 gVertices = new btVector3[totalVerts];
167 gIndices = new int[totalTriangles*3];
168 gMaterials = new CustomMaterial[totalMaterials];
169 gFaceMaterialIndices = new int[totalTriangles];
171 // Explicitly set up the materials. It's a small array so let's do it bit by bit.
172 gMaterials[0].m_friction = 0;
173 gMaterials[0].m_restitution = 0.9;
174 gMaterials[0].foo1 = 5;
175 gMaterials[0].foo2 = 7;
176 gMaterials[1].m_friction = 0.9;
177 gMaterials[1].m_restitution = 0.1;
178 gMaterials[1].foo1 = 53;
179 gMaterials[1].foo2 = 15;
182 // Set up the vertex data
183 setVertexPositions(waveheight,0.f);
185 // Set up the face data
186 for ( i=0;i<NUM_VERTS_X-1;i++)
188 for (int j=0;j<NUM_VERTS_Y-1;j++)
190 gIndices[index++] = j*NUM_VERTS_X+i;
191 gIndices[index++] = j*NUM_VERTS_X+i+1;
192 gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
194 gIndices[index++] = j*NUM_VERTS_X+i;
195 gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
196 gIndices[index++] = (j+1)*NUM_VERTS_X+i;
200 // Set up the face->material index data
201 for(int a = 0; a < totalTriangles; a++)
203 // This will give the first half of the faces low friction and high restitution
204 // and the second half of the faces high friction and low restitution
205 if(a > totalTriangles*0.5f)
206 gFaceMaterialIndices[a] = 0;
208 gFaceMaterialIndices[a] = 1;
211 // Create the array structure
212 m_indexVertexArrays = new btTriangleIndexVertexMaterialArray(
213 totalTriangles, gIndices, indexStride,
214 totalVerts,(btScalar*) &gVertices[0].x(),vertStride,
215 totalMaterials, (unsigned char *)gMaterials, sizeof(CustomMaterial),
216 gFaceMaterialIndices, sizeof(int));
218 bool useQuantizedAabbCompression = true;
219 // Create the multimaterial mesh shape
220 trimeshShape = new btMultimaterialTriangleMeshShape((btTriangleIndexVertexMaterialArray*)m_indexVertexArrays,useQuantizedAabbCompression);
221 m_collisionShapes.push_back(trimeshShape);
223 btCollisionShape* groundShape = trimeshShape;
225 m_collisionConfiguration = new btDefaultCollisionConfiguration();
227 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
229 btVector3 worldMin(-1000,-1000,-1000);
230 btVector3 worldMax(1000,1000,1000);
231 m_broadphase = new btAxisSweep3(worldMin,worldMax);
232 m_solver = new btSequentialImpulseConstraintSolver();
233 m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
236 btTransform startTransform;
237 startTransform.setIdentity();
238 startTransform.setOrigin(btVector3(0,-2,0));
240 btCollisionShape* colShape = new btBoxShape(btVector3(0.5f,0.5f,0.5f));
241 m_collisionShapes.push_back(colShape);
244 for (int i=0;i<1;i++)
246 startTransform.setOrigin(btVector3(10,10,-20));
247 btRigidBody* body = localCreateRigidBody(1, startTransform,colShape);
248 body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
249 body->setFriction(0.9f);
250 body->setGravity(btVector3(0,-20.f,0));
251 body->applyCentralImpulse(btVector3(-7.7f,0,0));
255 startTransform.setIdentity();
256 staticBody = localCreateRigidBody(mass, startTransform,groundShape);
258 staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT);
260 //enable custom material callback
261 staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
264 void MultiMaterialDemo::clientMoveAndDisplay()
266 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
268 float dt = getDeltaTimeMicroseconds() * 0.000001f;
272 static float offset=0.f;
275 // setVertexPositions(waveheight,offset);
279 btVector3 aabbMin(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
280 btVector3 aabbMax(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
282 for ( i=NUM_VERTS_X/2-3;i<NUM_VERTS_X/2+2;i++)
284 for (j=NUM_VERTS_X/2-3;j<NUM_VERTS_Y/2+2;j++)
287 aabbMax.setMax(gVertices[i+j*NUM_VERTS_X]);
288 aabbMin.setMin(gVertices[i+j*NUM_VERTS_X]);
290 gVertices[i+j*NUM_VERTS_X].setValue((i-NUM_VERTS_X*0.5f)*TRIANGLE_SIZE,
292 (j-NUM_VERTS_Y*0.5f)*TRIANGLE_SIZE);
294 aabbMin.setMin(gVertices[i+j*NUM_VERTS_X]);
295 aabbMax.setMax(gVertices[i+j*NUM_VERTS_X]);
300 trimeshShape->partialRefitTree(aabbMin,aabbMax);
302 //clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation.
303 m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(staticBody->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher());
306 m_dynamicsWorld->stepSimulation(dt);
308 //optional but useful: debug drawing
309 m_dynamicsWorld->debugDrawWorld();
321 void MultiMaterialDemo::displayCallback(void) {
323 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
333 void MultiMaterialDemo::exitPhysics()
338 //cleanup in the reverse order of creation/initialization
340 //remove the rigidbodies from the dynamics world and delete them
342 for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
344 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
345 btRigidBody* body = btRigidBody::upcast(obj);
346 if (body && body->getMotionState())
348 delete body->getMotionState();
350 m_dynamicsWorld->removeCollisionObject( obj );
354 //delete collision shapes
355 for (int j=0;j<m_collisionShapes.size();j++)
357 btCollisionShape* shape = m_collisionShapes[j];
361 //delete dynamics world
362 delete m_dynamicsWorld;
364 if (m_indexVertexArrays)
365 delete m_indexVertexArrays;
376 delete m_collisionConfiguration;