00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef BT_SERIALIZER_H
00017 #define BT_SERIALIZER_H
00018
00019 #include "btScalar.h"
00020 #include "btStackAlloc.h"
00021 #include "btHashMap.h"
00022
00023 #if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
00024 #include <memory.h>
00025 #endif
00026 #include <string.h>
00027
00028
00029
00031 extern unsigned char sBulletDNAstr[];
00032 extern int sBulletDNAlen;
00033 extern unsigned char sBulletDNAstr64[];
00034 extern int sBulletDNAlen64;
00035
00036 SIMD_FORCE_INLINE int btStrLen(const char* str)
00037 {
00038 if (!str)
00039 return(0);
00040 int len = 0;
00041
00042 while (*str != 0)
00043 {
00044 str++;
00045 len++;
00046 }
00047
00048 return len;
00049 }
00050
00051
00052 class btChunk
00053 {
00054 public:
00055 int m_chunkCode;
00056 int m_length;
00057 void *m_oldPtr;
00058 int m_dna_nr;
00059 int m_number;
00060 };
00061
00062 enum btSerializationFlags
00063 {
00064 BT_SERIALIZE_NO_BVH = 1,
00065 BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
00066 BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4
00067 };
00068
00069 class btSerializer
00070 {
00071
00072 public:
00073
00074 virtual ~btSerializer() {}
00075
00076 virtual const unsigned char* getBufferPointer() const = 0;
00077
00078 virtual int getCurrentBufferSize() const = 0;
00079
00080 virtual btChunk* allocate(size_t size, int numElements) = 0;
00081
00082 virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
00083
00084 virtual void* findPointer(void* oldPtr) = 0;
00085
00086 virtual void* getUniquePointer(void*oldPtr) = 0;
00087
00088 virtual void startSerialization() = 0;
00089
00090 virtual void finishSerialization() = 0;
00091
00092 virtual const char* findNameForPointer(const void* ptr) const = 0;
00093
00094 virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
00095
00096 virtual void serializeName(const char* ptr) = 0;
00097
00098 virtual int getSerializationFlags() const = 0;
00099
00100 virtual void setSerializationFlags(int flags) = 0;
00101
00102
00103 };
00104
00105
00106
00107 #define BT_HEADER_LENGTH 12
00108 #if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
00109 # define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
00110 #else
00111 # define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
00112 #endif
00113
00114 #define BT_SOFTBODY_CODE MAKE_ID('S','B','D','Y')
00115 #define BT_COLLISIONOBJECT_CODE MAKE_ID('C','O','B','J')
00116 #define BT_RIGIDBODY_CODE MAKE_ID('R','B','D','Y')
00117 #define BT_CONSTRAINT_CODE MAKE_ID('C','O','N','S')
00118 #define BT_BOXSHAPE_CODE MAKE_ID('B','O','X','S')
00119 #define BT_QUANTIZED_BVH_CODE MAKE_ID('Q','B','V','H')
00120 #define BT_TRIANLGE_INFO_MAP MAKE_ID('T','M','A','P')
00121 #define BT_SHAPE_CODE MAKE_ID('S','H','A','P')
00122 #define BT_ARRAY_CODE MAKE_ID('A','R','A','Y')
00123 #define BT_SBMATERIAL_CODE MAKE_ID('S','B','M','T')
00124 #define BT_SBNODE_CODE MAKE_ID('S','B','N','D')
00125 #define BT_DNA_CODE MAKE_ID('D','N','A','1')
00126
00127
00128 struct btPointerUid
00129 {
00130 union
00131 {
00132 void* m_ptr;
00133 int m_uniqueIds[2];
00134 };
00135 };
00136
00139 class btDefaultSerializer : public btSerializer
00140 {
00141
00142
00143 btAlignedObjectArray<char*> mTypes;
00144 btAlignedObjectArray<short*> mStructs;
00145 btAlignedObjectArray<short> mTlens;
00146 btHashMap<btHashInt, int> mStructReverse;
00147 btHashMap<btHashString,int> mTypeLookup;
00148
00149
00150 btHashMap<btHashPtr,void*> m_chunkP;
00151
00152 btHashMap<btHashPtr,const char*> m_nameMap;
00153
00154 btHashMap<btHashPtr,btPointerUid> m_uniquePointers;
00155 int m_uniqueIdGenerator;
00156
00157 int m_totalSize;
00158 unsigned char* m_buffer;
00159 int m_currentSize;
00160 void* m_dna;
00161 int m_dnaLength;
00162
00163 int m_serializationFlags;
00164
00165
00166 btAlignedObjectArray<btChunk*> m_chunkPtrs;
00167
00168 protected:
00169
00170 virtual void* findPointer(void* oldPtr)
00171 {
00172 void** ptr = m_chunkP.find(oldPtr);
00173 if (ptr && *ptr)
00174 return *ptr;
00175 return 0;
00176 }
00177
00178
00179
00180
00181
00182 void writeDNA()
00183 {
00184 btChunk* dnaChunk = allocate(m_dnaLength,1);
00185 memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
00186 finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna);
00187 }
00188
00189 int getReverseType(const char *type) const
00190 {
00191
00192 btHashString key(type);
00193 const int* valuePtr = mTypeLookup.find(key);
00194 if (valuePtr)
00195 return *valuePtr;
00196
00197 return -1;
00198 }
00199
00200 void initDNA(const char* bdnaOrg,int dnalen)
00201 {
00203 if (m_dna)
00204 return;
00205
00206 int littleEndian= 1;
00207 littleEndian= ((char*)&littleEndian)[0];
00208
00209
00210 m_dna = btAlignedAlloc(dnalen,16);
00211 memcpy(m_dna,bdnaOrg,dnalen);
00212 m_dnaLength = dnalen;
00213
00214 int *intPtr=0;
00215 short *shtPtr=0;
00216 char *cp = 0;int dataLen =0;long nr=0;
00217 intPtr = (int*)m_dna;
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 if (strncmp((const char*)m_dna, "SDNA", 4)==0)
00228 {
00229
00230 intPtr++; intPtr++;
00231 }
00232
00233
00234 if (!littleEndian)
00235 *intPtr = btSwapEndian(*intPtr);
00236
00237 dataLen = *intPtr;
00238
00239 intPtr++;
00240
00241 cp = (char*)intPtr;
00242 int i;
00243 for ( i=0; i<dataLen; i++)
00244 {
00245
00246 while (*cp)cp++;
00247 cp++;
00248 }
00249 {
00250 nr= (long)cp;
00251
00252 nr= ((nr+3)&~3)-nr;
00253 while (nr--)
00254 {
00255 cp++;
00256 }
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266 intPtr = (int*)cp;
00267 assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
00268
00269 if (!littleEndian)
00270 *intPtr = btSwapEndian(*intPtr);
00271
00272 dataLen = *intPtr;
00273 intPtr++;
00274
00275
00276 cp = (char*)intPtr;
00277 for (i=0; i<dataLen; i++)
00278 {
00279 mTypes.push_back(cp);
00280 while (*cp)cp++;
00281 cp++;
00282 }
00283
00284 {
00285 nr= (long)cp;
00286
00287 nr= ((nr+3)&~3)-nr;
00288 while (nr--)
00289 {
00290 cp++;
00291 }
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 intPtr = (int*)cp;
00303 assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
00304
00305 dataLen = (int)mTypes.size();
00306
00307 shtPtr = (short*)intPtr;
00308 for (i=0; i<dataLen; i++, shtPtr++)
00309 {
00310 if (!littleEndian)
00311 shtPtr[0] = btSwapEndian(shtPtr[0]);
00312 mTlens.push_back(shtPtr[0]);
00313 }
00314
00315 if (dataLen & 1) shtPtr++;
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 intPtr = (int*)shtPtr;
00329 cp = (char*)intPtr;
00330 assert(strncmp(cp, "STRC", 4)==0); intPtr++;
00331
00332 if (!littleEndian)
00333 *intPtr = btSwapEndian(*intPtr);
00334 dataLen = *intPtr ;
00335 intPtr++;
00336
00337
00338 shtPtr = (short*)intPtr;
00339 for (i=0; i<dataLen; i++)
00340 {
00341 mStructs.push_back (shtPtr);
00342
00343 if (!littleEndian)
00344 {
00345 shtPtr[0]= btSwapEndian(shtPtr[0]);
00346 shtPtr[1]= btSwapEndian(shtPtr[1]);
00347
00348 int len = shtPtr[1];
00349 shtPtr+= 2;
00350
00351 for (int a=0; a<len; a++, shtPtr+=2)
00352 {
00353 shtPtr[0]= btSwapEndian(shtPtr[0]);
00354 shtPtr[1]= btSwapEndian(shtPtr[1]);
00355 }
00356
00357 } else
00358 {
00359 shtPtr+= (2*shtPtr[1])+2;
00360 }
00361 }
00362
00363
00364 for (i=0; i<(int)mStructs.size(); i++)
00365 {
00366 short *strc = mStructs.at(i);
00367 mStructReverse.insert(strc[0], i);
00368 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
00369 }
00370 }
00371
00372 public:
00373
00374
00375
00376
00377 btDefaultSerializer(int totalSize=0)
00378 :m_totalSize(totalSize),
00379 m_currentSize(0),
00380 m_dna(0),
00381 m_dnaLength(0),
00382 m_serializationFlags(0)
00383 {
00384 m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0;
00385
00386 const bool VOID_IS_8 = ((sizeof(void*)==8));
00387
00388 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
00389 if (VOID_IS_8)
00390 {
00391 #if _WIN64
00392 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
00393 #else
00394 btAssert(0);
00395 #endif
00396 } else
00397 {
00398 #ifndef _WIN64
00399 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
00400 #else
00401 btAssert(0);
00402 #endif
00403 }
00404
00405 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
00406 if (VOID_IS_8)
00407 {
00408 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
00409 } else
00410 {
00411 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
00412 }
00413 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
00414
00415 }
00416
00417 virtual ~btDefaultSerializer()
00418 {
00419 if (m_buffer)
00420 btAlignedFree(m_buffer);
00421 if (m_dna)
00422 btAlignedFree(m_dna);
00423 }
00424
00425 void writeHeader(unsigned char* buffer) const
00426 {
00427
00428
00429 #ifdef BT_USE_DOUBLE_PRECISION
00430 memcpy(buffer, "BULLETd", 7);
00431 #else
00432 memcpy(buffer, "BULLETf", 7);
00433 #endif //BT_USE_DOUBLE_PRECISION
00434
00435 int littleEndian= 1;
00436 littleEndian= ((char*)&littleEndian)[0];
00437
00438 if (sizeof(void*)==8)
00439 {
00440 buffer[7] = '-';
00441 } else
00442 {
00443 buffer[7] = '_';
00444 }
00445
00446 if (littleEndian)
00447 {
00448 buffer[8]='v';
00449 } else
00450 {
00451 buffer[8]='V';
00452 }
00453
00454
00455 buffer[9] = '2';
00456 buffer[10] = '7';
00457 buffer[11] = '8';
00458
00459 }
00460
00461 virtual void startSerialization()
00462 {
00463 m_uniqueIdGenerator= 1;
00464 if (m_totalSize)
00465 {
00466 unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
00467 writeHeader(buffer);
00468 }
00469
00470 }
00471
00472 virtual void finishSerialization()
00473 {
00474 writeDNA();
00475
00476
00477 int mysize = 0;
00478 if (!m_totalSize)
00479 {
00480 if (m_buffer)
00481 btAlignedFree(m_buffer);
00482
00483 m_currentSize += BT_HEADER_LENGTH;
00484 m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize,16);
00485
00486 unsigned char* currentPtr = m_buffer;
00487 writeHeader(m_buffer);
00488 currentPtr += BT_HEADER_LENGTH;
00489 mysize+=BT_HEADER_LENGTH;
00490 for (int i=0;i< m_chunkPtrs.size();i++)
00491 {
00492 int curLength = sizeof(btChunk)+m_chunkPtrs[i]->m_length;
00493 memcpy(currentPtr,m_chunkPtrs[i], curLength);
00494 btAlignedFree(m_chunkPtrs[i]);
00495 currentPtr+=curLength;
00496 mysize+=curLength;
00497 }
00498 }
00499
00500 mTypes.clear();
00501 mStructs.clear();
00502 mTlens.clear();
00503 mStructReverse.clear();
00504 mTypeLookup.clear();
00505 m_chunkP.clear();
00506 m_nameMap.clear();
00507 m_uniquePointers.clear();
00508 m_chunkPtrs.clear();
00509 }
00510
00511 virtual void* getUniquePointer(void*oldPtr)
00512 {
00513 if (!oldPtr)
00514 return 0;
00515
00516 btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
00517 if (uptr)
00518 {
00519 return uptr->m_ptr;
00520 }
00521 m_uniqueIdGenerator++;
00522
00523 btPointerUid uid;
00524 uid.m_uniqueIds[0] = m_uniqueIdGenerator;
00525 uid.m_uniqueIds[1] = m_uniqueIdGenerator;
00526 m_uniquePointers.insert(oldPtr,uid);
00527 return uid.m_ptr;
00528
00529 }
00530
00531 virtual const unsigned char* getBufferPointer() const
00532 {
00533 return m_buffer;
00534 }
00535
00536 virtual int getCurrentBufferSize() const
00537 {
00538 return m_currentSize;
00539 }
00540
00541 virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
00542 {
00543 if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
00544 {
00545 btAssert(!findPointer(oldPtr));
00546 }
00547
00548 chunk->m_dna_nr = getReverseType(structType);
00549
00550 chunk->m_chunkCode = chunkCode;
00551
00552 void* uniquePtr = getUniquePointer(oldPtr);
00553
00554 m_chunkP.insert(oldPtr,uniquePtr);
00555 chunk->m_oldPtr = uniquePtr;
00556
00557 }
00558
00559
00560 virtual unsigned char* internalAlloc(size_t size)
00561 {
00562 unsigned char* ptr = 0;
00563
00564 if (m_totalSize)
00565 {
00566 ptr = m_buffer+m_currentSize;
00567 m_currentSize += int(size);
00568 btAssert(m_currentSize<m_totalSize);
00569 } else
00570 {
00571 ptr = (unsigned char*)btAlignedAlloc(size,16);
00572 m_currentSize += int(size);
00573 }
00574 return ptr;
00575 }
00576
00577
00578
00579 virtual btChunk* allocate(size_t size, int numElements)
00580 {
00581
00582 unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(btChunk));
00583
00584 unsigned char* data = ptr + sizeof(btChunk);
00585
00586 btChunk* chunk = (btChunk*)ptr;
00587 chunk->m_chunkCode = 0;
00588 chunk->m_oldPtr = data;
00589 chunk->m_length = int(size)*numElements;
00590 chunk->m_number = numElements;
00591
00592 m_chunkPtrs.push_back(chunk);
00593
00594
00595 return chunk;
00596 }
00597
00598 virtual const char* findNameForPointer(const void* ptr) const
00599 {
00600 const char*const * namePtr = m_nameMap.find(ptr);
00601 if (namePtr && *namePtr)
00602 return *namePtr;
00603 return 0;
00604
00605 }
00606
00607 virtual void registerNameForPointer(const void* ptr, const char* name)
00608 {
00609 m_nameMap.insert(ptr,name);
00610 }
00611
00612 virtual void serializeName(const char* name)
00613 {
00614 if (name)
00615 {
00616
00617 if (findPointer((void*)name))
00618 return;
00619
00620 int len = btStrLen(name);
00621 if (len)
00622 {
00623
00624 int newLen = len+1;
00625 int padding = ((newLen+3)&~3)-newLen;
00626 newLen += padding;
00627
00628
00629 btChunk* chunk = allocate(sizeof(char),newLen);
00630 char* destinationName = (char*)chunk->m_oldPtr;
00631 for (int i=0;i<len;i++)
00632 {
00633 destinationName[i] = name[i];
00634 }
00635 destinationName[len] = 0;
00636 finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
00637 }
00638 }
00639 }
00640
00641 virtual int getSerializationFlags() const
00642 {
00643 return m_serializationFlags;
00644 }
00645
00646 virtual void setSerializationFlags(int flags)
00647 {
00648 m_serializationFlags = flags;
00649 }
00650
00651 };
00652
00653
00654 #endif //BT_SERIALIZER_H
00655