2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
16 #ifndef BT_SERIALIZER_H
17 #define BT_SERIALIZER_H
19 #include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
20 #include "btStackAlloc.h"
21 #include "btHashMap.h"
23 #if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
30 ///only the 32bit versions for now
31 extern char sBulletDNAstr[];
32 extern int sBulletDNAlen;
33 extern char sBulletDNAstr64[];
34 extern int sBulletDNAlen64;
36 SIMD_FORCE_INLINE int btStrLen(const char* str)
62 enum btSerializationFlags
64 BT_SERIALIZE_NO_BVH = 1,
65 BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
66 BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4
74 virtual ~btSerializer() {}
76 virtual const unsigned char* getBufferPointer() const = 0;
78 virtual int getCurrentBufferSize() const = 0;
80 virtual btChunk* allocate(size_t size, int numElements) = 0;
82 virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
84 virtual void* findPointer(void* oldPtr) = 0;
86 virtual void* getUniquePointer(void*oldPtr) = 0;
88 virtual void startSerialization() = 0;
90 virtual void finishSerialization() = 0;
92 virtual const char* findNameForPointer(const void* ptr) const = 0;
94 virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
96 virtual void serializeName(const char* ptr) = 0;
98 virtual int getSerializationFlags() const = 0;
100 virtual void setSerializationFlags(int flags) = 0;
107 #define BT_HEADER_LENGTH 12
108 #if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
109 # define BT_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
111 # define BT_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
114 #define BT_SOFTBODY_CODE BT_MAKE_ID('S','B','D','Y')
115 #define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C','O','B','J')
116 #define BT_RIGIDBODY_CODE BT_MAKE_ID('R','B','D','Y')
117 #define BT_CONSTRAINT_CODE BT_MAKE_ID('C','O','N','S')
118 #define BT_BOXSHAPE_CODE BT_MAKE_ID('B','O','X','S')
119 #define BT_QUANTIZED_BVH_CODE BT_MAKE_ID('Q','B','V','H')
120 #define BT_TRIANLGE_INFO_MAP BT_MAKE_ID('T','M','A','P')
121 #define BT_SHAPE_CODE BT_MAKE_ID('S','H','A','P')
122 #define BT_ARRAY_CODE BT_MAKE_ID('A','R','A','Y')
123 #define BT_SBMATERIAL_CODE BT_MAKE_ID('S','B','M','T')
124 #define BT_SBNODE_CODE BT_MAKE_ID('S','B','N','D')
125 #define BT_DYNAMICSWORLD_CODE BT_MAKE_ID('D','W','L','D')
126 #define BT_DNA_CODE BT_MAKE_ID('D','N','A','1')
138 ///The btDefaultSerializer is the main Bullet serialization class.
139 ///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
140 class btDefaultSerializer : public btSerializer
144 btAlignedObjectArray<char*> mTypes;
145 btAlignedObjectArray<short*> mStructs;
146 btAlignedObjectArray<short> mTlens;
147 btHashMap<btHashInt, int> mStructReverse;
148 btHashMap<btHashString,int> mTypeLookup;
151 btHashMap<btHashPtr,void*> m_chunkP;
153 btHashMap<btHashPtr,const char*> m_nameMap;
155 btHashMap<btHashPtr,btPointerUid> m_uniquePointers;
156 int m_uniqueIdGenerator;
159 unsigned char* m_buffer;
164 int m_serializationFlags;
167 btAlignedObjectArray<btChunk*> m_chunkPtrs;
171 virtual void* findPointer(void* oldPtr)
173 void** ptr = m_chunkP.find(oldPtr);
185 btChunk* dnaChunk = allocate(m_dnaLength,1);
186 memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
187 finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna);
190 int getReverseType(const char *type) const
193 btHashString key(type);
194 const int* valuePtr = mTypeLookup.find(key);
201 void initDNA(const char* bdnaOrg,int dnalen)
203 ///was already initialized
208 littleEndian= ((char*)&littleEndian)[0];
211 m_dna = btAlignedAlloc(dnalen,16);
212 memcpy(m_dna,bdnaOrg,dnalen);
213 m_dnaLength = dnalen;
217 char *cp = 0;int dataLen =0;
218 intPtr = (int*)m_dna;
221 SDNA (4 bytes) (magic number)
223 <nr> (4 bytes) amount of names (int)
228 if (strncmp((const char*)m_dna, "SDNA", 4)==0)
236 *intPtr = btSwapEndian(*intPtr);
244 for ( i=0; i<dataLen; i++)
250 cp = btAlignPointer(cp,4);
254 <nr> amount of types (int)
260 btAssert(strncmp(cp, "TYPE", 4)==0); intPtr++;
263 *intPtr = btSwapEndian(*intPtr);
270 for (i=0; i<dataLen; i++)
272 mTypes.push_back(cp);
277 cp = btAlignPointer(cp,4);
282 <len> (short) the lengths of types
288 btAssert(strncmp(cp, "TLEN", 4)==0); intPtr++;
290 dataLen = (int)mTypes.size();
292 shtPtr = (short*)intPtr;
293 for (i=0; i<dataLen; i++, shtPtr++)
296 shtPtr[0] = btSwapEndian(shtPtr[0]);
297 mTlens.push_back(shtPtr[0]);
300 if (dataLen & 1) shtPtr++;
304 <nr> amount of structs (int)
313 intPtr = (int*)shtPtr;
315 btAssert(strncmp(cp, "STRC", 4)==0); intPtr++;
318 *intPtr = btSwapEndian(*intPtr);
323 shtPtr = (short*)intPtr;
324 for (i=0; i<dataLen; i++)
326 mStructs.push_back (shtPtr);
330 shtPtr[0]= btSwapEndian(shtPtr[0]);
331 shtPtr[1]= btSwapEndian(shtPtr[1]);
336 for (int a=0; a<len; a++, shtPtr+=2)
338 shtPtr[0]= btSwapEndian(shtPtr[0]);
339 shtPtr[1]= btSwapEndian(shtPtr[1]);
344 shtPtr+= (2*shtPtr[1])+2;
348 // build reverse lookups
349 for (i=0; i<(int)mStructs.size(); i++)
351 short *strc = mStructs.at(i);
352 mStructReverse.insert(strc[0], i);
353 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
362 btDefaultSerializer(int totalSize=0)
363 :m_totalSize(totalSize),
367 m_serializationFlags(0)
369 m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0;
371 const bool VOID_IS_8 = ((sizeof(void*)==8));
373 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
377 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
384 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
390 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
393 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
396 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
398 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
402 virtual ~btDefaultSerializer()
405 btAlignedFree(m_buffer);
407 btAlignedFree(m_dna);
410 void writeHeader(unsigned char* buffer) const
414 #ifdef BT_USE_DOUBLE_PRECISION
415 memcpy(buffer, "BULLETd", 7);
417 memcpy(buffer, "BULLETf", 7);
418 #endif //BT_USE_DOUBLE_PRECISION
421 littleEndian= ((char*)&littleEndian)[0];
423 if (sizeof(void*)==8)
446 virtual void startSerialization()
448 m_uniqueIdGenerator= 1;
451 unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
457 virtual void finishSerialization()
461 //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
466 btAlignedFree(m_buffer);
468 m_currentSize += BT_HEADER_LENGTH;
469 m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize,16);
471 unsigned char* currentPtr = m_buffer;
472 writeHeader(m_buffer);
473 currentPtr += BT_HEADER_LENGTH;
474 mysize+=BT_HEADER_LENGTH;
475 for (int i=0;i< m_chunkPtrs.size();i++)
477 int curLength = sizeof(btChunk)+m_chunkPtrs[i]->m_length;
478 memcpy(currentPtr,m_chunkPtrs[i], curLength);
479 btAlignedFree(m_chunkPtrs[i]);
480 currentPtr+=curLength;
488 mStructReverse.clear();
492 m_uniquePointers.clear();
496 virtual void* getUniquePointer(void*oldPtr)
501 btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
506 m_uniqueIdGenerator++;
509 uid.m_uniqueIds[0] = m_uniqueIdGenerator;
510 uid.m_uniqueIds[1] = m_uniqueIdGenerator;
511 m_uniquePointers.insert(oldPtr,uid);
516 virtual const unsigned char* getBufferPointer() const
521 virtual int getCurrentBufferSize() const
523 return m_currentSize;
526 virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
528 if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
530 btAssert(!findPointer(oldPtr));
533 chunk->m_dna_nr = getReverseType(structType);
535 chunk->m_chunkCode = chunkCode;
537 void* uniquePtr = getUniquePointer(oldPtr);
539 m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
540 chunk->m_oldPtr = uniquePtr;//oldPtr;
545 virtual unsigned char* internalAlloc(size_t size)
547 unsigned char* ptr = 0;
551 ptr = m_buffer+m_currentSize;
552 m_currentSize += int(size);
553 btAssert(m_currentSize<m_totalSize);
556 ptr = (unsigned char*)btAlignedAlloc(size,16);
557 m_currentSize += int(size);
564 virtual btChunk* allocate(size_t size, int numElements)
567 unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(btChunk));
569 unsigned char* data = ptr + sizeof(btChunk);
571 btChunk* chunk = (btChunk*)ptr;
572 chunk->m_chunkCode = 0;
573 chunk->m_oldPtr = data;
574 chunk->m_length = int(size)*numElements;
575 chunk->m_number = numElements;
577 m_chunkPtrs.push_back(chunk);
583 virtual const char* findNameForPointer(const void* ptr) const
585 const char*const * namePtr = m_nameMap.find(ptr);
586 if (namePtr && *namePtr)
592 virtual void registerNameForPointer(const void* ptr, const char* name)
594 m_nameMap.insert(ptr,name);
597 virtual void serializeName(const char* name)
601 //don't serialize name twice
602 if (findPointer((void*)name))
605 int len = btStrLen(name);
610 int padding = ((newLen+3)&~3)-newLen;
613 //serialize name string now
614 btChunk* chunk = allocate(sizeof(char),newLen);
615 char* destinationName = (char*)chunk->m_oldPtr;
616 for (int i=0;i<len;i++)
618 destinationName[i] = name[i];
620 destinationName[len] = 0;
621 finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
626 virtual int getSerializationFlags() const
628 return m_serializationFlags;
631 virtual void setSerializationFlags(int flags)
633 m_serializationFlags = flags;
639 #endif //BT_SERIALIZER_H