diff options
Diffstat (limited to 'thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h')
-rw-r--r-- | thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h | 639 |
1 files changed, 639 insertions, 0 deletions
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h new file mode 100644 index 0000000000..1c1ce43764 --- /dev/null +++ b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h @@ -0,0 +1,639 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef B3_SERIALIZER_H +#define B3_SERIALIZER_H + +#include "Bullet3Common/b3Scalar.h" // has definitions like B3_FORCE_INLINE +#include "Bullet3Common/b3StackAlloc.h" +#include "Bullet3Common/b3HashMap.h" + +#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__) +#include <memory.h> +#endif +#include <string.h> + + + +extern char b3s_bulletDNAstr[]; +extern int b3s_bulletDNAlen; +extern char b3s_bulletDNAstr64[]; +extern int b3s_bulletDNAlen64; + +B3_FORCE_INLINE int b3StrLen(const char* str) +{ + if (!str) + return(0); + int len = 0; + + while (*str != 0) + { + str++; + len++; + } + + return len; +} + + +class b3Chunk +{ +public: + int m_chunkCode; + int m_length; + void *m_oldPtr; + int m_dna_nr; + int m_number; +}; + +enum b3SerializationFlags +{ + B3_SERIALIZE_NO_BVH = 1, + B3_SERIALIZE_NO_TRIANGLEINFOMAP = 2, + B3_SERIALIZE_NO_DUPLICATE_ASSERT = 4 +}; + +class b3Serializer +{ + +public: + + virtual ~b3Serializer() {} + + virtual const unsigned char* getBufferPointer() const = 0; + + virtual int getCurrentBufferSize() const = 0; + + virtual b3Chunk* allocate(size_t size, int numElements) = 0; + + virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0; + + virtual void* findPointer(void* oldPtr) = 0; + + virtual void* getUniquePointer(void*oldPtr) = 0; + + virtual void startSerialization() = 0; + + virtual void finishSerialization() = 0; + + virtual const char* findNameForPointer(const void* ptr) const = 0; + + virtual void registerNameForPointer(const void* ptr, const char* name) = 0; + + virtual void serializeName(const char* ptr) = 0; + + virtual int getSerializationFlags() const = 0; + + virtual void setSerializationFlags(int flags) = 0; + + +}; + + + +#define B3_HEADER_LENGTH 12 +#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +# define B3_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) ) +#else +# define B3_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) ) +#endif + +#define B3_SOFTBODY_CODE B3_MAKE_ID('S','B','D','Y') +#define B3_COLLISIONOBJECT_CODE B3_MAKE_ID('C','O','B','J') +#define B3_RIGIDBODY_CODE B3_MAKE_ID('R','B','D','Y') +#define B3_CONSTRAINT_CODE B3_MAKE_ID('C','O','N','S') +#define B3_BOXSHAPE_CODE B3_MAKE_ID('B','O','X','S') +#define B3_QUANTIZED_BVH_CODE B3_MAKE_ID('Q','B','V','H') +#define B3_TRIANLGE_INFO_MAP B3_MAKE_ID('T','M','A','P') +#define B3_SHAPE_CODE B3_MAKE_ID('S','H','A','P') +#define B3_ARRAY_CODE B3_MAKE_ID('A','R','A','Y') +#define B3_SBMATERIAL_CODE B3_MAKE_ID('S','B','M','T') +#define B3_SBNODE_CODE B3_MAKE_ID('S','B','N','D') +#define B3_DYNAMICSWORLD_CODE B3_MAKE_ID('D','W','L','D') +#define B3_DNA_CODE B3_MAKE_ID('D','N','A','1') + + +struct b3PointerUid +{ + union + { + void* m_ptr; + int m_uniqueIds[2]; + }; +}; + +///The b3DefaultSerializer is the main Bullet serialization class. +///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero. +class b3DefaultSerializer : public b3Serializer +{ + + + b3AlignedObjectArray<char*> mTypes; + b3AlignedObjectArray<short*> mStructs; + b3AlignedObjectArray<short> mTlens; + b3HashMap<b3HashInt, int> mStructReverse; + b3HashMap<b3HashString,int> mTypeLookup; + + + b3HashMap<b3HashPtr,void*> m_chunkP; + + b3HashMap<b3HashPtr,const char*> m_nameMap; + + b3HashMap<b3HashPtr,b3PointerUid> m_uniquePointers; + int m_uniqueIdGenerator; + + int m_totalSize; + unsigned char* m_buffer; + int m_currentSize; + void* m_dna; + int m_dnaLength; + + int m_serializationFlags; + + + b3AlignedObjectArray<b3Chunk*> m_chunkPtrs; + +protected: + + virtual void* findPointer(void* oldPtr) + { + void** ptr = m_chunkP.find(oldPtr); + if (ptr && *ptr) + return *ptr; + return 0; + } + + + + + + void writeDNA() + { + b3Chunk* dnaChunk = allocate(m_dnaLength,1); + memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength); + finalizeChunk(dnaChunk,"DNA1",B3_DNA_CODE, m_dna); + } + + int getReverseType(const char *type) const + { + + b3HashString key(type); + const int* valuePtr = mTypeLookup.find(key); + if (valuePtr) + return *valuePtr; + + return -1; + } + + void initDNA(const char* bdnaOrg,int dnalen) + { + ///was already initialized + if (m_dna) + return; + + int littleEndian= 1; + littleEndian= ((char*)&littleEndian)[0]; + + + m_dna = b3AlignedAlloc(dnalen,16); + memcpy(m_dna,bdnaOrg,dnalen); + m_dnaLength = dnalen; + + int *intPtr=0; + short *shtPtr=0; + char *cp = 0;int dataLen =0; + intPtr = (int*)m_dna; + + /* + SDNA (4 bytes) (magic number) + NAME (4 bytes) + <nr> (4 bytes) amount of names (int) + <string> + <string> + */ + + if (strncmp((const char*)m_dna, "SDNA", 4)==0) + { + // skip ++ NAME + intPtr++; intPtr++; + } + + // Parse names + if (!littleEndian) + *intPtr = b3SwapEndian(*intPtr); + + dataLen = *intPtr; + + intPtr++; + + cp = (char*)intPtr; + int i; + for ( i=0; i<dataLen; i++) + { + + while (*cp)cp++; + cp++; + } + cp = b3AlignPointer(cp,4); + + /* + TYPE (4 bytes) + <nr> amount of types (int) + <string> + <string> + */ + + intPtr = (int*)cp; + b3Assert(strncmp(cp, "TYPE", 4)==0); intPtr++; + + if (!littleEndian) + *intPtr = b3SwapEndian(*intPtr); + + dataLen = *intPtr; + intPtr++; + + + cp = (char*)intPtr; + for (i=0; i<dataLen; i++) + { + mTypes.push_back(cp); + while (*cp)cp++; + cp++; + } + + cp = b3AlignPointer(cp,4); + + + /* + TLEN (4 bytes) + <len> (short) the lengths of types + <len> + */ + + // Parse type lens + intPtr = (int*)cp; + b3Assert(strncmp(cp, "TLEN", 4)==0); intPtr++; + + dataLen = (int)mTypes.size(); + + shtPtr = (short*)intPtr; + for (i=0; i<dataLen; i++, shtPtr++) + { + if (!littleEndian) + shtPtr[0] = b3SwapEndian(shtPtr[0]); + mTlens.push_back(shtPtr[0]); + } + + if (dataLen & 1) shtPtr++; + + /* + STRC (4 bytes) + <nr> amount of structs (int) + <typenr> + <nr_of_elems> + <typenr> + <namenr> + <typenr> + <namenr> + */ + + intPtr = (int*)shtPtr; + cp = (char*)intPtr; + b3Assert(strncmp(cp, "STRC", 4)==0); intPtr++; + + if (!littleEndian) + *intPtr = b3SwapEndian(*intPtr); + dataLen = *intPtr ; + intPtr++; + + + shtPtr = (short*)intPtr; + for (i=0; i<dataLen; i++) + { + mStructs.push_back (shtPtr); + + if (!littleEndian) + { + shtPtr[0]= b3SwapEndian(shtPtr[0]); + shtPtr[1]= b3SwapEndian(shtPtr[1]); + + int len = shtPtr[1]; + shtPtr+= 2; + + for (int a=0; a<len; a++, shtPtr+=2) + { + shtPtr[0]= b3SwapEndian(shtPtr[0]); + shtPtr[1]= b3SwapEndian(shtPtr[1]); + } + + } else + { + shtPtr+= (2*shtPtr[1])+2; + } + } + + // build reverse lookups + for (i=0; i<(int)mStructs.size(); i++) + { + short *strc = mStructs.at(i); + mStructReverse.insert(strc[0], i); + mTypeLookup.insert(b3HashString(mTypes[strc[0]]),i); + } + } + +public: + + + + + b3DefaultSerializer(int totalSize=0) + :m_totalSize(totalSize), + m_currentSize(0), + m_dna(0), + m_dnaLength(0), + m_serializationFlags(0) + { + m_buffer = m_totalSize?(unsigned char*)b3AlignedAlloc(totalSize,16):0; + + const bool VOID_IS_8 = ((sizeof(void*)==8)); + +#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { +#if _WIN64 + initDNA((const char*)b3s_bulletDNAstr64,b3s_bulletDNAlen64); +#else + b3Assert(0); +#endif + } else + { +#ifndef _WIN64 + initDNA((const char*)b3s_bulletDNAstr,b3s_bulletDNAlen); +#else + b3Assert(0); +#endif + } + +#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { + initDNA((const char*)b3s_bulletDNAstr64,b3s_bulletDNAlen64); + } else + { + initDNA((const char*)b3s_bulletDNAstr,b3s_bulletDNAlen); + } +#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + + } + + virtual ~b3DefaultSerializer() + { + if (m_buffer) + b3AlignedFree(m_buffer); + if (m_dna) + b3AlignedFree(m_dna); + } + + void writeHeader(unsigned char* buffer) const + { + + +#ifdef B3_USE_DOUBLE_PRECISION + memcpy(buffer, "BULLETd", 7); +#else + memcpy(buffer, "BULLETf", 7); +#endif //B3_USE_DOUBLE_PRECISION + + int littleEndian= 1; + littleEndian= ((char*)&littleEndian)[0]; + + if (sizeof(void*)==8) + { + buffer[7] = '-'; + } else + { + buffer[7] = '_'; + } + + if (littleEndian) + { + buffer[8]='v'; + } else + { + buffer[8]='V'; + } + + + buffer[9] = '2'; + buffer[10] = '8'; + buffer[11] = '1'; + + } + + virtual void startSerialization() + { + m_uniqueIdGenerator= 1; + if (m_totalSize) + { + unsigned char* buffer = internalAlloc(B3_HEADER_LENGTH); + writeHeader(buffer); + } + + } + + virtual void finishSerialization() + { + writeDNA(); + + //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now + int mysize = 0; + if (!m_totalSize) + { + if (m_buffer) + b3AlignedFree(m_buffer); + + m_currentSize += B3_HEADER_LENGTH; + m_buffer = (unsigned char*)b3AlignedAlloc(m_currentSize,16); + + unsigned char* currentPtr = m_buffer; + writeHeader(m_buffer); + currentPtr += B3_HEADER_LENGTH; + mysize+=B3_HEADER_LENGTH; + for (int i=0;i< m_chunkPtrs.size();i++) + { + int curLength = sizeof(b3Chunk)+m_chunkPtrs[i]->m_length; + memcpy(currentPtr,m_chunkPtrs[i], curLength); + b3AlignedFree(m_chunkPtrs[i]); + currentPtr+=curLength; + mysize+=curLength; + } + } + + mTypes.clear(); + mStructs.clear(); + mTlens.clear(); + mStructReverse.clear(); + mTypeLookup.clear(); + m_chunkP.clear(); + m_nameMap.clear(); + m_uniquePointers.clear(); + m_chunkPtrs.clear(); + } + + virtual void* getUniquePointer(void*oldPtr) + { + if (!oldPtr) + return 0; + + b3PointerUid* uptr = (b3PointerUid*)m_uniquePointers.find(oldPtr); + if (uptr) + { + return uptr->m_ptr; + } + m_uniqueIdGenerator++; + + b3PointerUid uid; + uid.m_uniqueIds[0] = m_uniqueIdGenerator; + uid.m_uniqueIds[1] = m_uniqueIdGenerator; + m_uniquePointers.insert(oldPtr,uid); + return uid.m_ptr; + + } + + virtual const unsigned char* getBufferPointer() const + { + return m_buffer; + } + + virtual int getCurrentBufferSize() const + { + return m_currentSize; + } + + virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode,void* oldPtr) + { + if (!(m_serializationFlags&B3_SERIALIZE_NO_DUPLICATE_ASSERT)) + { + b3Assert(!findPointer(oldPtr)); + } + + chunk->m_dna_nr = getReverseType(structType); + + chunk->m_chunkCode = chunkCode; + + void* uniquePtr = getUniquePointer(oldPtr); + + m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr); + chunk->m_oldPtr = uniquePtr;//oldPtr; + + } + + + virtual unsigned char* internalAlloc(size_t size) + { + unsigned char* ptr = 0; + + if (m_totalSize) + { + ptr = m_buffer+m_currentSize; + m_currentSize += int(size); + b3Assert(m_currentSize<m_totalSize); + } else + { + ptr = (unsigned char*)b3AlignedAlloc(size,16); + m_currentSize += int(size); + } + return ptr; + } + + + + virtual b3Chunk* allocate(size_t size, int numElements) + { + + unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(b3Chunk)); + + unsigned char* data = ptr + sizeof(b3Chunk); + + b3Chunk* chunk = (b3Chunk*)ptr; + chunk->m_chunkCode = 0; + chunk->m_oldPtr = data; + chunk->m_length = int(size)*numElements; + chunk->m_number = numElements; + + m_chunkPtrs.push_back(chunk); + + + return chunk; + } + + virtual const char* findNameForPointer(const void* ptr) const + { + const char*const * namePtr = m_nameMap.find(ptr); + if (namePtr && *namePtr) + return *namePtr; + return 0; + + } + + virtual void registerNameForPointer(const void* ptr, const char* name) + { + m_nameMap.insert(ptr,name); + } + + virtual void serializeName(const char* name) + { + if (name) + { + //don't serialize name twice + if (findPointer((void*)name)) + return; + + int len = b3StrLen(name); + if (len) + { + + int newLen = len+1; + int padding = ((newLen+3)&~3)-newLen; + newLen += padding; + + //serialize name string now + b3Chunk* chunk = allocate(sizeof(char),newLen); + char* destinationName = (char*)chunk->m_oldPtr; + for (int i=0;i<len;i++) + { + destinationName[i] = name[i]; + } + destinationName[len] = 0; + finalizeChunk(chunk,"char",B3_ARRAY_CODE,(void*)name); + } + } + } + + virtual int getSerializationFlags() const + { + return m_serializationFlags; + } + + virtual void setSerializationFlags(int flags) + { + m_serializationFlags = flags; + } + +}; + + +#endif //B3_SERIALIZER_H + |