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 "BulletCollision/CollisionShapes/btBoxShape.h"
19 #include "GLDebugDrawer.h"
20 #include "ConcaveConvexcastDemo.h"
21 #include "GL_ShapeDrawer.h"
22 #include "GlutStuff.h"
24 #define NUM_DYNAMIC_BOXES_X 30
25 #define NUM_DYNAMIC_BOXES_Y 30
27 static btVector3* gVertices=0;
28 static int* gIndices=0;
29 static btBvhTriangleMeshShape* trimeshShape =0;
30 static btRigidBody* staticBody = 0;
31 static float waveheight = 5.f;
33 const float TRIANGLE_SIZE=8.f;
36 /* Scrolls back and forth over terrain */
37 #define NUMRAYS_IN_BAR 100
38 class btConvexcastBatch
41 btVector3 source[NUMRAYS_IN_BAR];
42 btVector3 dest[NUMRAYS_IN_BAR];
43 btVector3 direction[NUMRAYS_IN_BAR];
44 btVector3 hit_com[NUMRAYS_IN_BAR];
45 btVector3 hit_surface[NUMRAYS_IN_BAR];
46 btScalar hit_fraction[NUMRAYS_IN_BAR];
47 btVector3 normal[NUMRAYS_IN_BAR];
67 btVector3 boxShapeHalfExtents;
70 btConvexcastBatch () : boxShape(btVector3(0.0, 0.0, 0.0))
79 btConvexcastBatch (bool unused, btScalar ray_length, btScalar min_z, btScalar max_z, btScalar min_y , btScalar max_y ) : boxShape(btVector3(0.0, 0.0, 0.0))
81 boxShapeHalfExtents = btVector3(1.0, 1.0, 1.0);
82 boxShape = btBoxShape(boxShapeHalfExtents);
95 // btScalar dalpha = 2*SIMD_2_PI/NUMRAYS_IN_BAR;
96 for (int i = 0; i < NUMRAYS_IN_BAR; i++)
98 btScalar z = (max_z-min_z)/NUMRAYS_IN_BAR * i + min_z;
99 source[i] = btVector3(min_x, max_y, z);
100 dest[i] = btVector3(min_x + ray_length, min_y, z);
101 normal[i] = btVector3(1.0, 0.0, 0.0);
105 btConvexcastBatch (btScalar ray_length, btScalar z, btScalar min_y = -1000, btScalar max_y = 10) : boxShape(btVector3(0.0, 0.0, 0.0))
107 boxShapeHalfExtents = btVector3(1.0, 1.0, 1.0);
108 boxShape = btBoxShape(boxShapeHalfExtents);
121 btScalar dalpha = btScalar(2)*SIMD_2_PI/btScalar(NUMRAYS_IN_BAR);
122 for (int i = 0; i < NUMRAYS_IN_BAR; i++)
124 btScalar alpha = dalpha * btScalar(i);
125 // rotate around by alpha degrees y
126 btTransform tr(btQuaternion(btVector3(0.0, 1.0, 0.0), alpha));
127 direction[i] = btVector3(1.0, 0.0, 0.0);
128 direction[i] = tr * direction[i];
129 source[i] = btVector3(min_x, max_y, z);
130 dest[i] = source[i] + direction[i] * ray_length;
132 normal[i] = btVector3(1.0, 0.0, 0.0);
136 void move (btScalar dt)
140 for (int i = 0; i < NUMRAYS_IN_BAR; i++)
142 source[i][0] += dx * dt * sign;
143 dest[i][0] += dx * dt * sign;
145 if (source[0][0] < min_x)
147 else if (source[0][0] > max_x)
151 void cast (btCollisionWorld* cw)
154 frame_timer.reset ();
155 #endif //USE_BT_CLOCK
156 for (int i = 0; i < NUMRAYS_IN_BAR; i++)
158 btCollisionWorld::ClosestConvexResultCallback cb(source[i], dest[i]);
161 qFrom.setRotation (btVector3(1.0, 0.0, 0.0), 0.0);
162 qTo.setRotation (btVector3(1.0, 0.0, 0.0), 0.7);
163 btTransform from(qFrom, source[i]);
164 btTransform to(qTo, dest[i]);
165 cw->convexSweepTest (&boxShape, from, to, cb);
168 hit_surface[i] = cb.m_hitPointWorld;
169 hit_com[i].setInterpolate3(source[i], dest[i], cb.m_closestHitFraction);
170 hit_fraction[i] = cb.m_closestHitFraction;
171 normal[i] = cb.m_hitNormalWorld;
172 normal[i].normalize ();
174 hit_com[i] = dest[i];
175 hit_surface[i] = dest[i];
176 hit_fraction[i] = 1.0f;
177 normal[i] = btVector3(1.0, 0.0, 0.0);
182 ms += frame_timer.getTimeMilliseconds ();
183 #endif //USE_BT_CLOCK
185 if (frame_counter > 50)
187 min_ms = ms < min_ms ? ms : min_ms;
188 max_ms = ms > max_ms ? ms : max_ms;
191 btScalar mean_ms = (btScalar)sum_ms/(btScalar)sum_ms_samples;
192 printf("%d rays in %d ms %d %d %f\n", NUMRAYS_IN_BAR * frame_counter, ms, min_ms, max_ms, mean_ms);
199 void drawCube (const btTransform& T)
201 ATTRIBUTE_ALIGNED16(btScalar) m[16];
202 T.getOpenGLMatrix (&m[0]);
204 #ifdef BT_USE_DOUBLE_PRECISION
205 glMultMatrixd (&m[0]);
206 glScaled (2.0 * boxShapeHalfExtents[0], 2.0 * boxShapeHalfExtents[1], 2.0 * boxShapeHalfExtents[2]);
208 glMultMatrixf (&m[0]);
209 glScalef (2.0 * boxShapeHalfExtents[0], 2.0 * boxShapeHalfExtents[1], 2.0 * boxShapeHalfExtents[2]);
210 #endif //BT_USE_DOUBLE_PRECISION
217 glDisable (GL_LIGHTING);
218 glColor3f (0.0, 1.0, 0.0);
221 for (i = 0; i < NUMRAYS_IN_BAR; i++)
223 glVertex3f (source[i][0], source[i][1], source[i][2]);
224 glVertex3f (hit_com[i][0], hit_com[i][1], hit_com[i][2]);
226 glColor3f (1.0, 1.0, 1.0);
228 btScalar normal_scale = 10.0; // easier to see if this is big
229 for (i = 0; i < NUMRAYS_IN_BAR; i++)
231 glVertex3f (hit_surface[i][0], hit_surface[i][1], hit_surface[i][2]);
232 glVertex3f (hit_surface[i][0] + normal_scale * normal[i][0], hit_surface[i][1] + normal_scale * normal[i][1], hit_surface[i][2] + normal_scale * normal[i][2]);
235 glColor3f (0.0, 1.0, 1.0);
238 qFrom.setRotation (btVector3(1.0, 0.0, 0.0), 0.0);
239 qTo.setRotation (btVector3(1.0, 0.0, 0.0), 0.7);
240 for ( i = 0; i < NUMRAYS_IN_BAR; i++)
242 btTransform from(qFrom, source[i]);
243 btTransform to(qTo, dest[i]);
244 btVector3 linVel, angVel;
245 btTransformUtil::calculateVelocity (from, to, 1.0, linVel, angVel);
247 btTransformUtil::integrateTransform (from, linVel, angVel, hit_fraction[i], T);
250 glEnable (GL_LIGHTING);
255 static btConvexcastBatch convexcastBatch;
261 const int NUM_VERTS_X = 30;
262 const int NUM_VERTS_Y = 30;
263 const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y;
265 void ConcaveConvexcastDemo::setVertexPositions(float waveheight, float offset)
270 for ( i=0;i<NUM_VERTS_X;i++)
272 for (j=0;j<NUM_VERTS_Y;j++)
274 gVertices[i+j*NUM_VERTS_X].setValue((i-NUM_VERTS_X*0.5f)*TRIANGLE_SIZE,
276 waveheight*sinf((float)i+offset)*cosf((float)j+offset),
277 (j-NUM_VERTS_Y*0.5f)*TRIANGLE_SIZE);
282 void ConcaveConvexcastDemo::keyboardCallback(unsigned char key, int x, int y)
286 m_animatedMesh = !m_animatedMesh;
289 staticBody->setCollisionFlags( staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
290 staticBody->setActivationState(DISABLE_DEACTIVATION);
293 staticBody->setCollisionFlags( staticBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT);
294 staticBody->forceActivationState(ACTIVE_TAG);
298 DemoApplication::keyboardCallback(key,x,y);
302 void ConcaveConvexcastDemo::initPhysics()
306 setCameraDistance(100.f);
309 int vertStride = sizeof(btVector3);
310 int indexStride = 3*sizeof(int);
313 const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1);
315 gVertices = new btVector3[totalVerts];
316 gIndices = new int[totalTriangles*3];
321 setVertexPositions(waveheight,0.f);
324 for ( i=0;i<NUM_VERTS_X-1;i++)
326 for (int j=0;j<NUM_VERTS_Y-1;j++)
328 gIndices[index++] = j*NUM_VERTS_X+i;
329 gIndices[index++] = j*NUM_VERTS_X+i+1;
330 gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
332 gIndices[index++] = j*NUM_VERTS_X+i;
333 gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
334 gIndices[index++] = (j+1)*NUM_VERTS_X+i;
338 m_indexVertexArrays = new btTriangleIndexVertexArray(totalTriangles,
341 totalVerts,(btScalar*) &gVertices[0].x(),vertStride);
343 bool useQuantizedAabbCompression = true;
345 trimeshShape = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression);
347 m_collisionShapes.push_back(trimeshShape);
349 btCollisionShape* groundShape = trimeshShape;
352 m_collisionConfiguration = new btDefaultCollisionConfiguration();
354 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
356 btVector3 worldMin(-1000,-1000,-1000);
357 btVector3 worldMax(1000,1000,1000);
358 m_broadphase = new btAxisSweep3(worldMin,worldMax);
359 m_solver = new btSequentialImpulseConstraintSolver();
360 m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
363 btTransform startTransform;
364 startTransform.setIdentity();
365 startTransform.setOrigin(btVector3(0,-2,0));
367 btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
368 m_collisionShapes.push_back(colShape);
371 for (int j=0;j<NUM_DYNAMIC_BOXES_X;j++)
372 for (int i=0;i<NUM_DYNAMIC_BOXES_Y;i++)
374 //btCollisionShape* colShape = new btCapsuleShape(0.5,2.0);//boxShape = new btSphereShape(1.f);
375 startTransform.setOrigin(btVector3(5*(i-NUM_DYNAMIC_BOXES_X/2),10,5*(j-NUM_DYNAMIC_BOXES_Y/2)));
376 localCreateRigidBody(1, startTransform,colShape);
380 startTransform.setIdentity();
381 //startTransform = btTransform(btQuaternion (btVector3(1,1,1), 1.5));
382 staticBody = localCreateRigidBody(mass, startTransform,groundShape);
384 staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT);
386 //enable custom material callback
387 staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
389 convexcastBatch = btConvexcastBatch (40.0, 0.0, -10.0,80.0);
390 //convexcastBatch = btConvexcastBatch (true, 40.0, -50.0, 50.0);
393 void ConcaveConvexcastDemo::clientMoveAndDisplay()
395 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
397 float dt = getDeltaTimeMicroseconds() * 0.000001f;
401 static float offset=0.f;
408 btVector3 aabbMin(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
409 btVector3 aabbMax(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
411 for ( i=NUM_VERTS_X/2-3;i<NUM_VERTS_X/2+2;i++)
413 for (j=NUM_VERTS_X/2-3;j<NUM_VERTS_Y/2+2;j++)
416 aabbMax.setMax(gVertices[i+j*NUM_VERTS_X]);
417 aabbMin.setMin(gVertices[i+j*NUM_VERTS_X]);
419 gVertices[i+j*NUM_VERTS_X].setValue((i-NUM_VERTS_X*0.5f)*TRIANGLE_SIZE,
421 waveheight*sinf((float)i+offset)*cosf((float)j+offset),
422 (j-NUM_VERTS_Y*0.5f)*TRIANGLE_SIZE);
424 aabbMin.setMin(gVertices[i+j*NUM_VERTS_X]);
425 aabbMax.setMax(gVertices[i+j*NUM_VERTS_X]);
430 trimeshShape->partialRefitTree(aabbMin,aabbMax);
433 //clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation.
434 m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(staticBody->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher());
437 m_dynamicsWorld->stepSimulation(dt);
439 //optional but useful: debug drawing
440 m_dynamicsWorld->debugDrawWorld();
442 convexcastBatch.move (dt);
443 convexcastBatch.cast (m_dynamicsWorld);
445 convexcastBatch.draw ();
454 void ConcaveConvexcastDemo::displayCallback(void) {
456 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
459 convexcastBatch.draw ();
466 void ConcaveConvexcastDemo::exitPhysics()
471 //cleanup in the reverse order of creation/initialization
473 //remove the rigidbodies from the dynamics world and delete them
475 for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
477 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
478 btRigidBody* body = btRigidBody::upcast(obj);
479 if (body && body->getMotionState())
481 delete body->getMotionState();
483 m_dynamicsWorld->removeCollisionObject( obj );
487 //delete collision shapes
488 for (int j=0;j<m_collisionShapes.size();j++)
490 btCollisionShape* shape = m_collisionShapes[j];
494 //delete dynamics world
495 delete m_dynamicsWorld;
497 if (m_indexVertexArrays)
498 delete m_indexVertexArrays;
509 delete m_collisionConfiguration;