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