Blender V2.61 - r43446

btSerializer.h

Go to the documentation of this file.
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