Bullet Collision Detection & Physics Library
btBulletWorldImporter.cpp
Go to the documentation of this file.
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
23 #endif
24 
25 
26 //#define USE_INTERNAL_EDGE_UTILITY
27 #ifdef USE_INTERNAL_EDGE_UTILITY
29 #endif //USE_INTERNAL_EDGE_UTILITY
30 
32  :btWorldImporter(world)
33 {
34 }
35 
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 
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 
90  {
91  bulletFile2->dumpChunks(bulletFile2->getFileDNA());
92  }
93 
94  return convertAllObjects(bulletFile2);
95 
96 }
97 
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  {
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  {
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
260  {
262  if (trimesh->getTriangleInfoMap())
263  {
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  {
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
289  {
291  if (trimesh->getTriangleInfoMap())
292  {
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];
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  {
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  {
355  convertConstraintFloat(dc, rbA,rbB, bulletFile2->getVersion());
356  }
357 
358 
359  }
360 
361  return true;
362 }
363 
void clear()
Definition: btHashMap.h:440
btTransformFloatData m_worldTransform
static const btRigidBody * upcast(const btCollisionObject *colObj)
to keep collision detection and dynamics separate we don't store a rigidbody pointer but a rigidbody ...
Definition: btRigidBody.h:200
btVector3DoubleData m_gravity
int getVersion() const
Definition: bFile.h:161
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
void convertConstraintBackwardsCompatible281(btTypedConstraintData *constraintData, btRigidBody *rbA, btRigidBody *rbB, int fileVersion)
btCollisionShape * convertCollisionShape(btCollisionShapeData *shapeData)
int getShapeType() const
void deSerializeFloat(const struct btTransformFloatData &dataIn)
Definition: btTransform.h:286
void convertRigidBodyDouble(btRigidBodyDoubleData *colObjData)
void deSerializeDouble(const struct btVector3DoubleData &dataIn)
Definition: btVector3.h:1333
const btTriangleInfoMap * getTriangleInfoMap() const
void convertRigidBodyFloat(btRigidBodyFloatData *colObjData)
btAlignedObjectArray< bStructHandle * > m_constraints
Definition: btBulletFile.h:52
double m_floats[4]
Definition: btVector3.h:1308
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
The btCollisionShape class provides an interface for collision shapes that can be shared among btColl...
btAlignedObjectArray< bStructHandle * > m_collisionObjects
Definition: btBulletFile.h:48
btHashMap< btHashString, btCollisionShape * > m_nameShapeMap
bool loadFile(const char *fileName, const char *preSwapFilenameOut=0)
if you pass a valid preSwapFilenameOut, it will save a new file with a different endianness this pre-...
int getCollisionFlags() const
void dumpChunks(bDNA *dna)
Definition: bFile.cpp:1546
bDNA * getFileDNA()
Definition: bFile.h:120
btVector3FloatData m_gravity
void setRestitution(btScalar rest)
btContactSolverInfoFloatData m_solverInfo
The btBvhTriangleMeshShape is a static-triangle mesh shape, it can only be used for fixed/non-moving ...
void preSwap()
Definition: bFile.cpp:590
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
btHashMap< btHashPtr, btOptimizedBvh * > m_bvhMap
int size() const
return the number of elements in the array
virtual void parse(int verboseMode)
btVector3FloatData m_origin
Definition: btTransform.h:256
void setFriction(btScalar frict)
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
Definition: btRigidBody.h:587
virtual void deSerializeDouble(struct btQuantizedBvhDoubleData &quantizedBvhDoubleData)
virtual btOptimizedBvh * createOptimizedBvh()
acceleration and connectivity structures
btHashMap< btHashPtr, btCollisionShape * > m_shapeMap
char * duplicateName(const char *name)
btCollisionObject can be used to manage collision detection objects.
#define btTypedConstraintData2
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:269
The btRigidBody is the main class for rigid body objects.
Definition: btRigidBody.h:62
The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface.
virtual btCollisionObject * createCollisionObject(const btTransform &startTransform, btCollisionShape *shape, const char *bodyName)
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
Definition: btRigidBody.h:561
this structure is not used, except for loading pre-2.82 .bullet files
void convertConstraintFloat(btTypedConstraintFloatData *constraintData, btRigidBody *rbA, btRigidBody *rbB, int fileVersion)
void writeFile(const char *fileName)
Definition: bFile.cpp:583
virtual void setDynamicsWorldInfo(const btVector3 &gravity, const btContactSolverInfo &solverInfo)
those virtuals are called by load and can be overridden by the user
btContactSolverInfoDoubleData m_solverInfo
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
const Value * find(const Key &key) const
Definition: btHashMap.h:402
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
virtual bool convertAllObjects(bParse::btBulletFile *file)
void setCollisionFlags(int flags)
btTransformDoubleData m_worldTransform
btAlignedObjectArray< bStructHandle * > m_bvhs
Definition: btBulletFile.h:54
virtual void deSerializeFloat(struct btQuantizedBvhFloatData &quantizedBvhFloatData)
static btRigidBody & getFixedBody()
double m_singleAxisRollingFrictionThreshold
it is only used for 'explicit' version of gyroscopic force
btAlignedObjectArray< bStructHandle * > m_collisionShapes
Definition: btBulletFile.h:50
btHashMap< btHashPtr, btCollisionObject * > m_bodyMap
bool loadFileFromMemory(char *memoryBuffer, int len)
the memoryBuffer might be modified (for example if endian swaps are necessary)
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
btAlignedObjectArray< bStructHandle * > m_dynamicsWorldInfo
Definition: btBulletFile.h:58
void deSerializeFloat(const struct btVector3FloatData &dataIn)
Definition: btVector3.h:1319
void deSerializeDouble(const struct btTransformDoubleData &dataIn)
Definition: btTransform.h:292
btBulletWorldImporter(btDynamicsWorld *world=0)
btHashMap< btHashPtr, const char * > m_objectNameMap
btAlignedObjectArray< bStructHandle * > m_rigidBodies
Definition: btBulletFile.h:46
int getFlags() const
Definition: bFile.h:127
btVector3DoubleData m_origin
Definition: btTransform.h:262
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
void convertConstraintDouble(btTypedConstraintDoubleData *constraintData, btRigidBody *rbA, btRigidBody *rbB, int fileVersion)
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:278