1 /* 2 Bullet Continuous Collision Detection and Physics Library 3 Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org 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 16 17 #include "btBulletWorldImporter.h" 18 #include "../BulletFileLoader/btBulletFile.h" 19 20 #include "btBulletDynamicsCommon.h" 21 #ifndef USE_GIMPACT 22 #include "BulletCollision/Gimpact/btGImpactShape.h" 23 #endif 24 25 26 //#define USE_INTERNAL_EDGE_UTILITY 27 #ifdef USE_INTERNAL_EDGE_UTILITY 28 #include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.h" 29 #endif //USE_INTERNAL_EDGE_UTILITY 30 31 btBulletWorldImporter::btBulletWorldImporter(btDynamicsWorld* world) 32 :btWorldImporter(world) 33 { 34 } 35 36 btBulletWorldImporter::~btBulletWorldImporter() 37 { 38 } 39 40 41 bool btBulletWorldImporter::loadFile( const char* fileName, const char* preSwapFilenameOut) 42 { 43 bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(fileName); 44 45 46 bool result = loadFileFromMemory(bulletFile2); 47 //now you could save the file in 'native' format using 48 //bulletFile2->writeFile("native.bullet"); 49 if (result) 50 { 51 if (preSwapFilenameOut) 52 { 53 bulletFile2->preSwap(); 54 bulletFile2->writeFile(preSwapFilenameOut); 55 } 56 57 } 58 delete bulletFile2; 59 60 return result; 61 62 } 63 64 65 66 bool btBulletWorldImporter::loadFileFromMemory( char* memoryBuffer, int len) 67 { 68 bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(memoryBuffer,len); 69 70 bool result = loadFileFromMemory(bulletFile2); 71 72 delete bulletFile2; 73 74 return result; 75 } 76 77 78 79 80 bool btBulletWorldImporter::loadFileFromMemory( bParse::btBulletFile* bulletFile2) 81 { 82 bool ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0; 83 84 if (ok) 85 bulletFile2->parse(m_verboseMode); 86 else 87 return false; 88 89 if (m_verboseMode & bParse::FD_VERBOSE_DUMP_CHUNKS) 90 { 91 bulletFile2->dumpChunks(bulletFile2->getFileDNA()); 92 } 93 94 return convertAllObjects(bulletFile2); 95 96 } 97 98 bool btBulletWorldImporter::convertAllObjects( bParse::btBulletFile* bulletFile2) 99 { 100 101 m_shapeMap.clear(); 102 m_bodyMap.clear(); 103 104 int i; 105 106 for (i=0;i<bulletFile2->m_bvhs.size();i++) 107 { 108 btOptimizedBvh* bvh = createOptimizedBvh(); 109 110 if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) 111 { 112 btQuantizedBvhDoubleData* bvhData = (btQuantizedBvhDoubleData*)bulletFile2->m_bvhs[i]; 113 bvh->deSerializeDouble(*bvhData); 114 } else 115 { 116 btQuantizedBvhFloatData* bvhData = (btQuantizedBvhFloatData*)bulletFile2->m_bvhs[i]; 117 bvh->deSerializeFloat(*bvhData); 118 } 119 m_bvhMap.insert(bulletFile2->m_bvhs[i],bvh); 120 } 121 122 123 124 125 126 for (i=0;i<bulletFile2->m_collisionShapes.size();i++) 127 { 128 btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i]; 129 btCollisionShape* shape = convertCollisionShape(shapeData); 130 if (shape) 131 { 132 // printf("shapeMap.insert(%x,%x)\n",shapeData,shape); 133 m_shapeMap.insert(shapeData,shape); 134 } 135 136 if (shape&& shapeData->m_name) 137 { 138 char* newname = duplicateName(shapeData->m_name); 139 m_objectNameMap.insert(shape,newname); 140 m_nameShapeMap.insert(newname,shape); 141 } 142 } 143 144 145 146 147 148 for (int i=0;i<bulletFile2->m_dynamicsWorldInfo.size();i++) 149 { 150 if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) 151 { 152 btDynamicsWorldDoubleData* solverInfoData = (btDynamicsWorldDoubleData*)bulletFile2->m_dynamicsWorldInfo[i]; 153 btContactSolverInfo solverInfo; 154 155 btVector3 gravity; 156 gravity.deSerializeDouble(solverInfoData->m_gravity); 157 158 solverInfo.m_tau = btScalar(solverInfoData->m_solverInfo.m_tau); 159 solverInfo.m_damping = btScalar(solverInfoData->m_solverInfo.m_damping); 160 solverInfo.m_friction = btScalar(solverInfoData->m_solverInfo.m_friction); 161 solverInfo.m_timeStep = btScalar(solverInfoData->m_solverInfo.m_timeStep); 162 163 solverInfo.m_restitution = btScalar(solverInfoData->m_solverInfo.m_restitution); 164 solverInfo.m_maxErrorReduction = btScalar(solverInfoData->m_solverInfo.m_maxErrorReduction); 165 solverInfo.m_sor = btScalar(solverInfoData->m_solverInfo.m_sor); 166 solverInfo.m_erp = btScalar(solverInfoData->m_solverInfo.m_erp); 167 168 solverInfo.m_erp2 = btScalar(solverInfoData->m_solverInfo.m_erp2); 169 solverInfo.m_globalCfm = btScalar(solverInfoData->m_solverInfo.m_globalCfm); 170 solverInfo.m_splitImpulsePenetrationThreshold = btScalar(solverInfoData->m_solverInfo.m_splitImpulsePenetrationThreshold); 171 solverInfo.m_splitImpulseTurnErp = btScalar(solverInfoData->m_solverInfo.m_splitImpulseTurnErp); 172 173 solverInfo.m_linearSlop = btScalar(solverInfoData->m_solverInfo.m_linearSlop); 174 solverInfo.m_warmstartingFactor = btScalar(solverInfoData->m_solverInfo.m_warmstartingFactor); 175 solverInfo.m_maxGyroscopicForce = btScalar(solverInfoData->m_solverInfo.m_maxGyroscopicForce); 176 solverInfo.m_singleAxisRollingFrictionThreshold = btScalar(solverInfoData->m_solverInfo.m_singleAxisRollingFrictionThreshold); 177 178 solverInfo.m_numIterations = solverInfoData->m_solverInfo.m_numIterations; 179 solverInfo.m_solverMode = solverInfoData->m_solverInfo.m_solverMode; 180 solverInfo.m_restingContactRestitutionThreshold = solverInfoData->m_solverInfo.m_restingContactRestitutionThreshold; 181 solverInfo.m_minimumSolverBatchSize = solverInfoData->m_solverInfo.m_minimumSolverBatchSize; 182 183 solverInfo.m_splitImpulse = solverInfoData->m_solverInfo.m_splitImpulse; 184 185 setDynamicsWorldInfo(gravity,solverInfo); 186 } else 187 { 188 btDynamicsWorldFloatData* solverInfoData = (btDynamicsWorldFloatData*)bulletFile2->m_dynamicsWorldInfo[i]; 189 btContactSolverInfo solverInfo; 190 191 btVector3 gravity; 192 gravity.deSerializeFloat(solverInfoData->m_gravity); 193 194 solverInfo.m_tau = solverInfoData->m_solverInfo.m_tau; 195 solverInfo.m_damping = solverInfoData->m_solverInfo.m_damping; 196 solverInfo.m_friction = solverInfoData->m_solverInfo.m_friction; 197 solverInfo.m_timeStep = solverInfoData->m_solverInfo.m_timeStep; 198 199 solverInfo.m_restitution = solverInfoData->m_solverInfo.m_restitution; 200 solverInfo.m_maxErrorReduction = solverInfoData->m_solverInfo.m_maxErrorReduction; 201 solverInfo.m_sor = solverInfoData->m_solverInfo.m_sor; 202 solverInfo.m_erp = solverInfoData->m_solverInfo.m_erp; 203 204 solverInfo.m_erp2 = solverInfoData->m_solverInfo.m_erp2; 205 solverInfo.m_globalCfm = solverInfoData->m_solverInfo.m_globalCfm; 206 solverInfo.m_splitImpulsePenetrationThreshold = solverInfoData->m_solverInfo.m_splitImpulsePenetrationThreshold; 207 solverInfo.m_splitImpulseTurnErp = solverInfoData->m_solverInfo.m_splitImpulseTurnErp; 208 209 solverInfo.m_linearSlop = solverInfoData->m_solverInfo.m_linearSlop; 210 solverInfo.m_warmstartingFactor = solverInfoData->m_solverInfo.m_warmstartingFactor; 211 solverInfo.m_maxGyroscopicForce = solverInfoData->m_solverInfo.m_maxGyroscopicForce; 212 solverInfo.m_singleAxisRollingFrictionThreshold = solverInfoData->m_solverInfo.m_singleAxisRollingFrictionThreshold; 213 214 solverInfo.m_numIterations = solverInfoData->m_solverInfo.m_numIterations; 215 solverInfo.m_solverMode = solverInfoData->m_solverInfo.m_solverMode; 216 solverInfo.m_restingContactRestitutionThreshold = solverInfoData->m_solverInfo.m_restingContactRestitutionThreshold; 217 solverInfo.m_minimumSolverBatchSize = solverInfoData->m_solverInfo.m_minimumSolverBatchSize; 218 219 solverInfo.m_splitImpulse = solverInfoData->m_solverInfo.m_splitImpulse; 220 221 setDynamicsWorldInfo(gravity,solverInfo); 222 } 223 } 224 225 226 for (i=0;i<bulletFile2->m_rigidBodies.size();i++) 227 { 228 if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) 229 { 230 btRigidBodyDoubleData* colObjData = (btRigidBodyDoubleData*)bulletFile2->m_rigidBodies[i]; 231 convertRigidBodyDouble(colObjData); 232 } else 233 { 234 btRigidBodyFloatData* colObjData = (btRigidBodyFloatData*)bulletFile2->m_rigidBodies[i]; 235 convertRigidBodyFloat(colObjData); 236 } 237 238 239 } 240 241 for (i=0;i<bulletFile2->m_collisionObjects.size();i++) 242 { 243 if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) 244 { 245 btCollisionObjectDoubleData* colObjData = (btCollisionObjectDoubleData*)bulletFile2->m_collisionObjects[i]; 246 btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape); 247 if (shapePtr && *shapePtr) 248 { 249 btTransform startTransform; 250 colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f; 251 startTransform.deSerializeDouble(colObjData->m_worldTransform); 252 253 btCollisionShape* shape = (btCollisionShape*)*shapePtr; 254 btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name); 255 body->setFriction(btScalar(colObjData->m_friction)); 256 body->setRestitution(btScalar(colObjData->m_restitution)); 257 258 #ifdef USE_INTERNAL_EDGE_UTILITY 259 if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) 260 { 261 btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape; 262 if (trimesh->getTriangleInfoMap()) 263 { 264 body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); 265 } 266 } 267 #endif //USE_INTERNAL_EDGE_UTILITY 268 m_bodyMap.insert(colObjData,body); 269 } else 270 { 271 printf("error: no shape found\n"); 272 } 273 274 } else 275 { 276 btCollisionObjectFloatData* colObjData = (btCollisionObjectFloatData*)bulletFile2->m_collisionObjects[i]; 277 btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape); 278 if (shapePtr && *shapePtr) 279 { 280 btTransform startTransform; 281 colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f; 282 startTransform.deSerializeFloat(colObjData->m_worldTransform); 283 284 btCollisionShape* shape = (btCollisionShape*)*shapePtr; 285 btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name); 286 287 #ifdef USE_INTERNAL_EDGE_UTILITY 288 if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) 289 { 290 btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape; 291 if (trimesh->getTriangleInfoMap()) 292 { 293 body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); 294 } 295 } 296 #endif //USE_INTERNAL_EDGE_UTILITY 297 m_bodyMap.insert(colObjData,body); 298 } else 299 { 300 printf("error: no shape found\n"); 301 } 302 } 303 304 } 305 306 307 for (i=0;i<bulletFile2->m_constraints.size();i++) 308 { 309 btTypedConstraintData2* constraintData = (btTypedConstraintData2*)bulletFile2->m_constraints[i]; 310 btTypedConstraintFloatData* singleC = (btTypedConstraintFloatData*)bulletFile2->m_constraints[i]; 311 btTypedConstraintDoubleData* doubleC = (btTypedConstraintDoubleData*)bulletFile2->m_constraints[i]; 312 313 btCollisionObject** colAptr = m_bodyMap.find(constraintData->m_rbA); 314 btCollisionObject** colBptr = m_bodyMap.find(constraintData->m_rbB); 315 316 btRigidBody* rbA = 0; 317 btRigidBody* rbB = 0; 318 319 if (colAptr) 320 { 321 rbA = btRigidBody::upcast(*colAptr); 322 if (!rbA) 323 rbA = &getFixedBody(); 324 } 325 if (colBptr) 326 { 327 rbB = btRigidBody::upcast(*colBptr); 328 if (!rbB) 329 rbB = &getFixedBody(); 330 } 331 if (!rbA && !rbB) 332 continue; 333 334 bool isDoublePrecisionData = (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)!=0; 335 336 if (isDoublePrecisionData) 337 { 338 if (bulletFile2->getVersion()>=282) 339 { 340 btTypedConstraintDoubleData* dc = (btTypedConstraintDoubleData*)constraintData; 341 convertConstraintDouble(dc, rbA,rbB, bulletFile2->getVersion()); 342 } else 343 { 344 //double-precision constraints were messed up until 2.82, try to recover data... 345 346 btTypedConstraintData* oldData = (btTypedConstraintData*)constraintData; 347 348 convertConstraintBackwardsCompatible281(oldData, rbA,rbB, bulletFile2->getVersion()); 349 350 } 351 } 352 else 353 { 354 btTypedConstraintFloatData* dc = (btTypedConstraintFloatData*)constraintData; 355 convertConstraintFloat(dc, rbA,rbB, bulletFile2->getVersion()); 356 } 357 358 359 } 360 361 return true; 362 } 363 364