Initialize libbullet git in 2.0_beta.
[platform/upstream/libbullet.git] / Demos / InternalEdgeDemo / InternalEdgeDemo.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 #include "GLDebugFont.h"
16
17
18 //#define SHIFT_INDICES 1
19 #define SWAP_WINDING 1
20 //#define ROTATE_GROUND 1
21 bool enable=true;
22
23 #if defined (SHIFT_INDICES) && !defined (SWAP_WINDING)
24 //#define TEST_INCONSISTENT_WINDING
25 #endif
26
27
28
29 #include "btBulletDynamicsCommon.h"
30 #include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.h"
31 #include "Taru.mdl"
32
33 #include "LinearMath/btIDebugDraw.h"
34 #include "GLDebugDrawer.h"
35 #include "InternalEdgeDemo.h"
36 #include "GL_ShapeDrawer.h"
37 #include "GlutStuff.h"
38 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
39 #include "GLDebugDrawer.h"
40 GLDebugDrawer   gDebugDrawer;
41
42 static btVector3*       gVertices=0;
43 static int*     gIndices=0;
44 static btBvhTriangleMeshShape* trimeshShape =0;
45 static btRigidBody* staticBody = 0;
46 static float waveheight = 0.f;
47
48 const float TRIANGLE_SIZE=20.f;
49
50
51
52 ///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
53 inline btScalar calculateCombinedFriction(float friction0,float friction1)
54 {
55         return 0.f;
56         btScalar friction = friction0 * friction1;
57
58         const btScalar MAX_FRICTION  = 10.f;
59         if (friction < -MAX_FRICTION)
60                 friction = -MAX_FRICTION;
61         if (friction > MAX_FRICTION)
62                 friction = MAX_FRICTION;
63         return friction;
64
65 }
66
67 inline btScalar calculateCombinedRestitution(float restitution0,float restitution1)
68 {
69         return restitution0 * restitution1;
70 }
71
72
73 ///////////////////////////////////////////////////////////////
74
75
76 static bool CustomMaterialCombinerCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1)
77 {
78
79         if (enable)
80         {
81                 btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1);
82                 //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_BACKFACE_MODE);
83                 //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_DOUBLE_SIDED+BT_TRIANGLE_CONCAVE_DOUBLE_SIDED);
84         }
85
86         float friction0 = colObj0->getFriction();
87         float friction1 = colObj1->getFriction();
88         float restitution0 = colObj0->getRestitution();
89         float restitution1 = colObj1->getRestitution();
90
91         if (colObj0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)
92         {
93                 friction0 = 1.0;//partId0,index0
94                 restitution0 = 0.f;
95         }
96         if (colObj1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)
97         {
98                 if (index1&1)
99                 {
100                         friction1 = 1.0f;//partId1,index1
101                 } else
102                 {
103                         friction1 = 0.f;
104                 }
105                 restitution1 = 0.f;
106         }
107
108         cp.m_combinedFriction = calculateCombinedFriction(friction0,friction1);
109         cp.m_combinedRestitution = calculateCombinedRestitution(restitution0,restitution1);
110
111         //this return value is currently ignored, but to be on the safe side: return false if you don't calculate friction
112         return true;
113 }
114
115 extern ContactAddedCallback             gContactAddedCallback;
116
117         const int NUM_VERTS_X = 2;
118         const int NUM_VERTS_Y = 2;
119         const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y;
120
121 void    InternalEdgeDemo::setVertexPositions(float waveheight, float offset)
122 {
123         int i;
124         int j;
125
126         for ( i=0;i<NUM_VERTS_X;i++)
127         {
128                 for (j=0;j<NUM_VERTS_Y;j++)
129                 {
130                         gVertices[i+j*NUM_VERTS_X].setValue(
131                                 (i-NUM_VERTS_X*0.5f)*TRIANGLE_SIZE,
132                                 //0.f,
133                                 waveheight*sinf((float)i+offset)*cosf((float)j+offset),
134                                 (j-NUM_VERTS_Y*0.5f)*TRIANGLE_SIZE);
135                 }
136         }
137 }
138
139 void InternalEdgeDemo::keyboardCallback(unsigned char key, int x, int y)
140 {
141         if (key=='n')
142         {
143                 enable = !enable;
144         }
145
146         if (key == 'g')
147         {
148                 m_animatedMesh = !m_animatedMesh;
149                 if (m_animatedMesh)
150                 {
151                         staticBody->setCollisionFlags( staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
152                         staticBody->setActivationState(DISABLE_DEACTIVATION);
153                 } else
154                 {
155                         staticBody->setCollisionFlags( staticBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT);
156                         staticBody->forceActivationState(ACTIVE_TAG);
157                 }
158         }
159
160         DemoApplication::keyboardCallback(key,x,y);
161
162 }
163
164
165
166 void    InternalEdgeDemo::initPhysics()
167 {
168         
169         setTexturing(true);
170         setShadows(false);//true);
171
172         #define TRISIZE 10.f
173
174      gContactAddedCallback = CustomMaterialCombinerCallback;
175
176 #define USE_TRIMESH_SHAPE 1
177 #ifdef USE_TRIMESH_SHAPE
178
179         int vertStride = sizeof(btVector3);
180         int indexStride = 3*sizeof(int);
181
182         
183         const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1);
184
185         gVertices = new btVector3[totalVerts];
186         gIndices = new int[totalTriangles*3];
187
188         int i;
189
190
191         setVertexPositions(waveheight,0.f);
192         
193         
194         //gVertices[1].setY(21.1);
195         //gVertices[1].setY(121.1);
196         gVertices[1].setY(.1f);
197
198 #ifdef ROTATE_GROUND
199         //gVertices[1].setY(-1.1);
200 #else
201         //gVertices[1].setY(0.1);
202         //gVertices[1].setY(-0.1);
203         //gVertices[1].setY(-20.1);
204         //gVertices[1].setY(-20);
205 #endif
206         
207         int index=0;
208         for ( i=0;i<NUM_VERTS_X-1;i++)
209         {
210                 for (int j=0;j<NUM_VERTS_Y-1;j++)
211                 {
212
213 #ifdef SWAP_WINDING
214 #ifdef SHIFT_INDICES
215                         gIndices[index++] = j*NUM_VERTS_X+i;
216                         gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
217                         gIndices[index++] = j*NUM_VERTS_X+i+1;
218                         
219                         gIndices[index++] = j*NUM_VERTS_X+i;
220                         gIndices[index++] = (j+1)*NUM_VERTS_X+i;
221                         gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
222                         
223 #else
224                         gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
225                         gIndices[index++] = j*NUM_VERTS_X+i+1;
226                         gIndices[index++] = j*NUM_VERTS_X+i;
227
228                         gIndices[index++] = (j+1)*NUM_VERTS_X+i;
229                         gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
230                         gIndices[index++] = j*NUM_VERTS_X+i;
231 #endif //SHIFT_INDICES
232 #else //SWAP_WINDING
233
234 #ifdef SHIFT_INDICES
235                         gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
236                         gIndices[index++] = j*NUM_VERTS_X+i;
237                         gIndices[index++] = j*NUM_VERTS_X+i+1;
238
239 #ifdef TEST_INCONSISTENT_WINDING
240                         gIndices[index++] = j*NUM_VERTS_X+i;
241                         gIndices[index++] = (j+1)*NUM_VERTS_X+i;
242                         gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
243
244 #else //TEST_INCONSISTENT_WINDING
245                         gIndices[index++] = (j+1)*NUM_VERTS_X+i;
246                         gIndices[index++] = j*NUM_VERTS_X+i;
247                         gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
248 #endif //TEST_INCONSISTENT_WINDING
249                         
250                         
251                         
252 #else //SHIFT_INDICES
253                         gIndices[index++] = j*NUM_VERTS_X+i;
254                         gIndices[index++] = j*NUM_VERTS_X+i+1;
255                         gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
256
257                         gIndices[index++] = j*NUM_VERTS_X+i;
258                         gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
259                         gIndices[index++] = (j+1)*NUM_VERTS_X+i;
260 #endif //SHIFT_INDICES
261
262 #endif //SWAP_WINDING
263
264                         
265                 }
266         }
267
268         m_indexVertexArrays = new btTriangleIndexVertexArray(totalTriangles,
269                 gIndices,
270                 indexStride,
271                 totalVerts,(btScalar*) &gVertices[0].x(),vertStride);
272
273         
274         bool useQuantizedAabbCompression = true;
275
276 //comment out the next line to read the BVH from disk (first run the demo once to create the BVH)
277 #define SERIALIZE_TO_DISK 1
278 #ifdef SERIALIZE_TO_DISK
279         btVector3 aabbMin(-1000,-1000,-1000),aabbMax(1000,1000,1000);
280         
281         trimeshShape  = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,aabbMin,aabbMax);
282         m_collisionShapes.push_back(trimeshShape);
283         
284         
285         ///we can serialize the BVH data 
286         void* buffer = 0;
287         int numBytes = trimeshShape->getOptimizedBvh()->calculateSerializeBufferSize();
288         buffer = btAlignedAlloc(numBytes,16);
289         bool swapEndian = false;
290         trimeshShape->getOptimizedBvh()->serialize(buffer,numBytes,swapEndian);
291         FILE* file = fopen("bvh.bin","wb");
292         fwrite(buffer,1,numBytes,file);
293         fclose(file);
294         btAlignedFree(buffer);
295         
296
297
298 #else
299
300         trimeshShape  = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,false);
301
302         char* fileName = "bvh.bin";
303
304         FILE* file = fopen(fileName,"rb");
305         int size=0;
306         btOptimizedBvh* bvh = 0;
307
308         if (fseek(file, 0, SEEK_END) || (size = ftell(file)) == EOF || fseek(file, 0, SEEK_SET)) {        /* File operations denied? ok, just close and return failure */
309                 printf("Error: cannot get filesize from %s\n", fileName);
310                 exit(0);
311         } else
312         {
313
314                 fseek(file, 0, SEEK_SET);
315
316                 int buffersize = size+btOptimizedBvh::getAlignmentSerializationPadding();
317
318                 void* buffer = btAlignedAlloc(buffersize,16);
319                 int read = fread(buffer,1,size,file);
320                 fclose(file);
321                 bool swapEndian = false;
322                 bvh = btOptimizedBvh::deSerializeInPlace(buffer,buffersize,swapEndian);
323         }
324
325         trimeshShape->setOptimizedBvh(bvh);
326
327 #endif
328
329         btCollisionShape* groundShape = trimeshShape;
330
331         btTriangleInfoMap* triangleInfoMap = new btTriangleInfoMap();
332         
333
334         btGenerateInternalEdgeInfo(trimeshShape,triangleInfoMap);
335         
336
337
338 #else
339         btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50));
340
341         m_collisionShapes.push_back(groundShape);
342
343 #endif //USE_TRIMESH_SHAPE
344
345         m_collisionConfiguration = new btDefaultCollisionConfiguration();
346         
347
348         m_dispatcher = new      btCollisionDispatcher(m_collisionConfiguration);
349
350
351         
352         m_broadphase = new btDbvtBroadphase();
353         m_solver = new btSequentialImpulseConstraintSolver();
354         m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
355 /*
356 m_dynamicsWorld->getSolverInfo().m_splitImpulse = true;
357         m_dynamicsWorld->getSolverInfo().m_splitImpulsePenetrationThreshold = 1e30f;
358         m_dynamicsWorld->getSolverInfo().m_maxErrorReduction = 1e30f;
359         m_dynamicsWorld->getSolverInfo().m_erp  =1.f;
360         m_dynamicsWorld->getSolverInfo().m_erp2 = 1.f;
361 */
362
363         m_dynamicsWorld->setGravity(btVector3(0,-10,0));
364
365         
366         float mass = 0.f;
367         btTransform     startTransform;
368         startTransform.setIdentity();
369         startTransform.setOrigin(btVector3(0,-2,0));
370
371
372         btConvexHullShape* colShape = new btConvexHullShape();
373         for (int i=0;i<TaruVtxCount;i++)
374         {
375                 btVector3 vtx(TaruVtx[i*3],TaruVtx[i*3+1],TaruVtx[i*3+2]);
376                 colShape->addPoint(vtx);
377         }
378         //this will enable polyhedral contact clipping, better quality, slightly slower
379         colShape->initializePolyhedralFeatures();
380
381         //the polyhedral contact clipping can use either GJK or SAT test to find the separating axis
382         m_dynamicsWorld->getDispatchInfo().m_enableSatConvex=false;
383
384         m_collisionShapes.push_back(colShape);
385
386         {
387                 for (int i=0;i<1;i++)
388                 {
389                         startTransform.setOrigin(btVector3(-10.f+i*3.f,2.2f+btScalar(i)*0.1f,-1.3f));
390                         btRigidBody* body = localCreateRigidBody(10, startTransform,colShape);
391                         body->setActivationState(DISABLE_DEACTIVATION);
392                         body->setLinearVelocity(btVector3(0,0,-1));
393                         //body->setContactProcessingThreshold(0.f);
394                 }
395         }
396         {
397                 btBoxShape* colShape = new btBoxShape(btVector3(1,1,1));
398                 colShape->initializePolyhedralFeatures();
399                 m_collisionShapes.push_back(colShape);
400                 startTransform.setOrigin(btVector3(-16.f+i*3.f,1.f+btScalar(i)*0.1f,-1.3f));
401                 btRigidBody* body = localCreateRigidBody(10, startTransform,colShape);
402                 body->setActivationState(DISABLE_DEACTIVATION);
403                 body->setLinearVelocity(btVector3(0,0,-1));
404         }
405
406         startTransform.setIdentity();
407 #ifdef ROTATE_GROUND
408         btQuaternion orn(btVector3(0,0,1),SIMD_PI);
409         startTransform.setOrigin(btVector3(-20,0,0));
410         startTransform.setRotation(orn);
411 #endif //ROTATE_GROUND
412
413         staticBody = localCreateRigidBody(mass, startTransform,groundShape);
414         //staticBody->setContactProcessingThreshold(-0.031f);
415         staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);//STATIC_OBJECT);
416
417         //enable custom material callback
418         staticBody->setCollisionFlags(staticBody->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
419
420         getDynamicsWorld()->setDebugDrawer(&gDebugDrawer);
421         setDebugMode(btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_NoHelpText+btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints);
422
423
424 #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
425         btSetDebugDrawer(&gDebugDrawer);
426 #endif //BT_INTERNAL_EDGE_DEBUG_DRAW
427
428         
429 }
430
431
432 void    InternalEdgeDemo::clientResetScene()
433 {
434         DemoApplication::clientResetScene();
435         for (int i=0;i<m_dynamicsWorld->getNumCollisionObjects();i++)
436         {
437                 btCollisionObject* colobj = m_dynamicsWorld->getCollisionObjectArray()[i];
438                 btRigidBody* body = btRigidBody::upcast(colobj);
439                 if (body && body->getInvMass() != 0.f)
440                 {
441
442                         body->setLinearVelocity(btVector3(0,0,-1));
443                 }
444
445         }
446 }
447
448 void InternalEdgeDemo::clientMoveAndDisplay()
449 {
450          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
451
452         float dt = getDeltaTimeMicroseconds() * 0.000001f;
453
454         if (m_animatedMesh)
455         {
456                 static float offset=0.f;
457                 offset+=0.01f;
458
459         //      setVertexPositions(waveheight,offset);
460 #if 0 ///not currently supported, we need to update the btInternalTriangleInfoMap
461                 int i;
462                 int j;
463                 btVector3 aabbMin(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
464                 btVector3 aabbMax(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
465
466                 for ( i=NUM_VERTS_X/2-3;i<NUM_VERTS_X/2+2;i++)
467                 {
468                         for (j=NUM_VERTS_X/2-3;j<NUM_VERTS_Y/2+2;j++)
469                         {
470                         
471                         aabbMax.setMax(gVertices[i+j*NUM_VERTS_X]);
472                         aabbMin.setMin(gVertices[i+j*NUM_VERTS_X]);
473                         
474                                 gVertices[i+j*NUM_VERTS_X].setValue((i-NUM_VERTS_X*0.5f)*TRIANGLE_SIZE,
475                                         0.f,
476                                         //waveheight*sinf((float)i+offset)*cosf((float)j+offset),
477                                         (j-NUM_VERTS_Y*0.5f)*TRIANGLE_SIZE);
478                                         
479                         aabbMin.setMin(gVertices[i+j*NUM_VERTS_X]);
480                         aabbMax.setMax(gVertices[i+j*NUM_VERTS_X]);
481
482                         }
483                 }
484                 trimeshShape->partialRefitTree(aabbMin,aabbMax);
485 #else
486                 btVector3 aabbMin,aabbMax;
487                 trimeshShape->getMeshInterface()->calculateAabbBruteForce(aabbMin,aabbMax);
488                 trimeshShape->refitTree(aabbMin,aabbMax);
489         
490 #endif
491
492                 
493                 //for debugging: clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation.
494                 //m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(staticBody->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher());
495         }
496
497
498
499         m_dynamicsWorld->stepSimulation(dt);
500         ///enable one of the following to debug (render debug lines each frame)
501         //m_dynamicsWorld->stepSimulation(1./800.,0);
502         //m_dynamicsWorld->stepSimulation(1./60.,100,1./800.);
503         //m_dynamicsWorld->stepSimulation(1./60.,0);
504
505         
506         int lineWidth=450;
507         int xStart = m_glutScreenWidth - lineWidth;
508         int yStart = 20;
509
510         if((getDebugMode() & btIDebugDraw::DBG_DrawText)!=0)
511         {
512                 setOrthographicProjection();
513                 glDisable(GL_LIGHTING);
514                 glColor3f(0, 0, 0);
515                 char buf[124];
516                 
517                 glRasterPos3f(xStart, yStart, 0);
518                 if (enable)
519                 {
520                         sprintf(buf,"InternalEdgeUtility enabled");
521                 } else
522                 {
523                         sprintf(buf,"InternalEdgeUtility disabled");
524                 }
525                 GLDebugDrawString(xStart,20,buf);
526                 yStart+=20;
527                 glRasterPos3f(xStart, yStart, 0);
528                 sprintf(buf,"Press 'n' to toggle InternalEdgeUtility");
529                 yStart+=20;
530                 GLDebugDrawString(xStart,yStart,buf);
531                 glRasterPos3f(xStart, yStart, 0);
532                 
533                 resetPerspectiveProjection();
534                 glEnable(GL_LIGHTING);
535         }
536
537         
538         renderme();
539
540         //optional but useful: debug drawing
541         m_dynamicsWorld->debugDrawWorld();
542
543
544     glFlush();
545     swapBuffers();
546
547 }
548
549
550
551
552 void InternalEdgeDemo::displayCallback(void) {
553
554         clientMoveAndDisplay();
555         /*
556     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
557
558         renderme();
559
560         //optional but useful: debug drawing
561         if (m_dynamicsWorld)
562                 m_dynamicsWorld->debugDrawWorld();
563
564
565     glFlush();
566     glutSwapBuffers();
567         */
568
569 }
570
571
572
573 void    InternalEdgeDemo::exitPhysics()
574 {
575
576
577
578         //cleanup in the reverse order of creation/initialization
579
580         //remove the rigidbodies from the dynamics world and delete them
581         int i;
582         for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
583         {
584                 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
585                 btRigidBody* body = btRigidBody::upcast(obj);
586                 if (body && body->getMotionState())
587                 {
588                         delete body->getMotionState();
589                 }
590                 m_dynamicsWorld->removeCollisionObject( obj );
591                 delete obj;
592         }
593
594         //delete collision shapes
595         for (int j=0;j<m_collisionShapes.size();j++)
596         {
597                 btCollisionShape* shape = m_collisionShapes[j];
598                 delete shape;
599         }
600
601         //delete dynamics world
602         delete m_dynamicsWorld;
603
604         if (m_indexVertexArrays)
605                 delete m_indexVertexArrays;
606
607         //delete solver
608         delete m_solver;
609
610         //delete broadphase
611         delete m_broadphase;
612
613         //delete dispatcher
614         delete m_dispatcher;
615
616         delete m_collisionConfiguration;
617
618         
619 }
620
621
622
623