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;
337  parseInternal(verboseMode, m_DnaCopy, sBulletDNAlen64);
338  }
339  else
340  {
341  if (m_DnaCopy)
342  delete m_DnaCopy;
343  m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen, 16);
345  parseInternal(verboseMode, m_DnaCopy, sBulletDNAlen);
346  }
347 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
348 
349  //the parsing will convert to cpu endian
351 
352  int littleEndian = 1;
353  littleEndian = ((char*)&littleEndian)[0];
354 
355  mFileBuffer[8] = littleEndian ? 'v' : 'V';
356 }
357 
358 // experimental
359 int btBulletFile::write(const char* fileName, bool fixupPointers)
360 {
361  FILE* fp = fopen(fileName, "wb");
362  if (fp)
363  {
364  char header[SIZEOFBLENDERHEADER];
365  memcpy(header, m_headerString, 7);
366  int endian = 1;
367  endian = ((char*)&endian)[0];
368 
369  if (endian)
370  {
371  header[7] = '_';
372  }
373  else
374  {
375  header[7] = '-';
376  }
377  if (VOID_IS_8)
378  {
379  header[8] = 'V';
380  }
381  else
382  {
383  header[8] = 'v';
384  }
385 
386  header[9] = '2';
387  header[10] = '7';
388  header[11] = '5';
389 
390  fwrite(header, SIZEOFBLENDERHEADER, 1, fp);
391 
392  writeChunks(fp, fixupPointers);
393 
394  writeDNA(fp);
395 
396  fclose(fp);
397  }
398  else
399  {
400  printf("Error: cannot open file %s for writing\n", fileName);
401  return 0;
402  }
403  return 1;
404 }
405 
406 void btBulletFile::addStruct(const char* structType, void* data, int len, void* oldPtr, int code)
407 {
408  bParse::bChunkInd dataChunk;
409  dataChunk.code = code;
410  dataChunk.nr = 1;
411  dataChunk.len = len;
412  dataChunk.dna_nr = mMemoryDNA->getReverseType(structType);
413  dataChunk.oldPtr = oldPtr;
414 
416  short* structInfo = mMemoryDNA->getStruct(dataChunk.dna_nr);
417  int elemBytes;
418  elemBytes = mMemoryDNA->getLength(structInfo[0]);
419  // int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]);
420  assert(len == elemBytes);
421 
422  mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data);
423  m_chunks.push_back(dataChunk);
424 }
#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:194
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:618
bPtrMap mLibPointers
Definition: bFile.h:58
virtual void writeChunks(FILE *fp, bool fixupPointers)
Definition: bFile.cpp:1498
char * mFileBuffer
Definition: bFile.h:54
void swapLen(char *dataPtr)
Definition: bFile.cpp:333
int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
Definition: bFile.cpp:1558
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