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 "btHashMap.h"
22 #if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
27 extern char sBulletDNAstr[];
28 extern int sBulletDNAlen;
29 extern char sBulletDNAstr64[];
30 extern int sBulletDNAlen64;
32 SIMD_FORCE_INLINE int btStrLen(const char* str)
57 enum btSerializationFlags
59 BT_SERIALIZE_NO_BVH = 1,
60 BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
61 BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4,
62 BT_SERIALIZE_CONTACT_MANIFOLDS = 8,
68 virtual ~btSerializer() {}
70 virtual const unsigned char* getBufferPointer() const = 0;
72 virtual int getCurrentBufferSize() const = 0;
74 virtual btChunk* allocate(size_t size, int numElements) = 0;
76 virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr) = 0;
78 virtual void* findPointer(void* oldPtr) = 0;
80 virtual void* getUniquePointer(void* oldPtr) = 0;
82 virtual void startSerialization() = 0;
84 virtual void finishSerialization() = 0;
86 virtual const char* findNameForPointer(const void* ptr) const = 0;
88 virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
90 virtual void serializeName(const char* ptr) = 0;
92 virtual int getSerializationFlags() const = 0;
94 virtual void setSerializationFlags(int flags) = 0;
96 virtual int getNumChunks() const = 0;
98 virtual const btChunk* getChunk(int chunkIndex) const = 0;
101 #define BT_HEADER_LENGTH 12
102 #if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
103 #define BT_MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
105 #define BT_MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
108 #define BT_MULTIBODY_CODE BT_MAKE_ID('M', 'B', 'D', 'Y')
109 #define BT_MB_LINKCOLLIDER_CODE BT_MAKE_ID('M', 'B', 'L', 'C')
110 #define BT_SOFTBODY_CODE BT_MAKE_ID('S', 'B', 'D', 'Y')
111 #define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C', 'O', 'B', 'J')
112 #define BT_RIGIDBODY_CODE BT_MAKE_ID('R', 'B', 'D', 'Y')
113 #define BT_CONSTRAINT_CODE BT_MAKE_ID('C', 'O', 'N', 'S')
114 #define BT_BOXSHAPE_CODE BT_MAKE_ID('B', 'O', 'X', 'S')
115 #define BT_QUANTIZED_BVH_CODE BT_MAKE_ID('Q', 'B', 'V', 'H')
116 #define BT_TRIANLGE_INFO_MAP BT_MAKE_ID('T', 'M', 'A', 'P')
117 #define BT_SHAPE_CODE BT_MAKE_ID('S', 'H', 'A', 'P')
118 #define BT_ARRAY_CODE BT_MAKE_ID('A', 'R', 'A', 'Y')
119 #define BT_SBMATERIAL_CODE BT_MAKE_ID('S', 'B', 'M', 'T')
120 #define BT_SBNODE_CODE BT_MAKE_ID('S', 'B', 'N', 'D')
121 #define BT_DYNAMICSWORLD_CODE BT_MAKE_ID('D', 'W', 'L', 'D')
122 #define BT_CONTACTMANIFOLD_CODE BT_MAKE_ID('C', 'O', 'N', 'T')
123 #define BT_DNA_CODE BT_MAKE_ID('D', 'N', 'A', '1')
133 struct btBulletSerializedArrays
135 btBulletSerializedArrays()
138 btAlignedObjectArray<struct btQuantizedBvhDoubleData*> m_bvhsDouble;
139 btAlignedObjectArray<struct btQuantizedBvhFloatData*> m_bvhsFloat;
140 btAlignedObjectArray<struct btCollisionShapeData*> m_colShapeData;
141 btAlignedObjectArray<struct btDynamicsWorldDoubleData*> m_dynamicWorldInfoDataDouble;
142 btAlignedObjectArray<struct btDynamicsWorldFloatData*> m_dynamicWorldInfoDataFloat;
143 btAlignedObjectArray<struct btRigidBodyDoubleData*> m_rigidBodyDataDouble;
144 btAlignedObjectArray<struct btRigidBodyFloatData*> m_rigidBodyDataFloat;
145 btAlignedObjectArray<struct btCollisionObjectDoubleData*> m_collisionObjectDataDouble;
146 btAlignedObjectArray<struct btCollisionObjectFloatData*> m_collisionObjectDataFloat;
147 btAlignedObjectArray<struct btTypedConstraintFloatData*> m_constraintDataFloat;
148 btAlignedObjectArray<struct btTypedConstraintDoubleData*> m_constraintDataDouble;
149 btAlignedObjectArray<struct btTypedConstraintData*> m_constraintData; //for backwards compatibility
150 btAlignedObjectArray<struct btSoftBodyFloatData*> m_softBodyFloatData;
151 btAlignedObjectArray<struct btSoftBodyDoubleData*> m_softBodyDoubleData;
154 ///The btDefaultSerializer is the main Bullet serialization class.
155 ///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
156 class btDefaultSerializer : public btSerializer
159 btAlignedObjectArray<char*> mTypes;
160 btAlignedObjectArray<short*> mStructs;
161 btAlignedObjectArray<short> mTlens;
162 btHashMap<btHashInt, int> mStructReverse;
163 btHashMap<btHashString, int> mTypeLookup;
165 btHashMap<btHashPtr, void*> m_chunkP;
167 btHashMap<btHashPtr, const char*> m_nameMap;
169 btHashMap<btHashPtr, btPointerUid> m_uniquePointers;
170 int m_uniqueIdGenerator;
173 unsigned char* m_buffer;
179 int m_serializationFlags;
181 btAlignedObjectArray<btChunk*> m_chunkPtrs;
184 virtual void* findPointer(void* oldPtr)
186 void** ptr = m_chunkP.find(oldPtr);
192 virtual void writeDNA()
194 btChunk* dnaChunk = allocate(m_dnaLength, 1);
195 memcpy(dnaChunk->m_oldPtr, m_dna, m_dnaLength);
196 finalizeChunk(dnaChunk, "DNA1", BT_DNA_CODE, m_dna);
199 int getReverseType(const char* type) const
201 btHashString key(type);
202 const int* valuePtr = mTypeLookup.find(key);
209 void initDNA(const char* bdnaOrg, int dnalen)
211 ///was already initialized
215 int littleEndian = 1;
216 littleEndian = ((char*)&littleEndian)[0];
218 m_dna = btAlignedAlloc(dnalen, 16);
219 memcpy(m_dna, bdnaOrg, dnalen);
220 m_dnaLength = dnalen;
226 intPtr = (int*)m_dna;
229 SDNA (4 bytes) (magic number)
231 <nr> (4 bytes) amount of names (int)
236 if (strncmp((const char*)m_dna, "SDNA", 4) == 0)
245 *intPtr = btSwapEndian(*intPtr);
253 for (i = 0; i < dataLen; i++)
258 cp = btAlignPointer(cp, 4);
262 <nr> amount of types (int)
268 btAssert(strncmp(cp, "TYPE", 4) == 0);
272 *intPtr = btSwapEndian(*intPtr);
278 for (i = 0; i < dataLen; i++)
280 mTypes.push_back(cp);
285 cp = btAlignPointer(cp, 4);
289 <len> (short) the lengths of types
295 btAssert(strncmp(cp, "TLEN", 4) == 0);
298 dataLen = (int)mTypes.size();
300 shtPtr = (short*)intPtr;
301 for (i = 0; i < dataLen; i++, shtPtr++)
304 shtPtr[0] = btSwapEndian(shtPtr[0]);
305 mTlens.push_back(shtPtr[0]);
308 if (dataLen & 1) shtPtr++;
312 <nr> amount of structs (int)
321 intPtr = (int*)shtPtr;
323 btAssert(strncmp(cp, "STRC", 4) == 0);
327 *intPtr = btSwapEndian(*intPtr);
331 shtPtr = (short*)intPtr;
332 for (i = 0; i < dataLen; i++)
334 mStructs.push_back(shtPtr);
338 shtPtr[0] = btSwapEndian(shtPtr[0]);
339 shtPtr[1] = btSwapEndian(shtPtr[1]);
344 for (int a = 0; a < len; a++, shtPtr += 2)
346 shtPtr[0] = btSwapEndian(shtPtr[0]);
347 shtPtr[1] = btSwapEndian(shtPtr[1]);
352 shtPtr += (2 * shtPtr[1]) + 2;
356 // build reverse lookups
357 for (i = 0; i < (int)mStructs.size(); i++)
359 short* strc = mStructs.at(i);
360 mStructReverse.insert(strc[0], i);
361 mTypeLookup.insert(btHashString(mTypes[strc[0]]), i);
366 btHashMap<btHashPtr, void*> m_skipPointers;
368 btDefaultSerializer(int totalSize = 0, unsigned char* buffer = 0)
369 : m_uniqueIdGenerator(0),
370 m_totalSize(totalSize),
374 m_serializationFlags(0)
378 m_buffer = m_totalSize ? (unsigned char*)btAlignedAlloc(totalSize, 16) : 0;
384 m_ownsBuffer = false;
387 const bool VOID_IS_8 = ((sizeof(void*) == 8));
389 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
393 initDNA((const char*)sBulletDNAstr64, sBulletDNAlen64);
401 initDNA((const char*)sBulletDNAstr, sBulletDNAlen);
407 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
410 initDNA((const char*)sBulletDNAstr64, sBulletDNAlen64);
414 initDNA((const char*)sBulletDNAstr, sBulletDNAlen);
416 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
419 virtual ~btDefaultSerializer()
421 if (m_buffer && m_ownsBuffer)
422 btAlignedFree(m_buffer);
424 btAlignedFree(m_dna);
427 static int getMemoryDnaSizeInBytes()
429 const bool VOID_IS_8 = ((sizeof(void*) == 8));
433 return sBulletDNAlen64;
435 return sBulletDNAlen;
437 static const char* getMemoryDna()
439 const bool VOID_IS_8 = ((sizeof(void*) == 8));
442 return (const char*)sBulletDNAstr64;
444 return (const char*)sBulletDNAstr;
449 writeHeader(m_buffer);
450 m_currentSize += BT_HEADER_LENGTH;
453 void writeHeader(unsigned char* buffer) const
455 #ifdef BT_USE_DOUBLE_PRECISION
456 memcpy(buffer, "BULLETd", 7);
458 memcpy(buffer, "BULLETf", 7);
459 #endif //BT_USE_DOUBLE_PRECISION
461 int littleEndian = 1;
462 littleEndian = ((char*)&littleEndian)[0];
464 if (sizeof(void*) == 8)
487 virtual void startSerialization()
489 m_uniqueIdGenerator = 1;
492 unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
497 virtual void finishSerialization()
501 //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
505 btAlignedFree(m_buffer);
507 m_currentSize += BT_HEADER_LENGTH;
508 m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize, 16);
510 unsigned char* currentPtr = m_buffer;
511 writeHeader(m_buffer);
512 currentPtr += BT_HEADER_LENGTH;
513 for (int i = 0; i < m_chunkPtrs.size(); i++)
515 int curLength = (int)sizeof(btChunk) + m_chunkPtrs[i]->m_length;
516 memcpy(currentPtr, m_chunkPtrs[i], curLength);
517 btAlignedFree(m_chunkPtrs[i]);
518 currentPtr += curLength;
525 mStructReverse.clear();
527 m_skipPointers.clear();
530 m_uniquePointers.clear();
534 virtual void* getUniquePointer(void* oldPtr)
536 btAssert(m_uniqueIdGenerator >= 0);
540 btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
546 void** ptr2 = m_skipPointers[oldPtr];
552 m_uniqueIdGenerator++;
555 uid.m_uniqueIds[0] = m_uniqueIdGenerator;
556 uid.m_uniqueIds[1] = m_uniqueIdGenerator;
557 m_uniquePointers.insert(oldPtr, uid);
561 virtual const unsigned char* getBufferPointer() const
566 virtual int getCurrentBufferSize() const
568 return m_currentSize;
571 virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
573 if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
575 btAssert(!findPointer(oldPtr));
578 chunk->m_dna_nr = getReverseType(structType);
580 chunk->m_chunkCode = chunkCode;
582 void* uniquePtr = getUniquePointer(oldPtr);
584 m_chunkP.insert(oldPtr, uniquePtr); //chunk->m_oldPtr);
585 chunk->m_oldPtr = uniquePtr; //oldPtr;
588 virtual unsigned char* internalAlloc(size_t size)
590 unsigned char* ptr = 0;
594 ptr = m_buffer + m_currentSize;
595 m_currentSize += int(size);
596 btAssert(m_currentSize < m_totalSize);
600 ptr = (unsigned char*)btAlignedAlloc(size, 16);
601 m_currentSize += int(size);
606 virtual btChunk* allocate(size_t size, int numElements)
608 unsigned char* ptr = internalAlloc(int(size) * numElements + sizeof(btChunk));
610 unsigned char* data = ptr + sizeof(btChunk);
612 btChunk* chunk = (btChunk*)ptr;
613 chunk->m_chunkCode = 0;
614 chunk->m_oldPtr = data;
615 chunk->m_length = int(size) * numElements;
616 chunk->m_number = numElements;
618 m_chunkPtrs.push_back(chunk);
623 virtual const char* findNameForPointer(const void* ptr) const
625 const char* const* namePtr = m_nameMap.find(ptr);
626 if (namePtr && *namePtr)
631 virtual void registerNameForPointer(const void* ptr, const char* name)
633 m_nameMap.insert(ptr, name);
636 virtual void serializeName(const char* name)
640 //don't serialize name twice
641 if (findPointer((void*)name))
644 int len = btStrLen(name);
647 int newLen = len + 1;
648 int padding = ((newLen + 3) & ~3) - newLen;
651 //serialize name string now
652 btChunk* chunk = allocate(sizeof(char), newLen);
653 char* destinationName = (char*)chunk->m_oldPtr;
654 for (int i = 0; i < len; i++)
656 destinationName[i] = name[i];
658 destinationName[len] = 0;
659 finalizeChunk(chunk, "char", BT_ARRAY_CODE, (void*)name);
664 virtual int getSerializationFlags() const
666 return m_serializationFlags;
669 virtual void setSerializationFlags(int flags)
671 m_serializationFlags = flags;
673 int getNumChunks() const
675 return m_chunkPtrs.size();
678 const btChunk* getChunk(int chunkIndex) const
680 return m_chunkPtrs[chunkIndex];
684 ///In general it is best to use btDefaultSerializer,
685 ///in particular when writing the data to disk or sending it over the network.
686 ///The btInMemorySerializer is experimental and only suitable in a few cases.
687 ///The btInMemorySerializer takes a shortcut and can be useful to create a deep-copy
688 ///of objects. There will be a demo on how to use the btInMemorySerializer.
689 #ifdef ENABLE_INMEMORY_SERIALIZER
691 struct btInMemorySerializer : public btDefaultSerializer
693 btHashMap<btHashPtr, btChunk*> m_uid2ChunkPtr;
694 btHashMap<btHashPtr, void*> m_orgPtr2UniqueDataPtr;
695 btHashMap<btHashString, const void*> m_names2Ptr;
697 btBulletSerializedArrays m_arrays;
699 btInMemorySerializer(int totalSize = 0, unsigned char* buffer = 0)
700 : btDefaultSerializer(totalSize, buffer)
704 virtual void startSerialization()
706 m_uid2ChunkPtr.clear();
707 //todo: m_arrays.clear();
708 btDefaultSerializer::startSerialization();
711 btChunk* findChunkFromUniquePointer(void* uniquePointer)
713 btChunk** chkPtr = m_uid2ChunkPtr[uniquePointer];
721 virtual void registerNameForPointer(const void* ptr, const char* name)
723 btDefaultSerializer::registerNameForPointer(ptr, name);
724 m_names2Ptr.insert(name, ptr);
727 virtual void finishSerialization()
731 virtual void* getUniquePointer(void* oldPtr)
736 // void* uniquePtr = getUniquePointer(oldPtr);
737 btChunk* chunk = findChunkFromUniquePointer(oldPtr);
740 return chunk->m_oldPtr;
744 const char* n = (const char*)oldPtr;
745 const void** ptr = m_names2Ptr[n];
752 void** ptr2 = m_skipPointers[oldPtr];
759 //If this assert hit, serialization happened in the wrong order
760 // 'getUniquePointer'
769 virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
771 if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
773 btAssert(!findPointer(oldPtr));
776 chunk->m_dna_nr = getReverseType(structType);
777 chunk->m_chunkCode = chunkCode;
778 //void* uniquePtr = getUniquePointer(oldPtr);
779 m_chunkP.insert(oldPtr, oldPtr); //chunk->m_oldPtr);
780 // chunk->m_oldPtr = uniquePtr;//oldPtr;
782 void* uid = findPointer(oldPtr);
783 m_uid2ChunkPtr.insert(uid, chunk);
785 switch (chunk->m_chunkCode)
787 case BT_SOFTBODY_CODE:
789 #ifdef BT_USE_DOUBLE_PRECISION
790 m_arrays.m_softBodyDoubleData.push_back((btSoftBodyDoubleData*)chunk->m_oldPtr);
792 m_arrays.m_softBodyFloatData.push_back((btSoftBodyFloatData*)chunk->m_oldPtr);
796 case BT_COLLISIONOBJECT_CODE:
798 #ifdef BT_USE_DOUBLE_PRECISION
799 m_arrays.m_collisionObjectDataDouble.push_back((btCollisionObjectDoubleData*)chunk->m_oldPtr);
800 #else //BT_USE_DOUBLE_PRECISION
801 m_arrays.m_collisionObjectDataFloat.push_back((btCollisionObjectFloatData*)chunk->m_oldPtr);
802 #endif //BT_USE_DOUBLE_PRECISION
805 case BT_RIGIDBODY_CODE:
807 #ifdef BT_USE_DOUBLE_PRECISION
808 m_arrays.m_rigidBodyDataDouble.push_back((btRigidBodyDoubleData*)chunk->m_oldPtr);
810 m_arrays.m_rigidBodyDataFloat.push_back((btRigidBodyFloatData*)chunk->m_oldPtr);
811 #endif //BT_USE_DOUBLE_PRECISION
814 case BT_CONSTRAINT_CODE:
816 #ifdef BT_USE_DOUBLE_PRECISION
817 m_arrays.m_constraintDataDouble.push_back((btTypedConstraintDoubleData*)chunk->m_oldPtr);
819 m_arrays.m_constraintDataFloat.push_back((btTypedConstraintFloatData*)chunk->m_oldPtr);
823 case BT_QUANTIZED_BVH_CODE:
825 #ifdef BT_USE_DOUBLE_PRECISION
826 m_arrays.m_bvhsDouble.push_back((btQuantizedBvhDoubleData*)chunk->m_oldPtr);
828 m_arrays.m_bvhsFloat.push_back((btQuantizedBvhFloatData*)chunk->m_oldPtr);
835 btCollisionShapeData* shapeData = (btCollisionShapeData*)chunk->m_oldPtr;
836 m_arrays.m_colShapeData.push_back(shapeData);
839 case BT_TRIANLGE_INFO_MAP:
841 case BT_SBMATERIAL_CODE:
843 case BT_DYNAMICSWORLD_CODE:
854 int getNumChunks() const
856 return m_uid2ChunkPtr.size();
859 const btChunk* getChunk(int chunkIndex) const
861 return *m_uid2ChunkPtr.getAtIndex(chunkIndex);
864 #endif //ENABLE_INMEMORY_SERIALIZER
866 #endif //BT_SERIALIZER_H