Bullet Collision Detection & Physics Library
btBulletFile.cpp
Go to the documentation of this file.
1 /*
2 bParse
3 Copyright (c) 2006-2010 Erwin Coumans http://gamekit.googlecode.com
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 "btBulletFile.h"
17 #include "bDefines.h"
18 #include "bDNA.h"
19 
20 #if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
21 #include <memory.h>
22 #endif
23 #include <string.h>
24 
25 // 32 && 64 bit versions
26 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
27 #ifdef _WIN64
28 extern char sBulletDNAstr64[];
29 extern int sBulletDNAlen64;
30 #else
31 extern char sBulletDNAstr[];
32 extern int sBulletDNAlen;
33 #endif //_WIN64
34 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
35 
36 extern char sBulletDNAstr64[];
37 extern int sBulletDNAlen64;
38 extern char sBulletDNAstr[];
39 extern int sBulletDNAlen;
40 
41 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
42 
43 using namespace bParse;
44 
46  : bFile("", "BULLET ")
47 {
48  mMemoryDNA = new bDNA(); //this memory gets released in the bFile::~bFile destructor,@todo not consistent with the rule 'who allocates it, has to deallocate it"
49 
50  m_DnaCopy = 0;
51 
52 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
53 #ifdef _WIN64
57 #else //_WIN64
61 #endif //_WIN64
62 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
63  if (VOID_IS_8)
64  {
68  }
69  else
70  {
74  }
75 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
76 }
77 
78 btBulletFile::btBulletFile(const char* fileName)
79  : bFile(fileName, "BULLET ")
80 {
81  m_DnaCopy = 0;
82 }
83 
84 btBulletFile::btBulletFile(char* memoryBuffer, int len)
85  : bFile(memoryBuffer, len, "BULLET ")
86 {
87  m_DnaCopy = 0;
88 }
89 
91 {
92  if (m_DnaCopy)
94 
95  while (m_dataBlocks.size())
96  {
97  char* dataBlock = m_dataBlocks[m_dataBlocks.size() - 1];
98  delete[] dataBlock;
100  }
101 }
102 
103 // ----------------------------------------------------- //
105 {
106  // printf ("Building datablocks");
107  // printf ("Chunk size = %d",CHUNK_HEADER_LEN);
108  // printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags));
109 
110  const bool brokenDNA = (mFlags & FD_BROKEN_DNA) != 0;
111 
112  //const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0;
113 
114  int remain = mFileLen;
115 
116  mDataStart = 12;
117  remain -= 12;
118 
119  //invalid/empty file?
120  if (remain < sizeof(bChunkInd))
121  return;
122 
123  char* dataPtr = mFileBuffer + mDataStart;
124 
125  bChunkInd dataChunk;
126  dataChunk.code = 0;
127 
128  //dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags);
129  int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
130 
131  if (mFlags & FD_ENDIAN_SWAP)
132  swapLen(dataPtr);
133 
134  //dataPtr += ChunkUtils::getOffset(mFlags);
135  char* dataPtrHead = 0;
136 
137  while (dataChunk.code != DNA1)
138  {
139  if (!brokenDNA || (dataChunk.code != BT_QUANTIZED_BVH_CODE))
140  {
141  // one behind
142  if (dataChunk.code == SDNA) break;
143  //if (dataChunk.code == DNA1) break;
144 
145  // same as (BHEAD+DATA dependency)
146  dataPtrHead = dataPtr + ChunkUtils::getOffset(mFlags);
147  if (dataChunk.dna_nr >= 0)
148  {
149  char* id = readStruct(dataPtrHead, dataChunk);
150 
151  // lookup maps
152  if (id)
153  {
154  m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk);
155  mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id);
156 
157  m_chunks.push_back(dataChunk);
158  // block it
159  //bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code);
160  //if (listID)
161  // listID->push_back((bStructHandle*)id);
162  }
163 
164  if (dataChunk.code == BT_CONTACTMANIFOLD_CODE)
165  {
166  m_contactManifolds.push_back((bStructHandle*)id);
167  }
168  if (dataChunk.code == BT_MULTIBODY_CODE)
169  {
170  m_multiBodies.push_back((bStructHandle*)id);
171  }
172 
173  if (dataChunk.code == BT_MB_LINKCOLLIDER_CODE)
174  {
175  m_multiBodyLinkColliders.push_back((bStructHandle*)id);
176  }
177 
178  if (dataChunk.code == BT_SOFTBODY_CODE)
179  {
180  m_softBodies.push_back((bStructHandle*)id);
181  }
182 
183  if (dataChunk.code == BT_RIGIDBODY_CODE)
184  {
185  m_rigidBodies.push_back((bStructHandle*)id);
186  }
187 
188  if (dataChunk.code == BT_DYNAMICSWORLD_CODE)
189  {
190  m_dynamicsWorldInfo.push_back((bStructHandle*)id);
191  }
192 
193  if (dataChunk.code == BT_CONSTRAINT_CODE)
194  {
195  m_constraints.push_back((bStructHandle*)id);
196  }
197 
198  if (dataChunk.code == BT_QUANTIZED_BVH_CODE)
199  {
200  m_bvhs.push_back((bStructHandle*)id);
201  }
202 
203  if (dataChunk.code == BT_TRIANLGE_INFO_MAP)
204  {
205  m_triangleInfoMaps.push_back((bStructHandle*)id);
206  }
207 
208  if (dataChunk.code == BT_COLLISIONOBJECT_CODE)
209  {
210  m_collisionObjects.push_back((bStructHandle*)id);
211  }
212 
213  if (dataChunk.code == BT_SHAPE_CODE)
214  {
215  m_collisionShapes.push_back((bStructHandle*)id);
216  }
217 
218  // if (dataChunk.code == GLOB)
219  // {
220  // m_glob = (bStructHandle*) id;
221  // }
222  }
223  else
224  {
225  //printf("unknown chunk\n");
226 
227  mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead);
228  }
229  }
230  else
231  {
232  printf("skipping BT_QUANTIZED_BVH_CODE due to broken DNA\n");
233  }
234 
235  dataPtr += seek;
236  remain -= seek;
237  if (remain <= 0)
238  break;
239 
240  seek = getNextBlock(&dataChunk, dataPtr, mFlags);
241  if (mFlags & FD_ENDIAN_SWAP)
242  swapLen(dataPtr);
243 
244  if (seek < 0)
245  break;
246  }
247 }
248 
249 void btBulletFile::addDataBlock(char* dataBlock)
250 {
251  m_dataBlocks.push_back(dataBlock);
252 }
253 
255 {
256  bChunkInd dataChunk;
257  dataChunk.code = DNA1;
258  dataChunk.dna_nr = 0;
259  dataChunk.nr = 1;
260 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
261  if (VOID_IS_8)
262  {
263 #ifdef _WIN64
264  dataChunk.len = sBulletDNAlen64;
265  dataChunk.oldPtr = sBulletDNAstr64;
266  fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
267  fwrite(sBulletDNAstr64, sBulletDNAlen64, 1, fp);
268 #else
269  btAssert(0);
270 #endif
271  }
272  else
273  {
274 #ifndef _WIN64
275  dataChunk.len = sBulletDNAlen;
276  dataChunk.oldPtr = sBulletDNAstr;
277  fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
278  fwrite(sBulletDNAstr, sBulletDNAlen, 1, fp);
279 #else //_WIN64
280  btAssert(0);
281 #endif //_WIN64
282  }
283 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
284  if (VOID_IS_8)
285  {
286  dataChunk.len = sBulletDNAlen64;
287  dataChunk.oldPtr = sBulletDNAstr64;
288  fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
289  fwrite(sBulletDNAstr64, sBulletDNAlen64, 1, fp);
290  }
291  else
292  {
293  dataChunk.len = sBulletDNAlen;
294  dataChunk.oldPtr = sBulletDNAstr;
295  fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
296  fwrite(sBulletDNAstr, sBulletDNAlen, 1, fp);
297  }
298 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
299 }
300 
301 void btBulletFile::parse(int verboseMode)
302 {
303 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
304  if (VOID_IS_8)
305  {
306 #ifdef _WIN64
307 
308  if (m_DnaCopy)
309  delete m_DnaCopy;
312  parseInternal(verboseMode, (char*)sBulletDNAstr64, sBulletDNAlen64);
313 #else
314  btAssert(0);
315 #endif
316  }
317  else
318  {
319 #ifndef _WIN64
320 
321  if (m_DnaCopy)
322  delete m_DnaCopy;
323  m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen, 16);
325  parseInternal(verboseMode, m_DnaCopy, sBulletDNAlen);
326 #else
327  btAssert(0);
328 #endif
329  }
330 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
331  if (VOID_IS_8)
332  {
333  if (m_DnaCopy)
334  delete m_DnaCopy;
336  memset(m_DnaCopy, 0, sBulletDNAlen64);
338  parseInternal(verboseMode, m_DnaCopy, sBulletDNAlen64);
339  }
340  else
341  {
342  if (m_DnaCopy)
343  delete m_DnaCopy;
344  m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen, 16);
346  parseInternal(verboseMode, m_DnaCopy, sBulletDNAlen);
347  }
348 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
349 
350  //the parsing will convert to cpu endian
352 
353  int littleEndian = 1;
354  littleEndian = ((char*)&littleEndian)[0];
355 
356  mFileBuffer[8] = littleEndian ? 'v' : 'V';
357 }
358 
359 // experimental
360 int btBulletFile::write(const char* fileName, bool fixupPointers)
361 {
362  FILE* fp = fopen(fileName, "wb");
363  if (fp)
364  {
365  char header[SIZEOFBLENDERHEADER];
366  memcpy(header, m_headerString, 7);
367  int endian = 1;
368  endian = ((char*)&endian)[0];
369 
370  if (endian)
371  {
372  header[7] = '_';
373  }
374  else
375  {
376  header[7] = '-';
377  }
378  if (VOID_IS_8)
379  {
380  header[8] = 'V';
381  }
382  else
383  {
384  header[8] = 'v';
385  }
386 
387  header[9] = '2';
388  header[10] = '7';
389  header[11] = '5';
390 
391  fwrite(header, SIZEOFBLENDERHEADER, 1, fp);
392 
393  writeChunks(fp, fixupPointers);
394 
395  writeDNA(fp);
396 
397  fclose(fp);
398  }
399  else
400  {
401  printf("Error: cannot open file %s for writing\n", fileName);
402  return 0;
403  }
404  return 1;
405 }
406 
407 void btBulletFile::addStruct(const char* structType, void* data, int len, void* oldPtr, int code)
408 {
409  bParse::bChunkInd dataChunk;
410  dataChunk.code = code;
411  dataChunk.nr = 1;
412  dataChunk.len = len;
413  dataChunk.dna_nr = mMemoryDNA->getReverseType(structType);
414  dataChunk.oldPtr = oldPtr;
415 
417  short* structInfo = mMemoryDNA->getStruct(dataChunk.dna_nr);
418  int elemBytes;
419  elemBytes = mMemoryDNA->getLength(structInfo[0]);
420  // int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]);
421  assert(len == elemBytes);
422 
423  mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data);
424  m_chunks.push_back(dataChunk);
425 }
#define SIZEOFBLENDERHEADER
Definition: bDefines.h:23
#define DNA1
Definition: bDefines.h:101
#define SDNA
Definition: bDefines.h:105
#define btAlignedFree(ptr)
#define btAlignedAlloc(size, alignment)
int sBulletDNAlen64
char sBulletDNAstr[]
Definition: btSerializer.cpp:1
char sBulletDNAstr64[]
int sBulletDNAlen
#define btAssert(x)
Definition: btScalar.h:153
#define BT_COLLISIONOBJECT_CODE
Definition: btSerializer.h:111
#define BT_CONTACTMANIFOLD_CODE
Definition: btSerializer.h:122
#define BT_TRIANLGE_INFO_MAP
Definition: btSerializer.h:116
#define BT_QUANTIZED_BVH_CODE
Definition: btSerializer.h:115
#define BT_RIGIDBODY_CODE
Definition: btSerializer.h:112
#define BT_DYNAMICSWORLD_CODE
Definition: btSerializer.h:121
#define BT_SOFTBODY_CODE
Definition: btSerializer.h:110
#define BT_SHAPE_CODE
Definition: btSerializer.h:117
#define BT_CONSTRAINT_CODE
Definition: btSerializer.h:113
#define BT_MULTIBODY_CODE
Definition: btSerializer.h:108
#define BT_MB_LINKCOLLIDER_CODE
Definition: btSerializer.h:109
static int getOffset(int flags)
Definition: bChunk.cpp:49
void * oldPtr
Definition: bChunk.h:63
short getLength(int ind)
Definition: bDNA.cpp:69
void init(char *data, int len, bool swap=false)
Definition: bDNA.cpp:345
int getReverseType(short type)
Definition: bDNA.cpp:76
short * getStruct(int ind)
Definition: bDNA.cpp:62
int mFileLen
Definition: bFile.h:55
bDNA * mMemoryDNA
Definition: bFile.h:62
virtual void parseInternal(int verboseMode, char *memDna, int memDnaLength)
Definition: bFile.cpp:195
btAlignedObjectArray< bChunkInd > m_chunks
Definition: bFile.h:67
int mDataStart
Definition: bFile.h:60
btHashMap< btHashPtr, bChunkInd > m_chunkPtrPtrMap
Definition: bFile.h:68
char * readStruct(char *head, class bChunkInd &chunk)
Definition: bFile.cpp:619
bPtrMap mLibPointers
Definition: bFile.h:58
virtual void writeChunks(FILE *fp, bool fixupPointers)
Definition: bFile.cpp:1499
char * mFileBuffer
Definition: bFile.h:54
void swapLen(char *dataPtr)
Definition: bFile.cpp:334
int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
Definition: bFile.cpp:1559
char m_headerString[7]
Definition: bFile.h:51
int mFlags
Definition: bFile.h:74
btAlignedObjectArray< bStructHandle * > m_dynamicsWorldInfo
Definition: btBulletFile.h:52
btAlignedObjectArray< bStructHandle * > m_rigidBodies
Definition: btBulletFile.h:40
virtual void parse(int verboseMode)
btAlignedObjectArray< bStructHandle * > m_triangleInfoMaps
Definition: btBulletFile.h:50
btAlignedObjectArray< bStructHandle * > m_bvhs
Definition: btBulletFile.h:48
virtual void addDataBlock(char *dataBlock)
btAlignedObjectArray< bStructHandle * > m_multiBodies
Definition: btBulletFile.h:34
btAlignedObjectArray< bStructHandle * > m_constraints
Definition: btBulletFile.h:46
btAlignedObjectArray< char * > m_dataBlocks
Definition: btBulletFile.h:56
virtual int write(const char *fileName, bool fixupPointers=false)
btAlignedObjectArray< bStructHandle * > m_contactManifolds
Definition: btBulletFile.h:54
virtual void parseData()
btAlignedObjectArray< bStructHandle * > m_collisionObjects
Definition: btBulletFile.h:42
btAlignedObjectArray< bStructHandle * > m_multiBodyLinkColliders
Definition: btBulletFile.h:36
virtual void writeDNA(FILE *fp)
btAlignedObjectArray< bStructHandle * > m_softBodies
Definition: btBulletFile.h:38
btAlignedObjectArray< bStructHandle * > m_collisionShapes
Definition: btBulletFile.h:44
void addStruct(const char *structType, void *data, int len, void *oldPtr, int code)
int size() const
return the number of elements in the array
void push_back(const T &_Val)
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:264
const bool VOID_IS_8
Definition: bChunk.h:81
@ FD_ENDIAN_SWAP
Definition: bFile.h:31
@ FD_BROKEN_DNA
Definition: bFile.h:36