Blender V2.61 - r43446
|
00001 /* 00002 Bullet Continuous Collision Detection and Physics Library 00003 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org 00004 00005 This software is provided 'as-is', without any express or implied warranty. 00006 In no event will the authors be held liable for any damages arising from the use of this software. 00007 Permission is granted to anyone to use this software for any purpose, 00008 including commercial applications, and to alter it and redistribute it freely, 00009 subject to the following restrictions: 00010 00011 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. 00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 00013 3. This notice may not be removed or altered from any source distribution. 00014 */ 00015 00016 #ifndef BT_SERIALIZER_H 00017 #define BT_SERIALIZER_H 00018 00019 #include "btScalar.h" // has definitions like SIMD_FORCE_INLINE 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 SDNA (4 bytes) (magic number) 00221 NAME (4 bytes) 00222 <nr> (4 bytes) amount of names (int) 00223 <string> 00224 <string> 00225 */ 00226 00227 if (strncmp((const char*)m_dna, "SDNA", 4)==0) 00228 { 00229 // skip ++ NAME 00230 intPtr++; intPtr++; 00231 } 00232 00233 // Parse names 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 // long mask=3; 00252 nr= ((nr+3)&~3)-nr; 00253 while (nr--) 00254 { 00255 cp++; 00256 } 00257 } 00258 00259 /* 00260 TYPE (4 bytes) 00261 <nr> amount of types (int) 00262 <string> 00263 <string> 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 // long mask=3; 00287 nr= ((nr+3)&~3)-nr; 00288 while (nr--) 00289 { 00290 cp++; 00291 } 00292 } 00293 00294 00295 /* 00296 TLEN (4 bytes) 00297 <len> (short) the lengths of types 00298 <len> 00299 */ 00300 00301 // Parse type lens 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 STRC (4 bytes) 00319 <nr> amount of structs (int) 00320 <typenr> 00321 <nr_of_elems> 00322 <typenr> 00323 <namenr> 00324 <typenr> 00325 <namenr> 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 // build reverse lookups 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 //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now 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);//chunk->m_oldPtr); 00555 chunk->m_oldPtr = uniquePtr;//oldPtr; 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 //don't serialize name twice 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 //serialize name string now 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