GCOP
1.0
|
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