Bullet Collision Detection & Physics Library
btBulletWorldImporter.cpp
Go to the documentation of this file.
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
17#include "../BulletFileLoader/btBulletFile.h"
18
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
38bool 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
58bool 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{
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 {
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 {
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}
@ TRIANGLE_MESH_SHAPE_PROXYTYPE
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
#define btTypedConstraintData2
void writeFile(const char *fileName)
Definition: bFile.cpp:538
void dumpChunks(bDNA *dna)
Definition: bFile.cpp:1458
int getFlags() const
Definition: bFile.h:122
bDNA * getFileDNA()
Definition: bFile.h:115
int getVersion() const
Definition: bFile.h:156
void preSwap()
Definition: bFile.cpp:545
btAlignedObjectArray< bStructHandle * > m_dynamicsWorldInfo
Definition: btBulletFile.h:52
btAlignedObjectArray< bStructHandle * > m_rigidBodies
Definition: btBulletFile.h:40
virtual void parse(int verboseMode)
btAlignedObjectArray< bStructHandle * > m_bvhs
Definition: btBulletFile.h:48
btAlignedObjectArray< bStructHandle * > m_constraints
Definition: btBulletFile.h:46
btAlignedObjectArray< bStructHandle * > m_collisionObjects
Definition: btBulletFile.h:42
btAlignedObjectArray< bStructHandle * > m_collisionShapes
Definition: btBulletFile.h:44
int size() const
return the number of elements in the array
bool loadFileFromMemory(char *memoryBuffer, int len)
the memoryBuffer might be modified (for example if endian swaps are necessary)
btBulletWorldImporter(btDynamicsWorld *world=0)
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-...
virtual bool convertAllObjects(bParse::btBulletFile *file)
The btBvhTriangleMeshShape is a static-triangle mesh shape, it can only be used for fixed/non-moving ...
const btTriangleInfoMap * getTriangleInfoMap() const
btCollisionObject can be used to manage collision detection objects.
void setRestitution(btScalar rest)
void setCollisionFlags(int flags)
void setFriction(btScalar frict)
int getCollisionFlags() const
The btCollisionShape class provides an interface for collision shapes that can be shared among btColl...
int getShapeType() const
The btDynamicsWorld is the interface class for several dynamics implementation, basic,...
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:264
void clear()
Definition: btHashMap.h:461
const Value * find(const Key &key) const
Definition: btHashMap.h:424
The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes,...
virtual void deSerializeFloat(struct btQuantizedBvhFloatData &quantizedBvhFloatData)
virtual void deSerializeDouble(struct btQuantizedBvhDoubleData &quantizedBvhDoubleData)
The btRigidBody is the main class for rigid body objects.
Definition: btRigidBody.h:60
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:189
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:30
void deSerializeFloat(const struct btTransformFloatData &dataIn)
Definition: btTransform.h:275
void deSerializeDouble(const struct btTransformDoubleData &dataIn)
Definition: btTransform.h:281
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:82
void deSerializeFloat(const struct btVector3FloatData &dataIn)
Definition: btVector3.h:1298
void deSerializeDouble(const struct btVector3DoubleData &dataIn)
Definition: btVector3.h:1311
char * duplicateName(const char *name)
virtual btCollisionObject * createCollisionObject(const btTransform &startTransform, btCollisionShape *shape, const char *bodyName)
static btRigidBody & getFixedBody()
virtual btOptimizedBvh * createOptimizedBvh()
acceleration and connectivity structures
void convertConstraintBackwardsCompatible281(btTypedConstraintData *constraintData, btRigidBody *rbA, btRigidBody *rbB, int fileVersion)
btHashMap< btHashPtr, btOptimizedBvh * > m_bvhMap
void convertConstraintDouble(btTypedConstraintDoubleData *constraintData, btRigidBody *rbA, btRigidBody *rbB, int fileVersion)
virtual void setDynamicsWorldInfo(const btVector3 &gravity, const btContactSolverInfo &solverInfo)
those virtuals are called by load and can be overridden by the user
void convertConstraintFloat(btTypedConstraintFloatData *constraintData, btRigidBody *rbA, btRigidBody *rbB, int fileVersion)
btHashMap< btHashString, btCollisionShape * > m_nameShapeMap
btHashMap< btHashPtr, btCollisionShape * > m_shapeMap
btCollisionShape * convertCollisionShape(btCollisionShapeData *shapeData)
void convertRigidBodyDouble(btRigidBodyDoubleData *colObjData)
void convertRigidBodyFloat(btRigidBodyFloatData *colObjData)
btHashMap< btHashPtr, btCollisionObject * > m_bodyMap
btHashMap< btHashPtr, const char * > m_objectNameMap
@ FD_OK
Definition: bFile.h:29
@ FD_DOUBLE_PRECISION
Definition: bFile.h:35
@ FD_VERBOSE_DUMP_CHUNKS
Definition: bFile.h:44
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
btTransformDoubleData m_worldTransform
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
btTransformFloatData m_worldTransform
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
double m_singleAxisRollingFrictionThreshold
it is only used for 'explicit' version of gyroscopic force
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
btContactSolverInfoDoubleData m_solverInfo
btVector3DoubleData m_gravity
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
btVector3FloatData m_gravity
btContactSolverInfoFloatData m_solverInfo
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
Definition: btRigidBody.h:662
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
Definition: btRigidBody.h:636
btVector3DoubleData m_origin
Definition: btTransform.h:254
btVector3FloatData m_origin
Definition: btTransform.h:248
this structure is not used, except for loading pre-2.82 .bullet files
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
double m_floats[4]
Definition: btVector3.h:1288