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