GCOP  1.0
bulletworld.h
Go to the documentation of this file.
00001 #ifndef BULLET_WORLD
00002 #define BULLET_WORLD
00003 
00011 #include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
00012 #include <BulletDynamics/Dynamics/btRigidBody.h>
00013 #include <btBulletDynamicsCommon.h>
00014 #include <LinearMath/btDefaultMotionState.h>
00015 #include <BulletDynamics/Dynamics/btDynamicsWorld.h>
00016 #include <BulletCollision/CollisionShapes/btCollisionShape.h>
00017 #include <BulletCollision/CollisionShapes/btCollisionShape.h>
00018 #include <BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h>
00019 #include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
00020 #include <BulletDynamics/ConstraintSolver/btConstraintSolver.h>
00021 
00022 #include <iostream>
00023 #include <stdio.h>
00024 
00025 using namespace std;
00026 
00027 namespace gcop{
00028   class BulletWorld
00029   {
00030     protected:
00031       class btBroadphaseInterface*  m_overlappingPairCache;
00032 
00033       class btCollisionDispatcher*  m_dispatcher;
00034 
00035       class btConstraintSolver* m_constraintSolver;
00036 
00037       class btDefaultCollisionConfiguration* m_collisionConfiguration;
00038 
00039 
00040       //#TODO Provide custom coordinate sysem
00041       bool usezupaxis;
00042 
00043     public: 
00044       btDynamicsWorld*    m_dynamicsWorld;
00045       btScalar m_defaultContactProcessingThreshold;
00046       btAlignedObjectArray<btCollisionShape*> m_collisionShapes;
00047       btVector3 worldMin;
00048       btVector3 worldMax;
00049 
00050 
00051     public:
00057       BulletWorld(bool usezupaxis_ = false, btVector3 worldMin_ = btVector3(-1000,-1000,-1000), btVector3 worldMax_ = btVector3(1000,1000,1000)):
00058         m_defaultContactProcessingThreshold(1e10)
00059         ,worldMin(worldMin_), worldMax(worldMax_), usezupaxis(usezupaxis_)
00060       {
00061         m_collisionConfiguration = new btDefaultCollisionConfiguration();
00062         m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
00063         m_overlappingPairCache = new btAxisSweep3(worldMin,worldMax);
00064         m_constraintSolver = new btSequentialImpulseConstraintSolver();
00065         m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration);
00066         if(usezupaxis)
00067         {
00068           m_dynamicsWorld->setGravity(btVector3(0,0,-9.81));//Sets Gravity Vector
00069           btVector3 gravity_ = m_dynamicsWorld->getGravity();
00070         }
00071         else
00072         {
00073           m_dynamicsWorld->setGravity(btVector3(0,-9.81,0));//Sets Gravity Vector
00074         }
00075       }
00078       bool IsZupAxis()
00079       {
00080         return usezupaxis;
00081       }
00085       void SetGravity(btVector3 gravity_)
00086       {
00087         m_dynamicsWorld->setGravity(gravity_);//Sets Gravity Vector
00088       }
00089 
00096       btRigidBody*  LocalCreateRigidBody(float mass, const btTransform& startTransform, btCollisionShape* shape, bool use_motion_state = false)
00097       {
00098         btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
00099 
00100         //rigidbody is dynamic if and only if mass is non zero, otherwise static
00101         bool isDynamic = (mass != 0.f);
00102 
00103 
00104         btVector3 localInertia(0,0,0);
00105         if (isDynamic)
00106           shape->calculateLocalInertia(mass,localInertia);
00107 
00108         btRigidBody* body = NULL;
00109         //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
00110         if(use_motion_state)
00111         {
00112           btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
00113 
00114           btRigidBody::btRigidBodyConstructionInfo cInfo(mass,myMotionState,shape,localInertia);
00115 
00116           body = new btRigidBody(cInfo);
00117           body->setContactProcessingThreshold(m_defaultContactProcessingThreshold);
00118         }
00119         else
00120         {
00121           body = new btRigidBody(mass,0,shape,localInertia);
00122           body->setWorldTransform(startTransform);
00123         }
00124         if(body != NULL)
00125           m_dynamicsWorld->addRigidBody(body);
00126 
00127         return body;
00128       }
00129 
00135       btTriangleIndexVertexArray *CreateVertexArrayFromSTL(const char *filename, btVector3 scale = btVector3(1,1,1))
00136       {
00137         FILE* file = fopen(filename,"rb");
00138         if(file)
00139         {
00140           int size=0;
00141           if (fseek(file, 0, SEEK_END) || (size = ftell(file)) == EOF || fseek(file, 0, SEEK_SET))
00142           {
00143             printf("Error: Cannot access file to determine size of %s\n", filename);
00144           } 
00145           else
00146           {
00147             if (size)
00148             {
00149               printf("Open STL file of %d bytes\n",size);
00150               char* memoryBuffer = new char[size+1];
00151               int actualBytesRead = fread(memoryBuffer,1,size,file);
00152               if (actualBytesRead!=size)
00153               {
00154                 printf("Error reading from file %s",filename);
00155               } 
00156               else
00157               {
00158                 int numTriangles = *(int*)&memoryBuffer[80];
00159 
00160                 if (numTriangles)
00161                 {
00162                   {
00163                     //perform a sanity check instead of crashing on invalid triangles/STL files
00164                     int expectedBinaryFileSize = numTriangles* 50 + 84;
00165                     if (expectedBinaryFileSize != size)
00166                     {
00167                       return 0;
00168                     }
00169 
00170                   }
00171                   btScalar *verts = (btScalar *)malloc(3*3*numTriangles*sizeof(btScalar));//No compression used Can use trees if needed later 3 vertices per triangle, 3 indices per vertex
00172                   int *inds = (int *)malloc(3*numTriangles*sizeof(int));
00173                   int i;
00174 
00175                   {
00176                     float *vert_temp = (float *)malloc(3*3*numTriangles*sizeof(float));
00177 
00178 #pragma omp parallel for private(i)
00179                     for (i=0;i<numTriangles;i++)
00180                     {
00181                       memcpy(&vert_temp[9*i],&memoryBuffer[96+i*50],36);//9 floats of 4 bytes each (3 loats per vertex)
00182                       inds[3*i+0] = 3*i;
00183                       inds[3*i+1] = 3*i+1;
00184                       inds[3*i+2] = 3*i+2;
00185                       //cout<<"Vertices["<<3*i<<"]: "<<verts[3*i]<<"\t"<<verts[3*i+1]<<"\t"<<verts[3*i+2]<<endl;
00186                       //cout<<"Vertices["<<(3*i+1)<<"]: "<<verts[3*(i+1)]<<"\t"<<verts[3*(i+1)+1]<<"\t"<<verts[3*(i+1)+2]<<endl;
00187                       //cout<<"Vertices["<<(3*i+2)<<"]: "<<verts[3*(i+2)]<<"\t"<<verts[3*(i+2)+1]<<"\t"<<verts[3*(i+2)+2]<<endl;
00188                     }
00189 
00190                     //Convert float vertices into  double vertices:
00191 #pragma omp parallel for private(i)
00192                     for(i = 0; i < 9*numTriangles; i++)
00193                     {
00194                       verts[i] = double(vert_temp[i]);//explicit casting 
00195                     }
00196                   }
00197 
00198                   //Scale the vertices accordingly
00199                   if((scale - btVector3(1,1,1)).norm()>1e-6)
00200                   {
00201 #pragma omp parallel for private(i)
00202                     for(i = 0;i < 9*numTriangles;i++)
00203                     {
00204                       verts[i] *= scale[i%3];
00205                     }
00206                   }
00207 
00208                   int vertStride = 3*sizeof(btScalar); 
00209                   int indexStride = 3*sizeof(int);
00210                   btTriangleIndexVertexArray *m_indexVertexArrays = new btTriangleIndexVertexArray(numTriangles
00211                                                                       ,inds
00212                                                                       ,indexStride
00213                                                                       ,3*numTriangles,verts,vertStride);
00214                   return m_indexVertexArrays;
00215                   //return CreateMeshFromData(verts, inds, numTriangles, 3*numTriangles);
00216                 }
00217                 delete[] memoryBuffer;
00218               }
00219             }
00220             fclose(file);
00221           }
00222         }
00223         return 0;
00224       }
00225 
00233       btCollisionShape *CreateMeshFromData(btScalar *verts, int *inds, int noftriangles, int nofverts)
00234       {
00235         if(!inds || !verts)
00236           return 0;
00237         int vertStride = 3*sizeof(btScalar); 
00238         int indexStride = 3*sizeof(int);
00239         btTriangleIndexVertexArray *m_indexVertexArrays = new btTriangleIndexVertexArray(noftriangles
00240                                                                                         ,inds
00241                                                                                         ,indexStride
00242                                                                                         ,nofverts,verts,vertStride);
00243         bool useQuantizedAabbCompression = true;
00244         btCollisionShape *collshape = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression);
00245         m_collisionShapes.push_back(collshape);
00246         return collshape;
00247       }
00248 
00253       btCollisionShape *CreateMeshFromSTL(const char *filename, btVector3 scale = btVector3(1,1,1))
00254       {
00255         btTriangleIndexVertexArray *vertexarray = CreateVertexArrayFromSTL(filename, scale);
00256         if(vertexarray != 0)
00257         {
00258           bool useQuantizedAabbCompression = true;
00259           btCollisionShape *collshape = new btBvhTriangleMeshShape(vertexarray, useQuantizedAabbCompression);
00260           m_collisionShapes.push_back(collshape);
00261           return collshape;
00262         }
00263         return 0;
00264       }
00265       
00266 
00273       btCollisionShape *CreateHeightMap(btScalar length, btScalar width, const char *data, btScalar maxHeight = 100)
00274       {
00275         btHeightfieldTerrainShape* heightFieldShape;
00276         if(usezupaxis)
00277         {
00278           heightFieldShape = new btHeightfieldTerrainShape(width,length,data,maxHeight,2,false, false);
00279         }
00280         else
00281         {
00282           heightFieldShape = new btHeightfieldTerrainShape(width,length,data,maxHeight,1,false,false);
00283         }
00284         return (btCollisionShape*)heightFieldShape;
00285       }
00286 
00293       btCollisionShape *CreateGroundPlane(btScalar length, btScalar width, btScalar(*heightfunc)(btScalar, btScalar)=0,int subdivisions = 1)
00294       {
00295         cout<<"Subdivisions: "<<subdivisions<<endl;
00296         int i;
00297 
00298         const btScalar TRIANGLE_SIZE_X = (length/subdivisions);
00299         const btScalar TRIANGLE_SIZE_Y = (width/subdivisions);
00300 
00301         const int NUM_VERTS_X = subdivisions+1;
00302         const int NUM_VERTS_Y = subdivisions+1;
00303         const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y;
00304 
00305         const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1);
00306 
00307         btScalar *m_vertices = new btScalar[3*totalVerts];
00308         int*  gIndices = new int[totalTriangles*3];
00309 
00310         cout<<"Number of Verts: "<<NUM_VERTS_X<<"\t"<<NUM_VERTS_Y<<endl;
00311 
00312 #pragma omp parallel for private(i)
00313         for ( i=0;i<NUM_VERTS_X;i++)
00314         {
00315           for (int j=0;j<NUM_VERTS_Y;j++)
00316           {
00317             btScalar height = 0.f;//20.f*sinf(float(i)*wl)*cosf(float(j)*wl);
00318             if(heightfunc != 0)
00319             {
00320               height = heightfunc(i*TRIANGLE_SIZE_X, j*TRIANGLE_SIZE_Y);
00321             }
00322 
00323             m_vertices[3*(i+j*NUM_VERTS_X)] = (i-NUM_VERTS_X*0.5)*TRIANGLE_SIZE_X + 0.5*TRIANGLE_SIZE_X;
00324             if(usezupaxis)
00325             {
00326               m_vertices[3*(i+j*NUM_VERTS_X)+1] = (j-NUM_VERTS_Y*0.5)*TRIANGLE_SIZE_Y + 0.5*TRIANGLE_SIZE_Y;
00327               m_vertices[3*(i+j*NUM_VERTS_X)+2] = height;
00328             }
00329             else
00330             {
00331               m_vertices[3*(i+j*NUM_VERTS_X)+1] = height;
00332               m_vertices[3*(i+j*NUM_VERTS_X)+2] = (j-NUM_VERTS_Y*0.5)*TRIANGLE_SIZE_Y + 0.5*TRIANGLE_SIZE_Y;
00333             }
00334             //cout<<"Vertices: "<<3*(i+j*NUM_VERTS_X)<<"\t"<<m_vertices[3*(i+j*NUM_VERTS_X)]<<"\t"<<m_vertices[3*(i+j*NUM_VERTS_X)+1]<<"\t"<<m_vertices[3*(i+j*NUM_VERTS_X)+2]<<endl;
00335           }
00336         }
00337 
00338 #pragma omp parallel for private(i)
00339         for ( i=0;i<NUM_VERTS_X-1;i++)
00340         {
00341           for (int j=0;j<NUM_VERTS_Y-1;j++)
00342           {
00343             int index = (i*(NUM_VERTS_Y-1) + j)*6;
00344             gIndices[index++] = j*NUM_VERTS_X+i;
00345             gIndices[index++] = j*NUM_VERTS_X+i+1;
00346             gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
00347 
00348             gIndices[index++] = j*NUM_VERTS_X+i;
00349             gIndices[index++] = (j+1)*NUM_VERTS_X+i+1;
00350             gIndices[index++] = (j+1)*NUM_VERTS_X+i;
00351             //cout<<"Indices: "<<j*NUM_VERTS_X+i<<"\t"<<j*NUM_VERTS_X+i+1<<(j+1)*NUM_VERTS_X+i+1<<"\t"<<j*NUM_VERTS_X+i<<"\t"<<(j+1)*NUM_VERTS_X+i+1<<"\t"<<(j+1)*NUM_VERTS_X+i<<endl;
00352           }
00353         }
00354         return CreateMeshFromData(m_vertices, gIndices, totalTriangles, totalVerts);
00355       }
00356 
00361       void Step(double dt, int substeps)
00362       {
00363         if(!m_dynamicsWorld)
00364         {
00365           cerr<<"m_dynamicsWorld not defined"<<endl;
00366           return;
00367         }
00368         double fixedstepsize = dt/substeps;
00369         int numSimSteps = m_dynamicsWorld->stepSimulation(dt,substeps,fixedstepsize);//No interpolation used
00370       }
00371 
00374       void Reset()
00375       {
00376         //cout<<"Resetting Pool and constraint solver"<<endl;
00377         m_overlappingPairCache->resetPool(m_dispatcher);
00378         m_constraintSolver->reset();
00379       }
00380 
00383       ~BulletWorld()      
00384       {
00385         delete m_dynamicsWorld;
00386 
00387         //remove the rigidbodies from the dynamics world and delete them
00388         int i;
00389         for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
00390         {
00391           btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
00392           btRigidBody* body = btRigidBody::upcast(obj);
00393           if (body && body->getMotionState())
00394           {
00395             delete body->getMotionState();
00396           }
00397           m_dynamicsWorld->removeCollisionObject( obj );
00398           delete obj;
00399         }
00400         //delete collision shapes
00401         for (int j=0;j<m_collisionShapes.size();j++)
00402         {
00403           btCollisionShape* shape = m_collisionShapes[j];
00404           delete shape;
00405         }
00406 
00407 
00408         //delete solver
00409         delete m_constraintSolver;
00410 
00411         //delete broadphase
00412         delete m_overlappingPairCache;
00413 
00414         //delete dispatcher
00415         delete m_dispatcher;
00416 
00417         delete m_collisionConfiguration;
00418 
00419       }
00420   };
00421 };
00422 #endif