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 #include "btBulletWorldImporter.h"
17 #include "../BulletFileLoader/btBulletFile.h"
18 
19 #include "btBulletDynamicsCommon.h"
20 #ifndef USE_GIMPACT
22 #endif
23 
24 //#define USE_INTERNAL_EDGE_UTILITY
25 #ifdef USE_INTERNAL_EDGE_UTILITY
27 #endif //USE_INTERNAL_EDGE_UTILITY
28 
30  : btWorldImporter(world)
31 {
32 }
33 
35 {
36 }
37 
38 bool btBulletWorldImporter::loadFile(const char* fileName, const char* preSwapFilenameOut)
39 {
40  bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(fileName);
41 
42  bool result = loadFileFromMemory(bulletFile2);
43  //now you could save the file in 'native' format using
44  //bulletFile2->writeFile("native.bullet");
45  if (result)
46  {
47  if (preSwapFilenameOut)
48  {
49  bulletFile2->preSwap();
50  bulletFile2->writeFile(preSwapFilenameOut);
51  }
52  }
53  delete bulletFile2;
54 
55  return result;
56 }
57 
58 bool btBulletWorldImporter::loadFileFromMemory(char* memoryBuffer, int len)
59 {
60  bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(memoryBuffer, len);
61 
62  bool result = loadFileFromMemory(bulletFile2);
63 
64  delete bulletFile2;
65 
66  return result;
67 }
68 
70 {
71  bool ok = (bulletFile2->getFlags() & bParse::FD_OK) != 0;
72 
73  if (ok)
74  bulletFile2->parse(m_verboseMode);
75  else
76  return false;
77 
79  {
80  bulletFile2->dumpChunks(bulletFile2->getFileDNA());
81  }
82 
83  return convertAllObjects(bulletFile2);
84 }
85 
87 {
88  m_shapeMap.clear();
89  m_bodyMap.clear();
90 
91  int i;
92 
93  for (i = 0; i < bulletFile2->m_bvhs.size(); i++)
94  {
96 
97  if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
98  {
99  btQuantizedBvhDoubleData* bvhData = (btQuantizedBvhDoubleData*)bulletFile2->m_bvhs[i];
100  bvh->deSerializeDouble(*bvhData);
101  }
102  else
103  {
104  btQuantizedBvhFloatData* bvhData = (btQuantizedBvhFloatData*)bulletFile2->m_bvhs[i];
105  bvh->deSerializeFloat(*bvhData);
106  }
107  m_bvhMap.insert(bulletFile2->m_bvhs[i], bvh);
108  }
109 
110  for (i = 0; i < bulletFile2->m_collisionShapes.size(); i++)
111  {
112  btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i];
113  btCollisionShape* shape = convertCollisionShape(shapeData);
114  if (shape)
115  {
116  // printf("shapeMap.insert(%x,%x)\n",shapeData,shape);
117  m_shapeMap.insert(shapeData, shape);
118  }
119 
120  if (shape && shapeData->m_name)
121  {
122  char* newname = duplicateName(shapeData->m_name);
123  m_objectNameMap.insert(shape, newname);
124  m_nameShapeMap.insert(newname, shape);
125  }
126  }
127 
128  for (int i = 0; i < bulletFile2->m_dynamicsWorldInfo.size(); i++)
129  {
130  if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
131  {
132  btDynamicsWorldDoubleData* solverInfoData = (btDynamicsWorldDoubleData*)bulletFile2->m_dynamicsWorldInfo[i];
133  btContactSolverInfo solverInfo;
134 
135  btVector3 gravity;
136  gravity.deSerializeDouble(solverInfoData->m_gravity);
137 
138  solverInfo.m_tau = btScalar(solverInfoData->m_solverInfo.m_tau);
139  solverInfo.m_damping = btScalar(solverInfoData->m_solverInfo.m_damping);
140  solverInfo.m_friction = btScalar(solverInfoData->m_solverInfo.m_friction);
141  solverInfo.m_timeStep = btScalar(solverInfoData->m_solverInfo.m_timeStep);
142 
143  solverInfo.m_restitution = btScalar(solverInfoData->m_solverInfo.m_restitution);
144  solverInfo.m_maxErrorReduction = btScalar(solverInfoData->m_solverInfo.m_maxErrorReduction);
145  solverInfo.m_sor = btScalar(solverInfoData->m_solverInfo.m_sor);
146  solverInfo.m_erp = btScalar(solverInfoData->m_solverInfo.m_erp);
147 
148  solverInfo.m_erp2 = btScalar(solverInfoData->m_solverInfo.m_erp2);
149  solverInfo.m_globalCfm = btScalar(solverInfoData->m_solverInfo.m_globalCfm);
150  solverInfo.m_splitImpulsePenetrationThreshold = btScalar(solverInfoData->m_solverInfo.m_splitImpulsePenetrationThreshold);
151  solverInfo.m_splitImpulseTurnErp = btScalar(solverInfoData->m_solverInfo.m_splitImpulseTurnErp);
152 
153  solverInfo.m_linearSlop = btScalar(solverInfoData->m_solverInfo.m_linearSlop);
154  solverInfo.m_warmstartingFactor = btScalar(solverInfoData->m_solverInfo.m_warmstartingFactor);
155  solverInfo.m_maxGyroscopicForce = btScalar(solverInfoData->m_solverInfo.m_maxGyroscopicForce);
156  solverInfo.m_singleAxisRollingFrictionThreshold = btScalar(solverInfoData->m_solverInfo.m_singleAxisRollingFrictionThreshold);
157 
158  solverInfo.m_numIterations = solverInfoData->m_solverInfo.m_numIterations;
159  solverInfo.m_solverMode = solverInfoData->m_solverInfo.m_solverMode;
160  solverInfo.m_restingContactRestitutionThreshold = solverInfoData->m_solverInfo.m_restingContactRestitutionThreshold;
161  solverInfo.m_minimumSolverBatchSize = solverInfoData->m_solverInfo.m_minimumSolverBatchSize;
162 
163  solverInfo.m_splitImpulse = solverInfoData->m_solverInfo.m_splitImpulse;
164 
165  setDynamicsWorldInfo(gravity, solverInfo);
166  }
167  else
168  {
169  btDynamicsWorldFloatData* solverInfoData = (btDynamicsWorldFloatData*)bulletFile2->m_dynamicsWorldInfo[i];
170  btContactSolverInfo solverInfo;
171 
172  btVector3 gravity;
173  gravity.deSerializeFloat(solverInfoData->m_gravity);
174 
175  solverInfo.m_tau = solverInfoData->m_solverInfo.m_tau;
176  solverInfo.m_damping = solverInfoData->m_solverInfo.m_damping;
177  solverInfo.m_friction = solverInfoData->m_solverInfo.m_friction;
178  solverInfo.m_timeStep = solverInfoData->m_solverInfo.m_timeStep;
179 
180  solverInfo.m_restitution = solverInfoData->m_solverInfo.m_restitution;
181  solverInfo.m_maxErrorReduction = solverInfoData->m_solverInfo.m_maxErrorReduction;
182  solverInfo.m_sor = solverInfoData->m_solverInfo.m_sor;
183  solverInfo.m_erp = solverInfoData->m_solverInfo.m_erp;
184 
185  solverInfo.m_erp2 = solverInfoData->m_solverInfo.m_erp2;
186  solverInfo.m_globalCfm = solverInfoData->m_solverInfo.m_globalCfm;
187  solverInfo.m_splitImpulsePenetrationThreshold = solverInfoData->m_solverInfo.m_splitImpulsePenetrationThreshold;
188  solverInfo.m_splitImpulseTurnErp = solverInfoData->m_solverInfo.m_splitImpulseTurnErp;
189 
190  solverInfo.m_linearSlop = solverInfoData->m_solverInfo.m_linearSlop;
191  solverInfo.m_warmstartingFactor = solverInfoData->m_solverInfo.m_warmstartingFactor;
192  solverInfo.m_maxGyroscopicForce = solverInfoData->m_solverInfo.m_maxGyroscopicForce;
193  solverInfo.m_singleAxisRollingFrictionThreshold = solverInfoData->m_solverInfo.m_singleAxisRollingFrictionThreshold;
194 
195  solverInfo.m_numIterations = solverInfoData->m_solverInfo.m_numIterations;
196  solverInfo.m_solverMode = solverInfoData->m_solverInfo.m_solverMode;
197  solverInfo.m_restingContactRestitutionThreshold = solverInfoData->m_solverInfo.m_restingContactRestitutionThreshold;
198  solverInfo.m_minimumSolverBatchSize = solverInfoData->m_solverInfo.m_minimumSolverBatchSize;
199 
200  solverInfo.m_splitImpulse = solverInfoData->m_solverInfo.m_splitImpulse;
201 
202  setDynamicsWorldInfo(gravity, solverInfo);
203  }
204  }
205 
206  for (i = 0; i < bulletFile2->m_rigidBodies.size(); i++)
207  {
208  if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
209  {
210  btRigidBodyDoubleData* colObjData = (btRigidBodyDoubleData*)bulletFile2->m_rigidBodies[i];
211  convertRigidBodyDouble(colObjData);
212  }
213  else
214  {
215  btRigidBodyFloatData* colObjData = (btRigidBodyFloatData*)bulletFile2->m_rigidBodies[i];
216  convertRigidBodyFloat(colObjData);
217  }
218  }
219 
220  for (i = 0; i < bulletFile2->m_collisionObjects.size(); i++)
221  {
222  if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
223  {
225  btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
226  if (shapePtr && *shapePtr)
227  {
228  btTransform startTransform;
229  colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
230  startTransform.deSerializeDouble(colObjData->m_worldTransform);
231 
232  btCollisionShape* shape = (btCollisionShape*)*shapePtr;
233  btCollisionObject* body = createCollisionObject(startTransform, shape, colObjData->m_name);
234  body->setFriction(btScalar(colObjData->m_friction));
235  body->setRestitution(btScalar(colObjData->m_restitution));
236 
237 #ifdef USE_INTERNAL_EDGE_UTILITY
239  {
241  if (trimesh->getTriangleInfoMap())
242  {
244  }
245  }
246 #endif //USE_INTERNAL_EDGE_UTILITY
247  m_bodyMap.insert(colObjData, body);
248  }
249  else
250  {
251  printf("error: no shape found\n");
252  }
253  }
254  else
255  {
257  btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
258  if (shapePtr && *shapePtr)
259  {
260  btTransform startTransform;
261  colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
262  startTransform.deSerializeFloat(colObjData->m_worldTransform);
263 
264  btCollisionShape* shape = (btCollisionShape*)*shapePtr;
265  btCollisionObject* body = createCollisionObject(startTransform, shape, colObjData->m_name);
266 
267 #ifdef USE_INTERNAL_EDGE_UTILITY
269  {
271  if (trimesh->getTriangleInfoMap())
272  {
274  }
275  }
276 #endif //USE_INTERNAL_EDGE_UTILITY
277  m_bodyMap.insert(colObjData, body);
278  }
279  else
280  {
281  printf("error: no shape found\n");
282  }
283  }
284  }
285 
286  for (i = 0; i < bulletFile2->m_constraints.size(); i++)
287  {
288  btTypedConstraintData2* constraintData = (btTypedConstraintData2*)bulletFile2->m_constraints[i];
289 
290  btCollisionObject** colAptr = m_bodyMap.find(constraintData->m_rbA);
291  btCollisionObject** colBptr = m_bodyMap.find(constraintData->m_rbB);
292 
293  btRigidBody* rbA = 0;
294  btRigidBody* rbB = 0;
295 
296  if (colAptr)
297  {
298  rbA = btRigidBody::upcast(*colAptr);
299  if (!rbA)
300  rbA = &getFixedBody();
301  }
302  if (colBptr)
303  {
304  rbB = btRigidBody::upcast(*colBptr);
305  if (!rbB)
306  rbB = &getFixedBody();
307  }
308  if (!rbA && !rbB)
309  continue;
310 
311  bool isDoublePrecisionData = (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) != 0;
312 
313  if (isDoublePrecisionData)
314  {
315  if (bulletFile2->getVersion() >= 282)
316  {
318  convertConstraintDouble(dc, rbA, rbB, bulletFile2->getVersion());
319  }
320  else
321  {
322  //double-precision constraints were messed up until 2.82, try to recover data...
323 
324  btTypedConstraintData* oldData = (btTypedConstraintData*)constraintData;
325 
326  convertConstraintBackwardsCompatible281(oldData, rbA, rbB, bulletFile2->getVersion());
327  }
328  }
329  else
330  {
332  convertConstraintFloat(dc, rbA, rbB, bulletFile2->getVersion());
333  }
334  }
335 
336  return true;
337 }
void clear()
Definition: btHashMap.h:461
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:189
btVector3DoubleData m_gravity
const btTriangleInfoMap * getTriangleInfoMap() const
btHashMap< btHashString, btCollisionShape * > m_nameShapeMap
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:274
void convertRigidBodyDouble(btRigidBodyDoubleData *colObjData)
void deSerializeDouble(const struct btVector3DoubleData &dataIn)
Definition: btVector3.h:1311
void convertRigidBodyFloat(btRigidBodyFloatData *colObjData)
btAlignedObjectArray< bStructHandle * > m_constraints
Definition: btBulletFile.h:46
double m_floats[4]
Definition: btVector3.h:1288
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
const Value * find(const Key &key) const
Definition: btHashMap.h:424
The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
btHashMap< btHashPtr, btCollisionObject * > m_bodyMap
The btCollisionShape class provides an interface for collision shapes that can be shared among btColl...
btAlignedObjectArray< bStructHandle * > m_collisionObjects
Definition: btBulletFile.h:42
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:1457
bDNA * getFileDNA()
Definition: bFile.h:115
btVector3FloatData m_gravity
void setRestitution(btScalar rest)
btContactSolverInfoFloatData m_solverInfo
btHashMap< btHashPtr, const char * > m_objectNameMap
The btBvhTriangleMeshShape is a static-triangle mesh shape, it can only be used for fixed/non-moving ...
void preSwap()
Definition: bFile.cpp:544
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
virtual void parse(int verboseMode)
btVector3FloatData m_origin
Definition: btTransform.h:247
void setFriction(btScalar frict)
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
Definition: btRigidBody.h:569
virtual void deSerializeDouble(struct btQuantizedBvhDoubleData &quantizedBvhDoubleData)
virtual btOptimizedBvh * createOptimizedBvh()
acceleration and connectivity structures
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:264
The btRigidBody is the main class for rigid body objects.
Definition: btRigidBody.h:59
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:543
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:537
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:80
int getVersion() const
Definition: bFile.h:156
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:28
virtual bool convertAllObjects(bParse::btBulletFile *file)
void setCollisionFlags(int flags)
btTransformDoubleData m_worldTransform
btAlignedObjectArray< bStructHandle * > m_bvhs
Definition: btBulletFile.h:48
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:44
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
btHashMap< btHashPtr, btCollisionShape * > m_shapeMap
btAlignedObjectArray< bStructHandle * > m_dynamicsWorldInfo
Definition: btBulletFile.h:52
void deSerializeFloat(const struct btVector3FloatData &dataIn)
Definition: btVector3.h:1298
void deSerializeDouble(const struct btTransformDoubleData &dataIn)
Definition: btTransform.h:280
btBulletWorldImporter(btDynamicsWorld *world=0)
btHashMap< btHashPtr, btOptimizedBvh * > m_bvhMap
btAlignedObjectArray< bStructHandle * > m_rigidBodies
Definition: btBulletFile.h:40
btVector3DoubleData m_origin
Definition: btTransform.h:253
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:294
int getFlags() const
Definition: bFile.h:122