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