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