1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
4 
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:
10 
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.
14 */
15 
16 #ifndef BT_SERIALIZER_H
17 #define BT_SERIALIZER_H
18 
19 #include "btScalar.h"  // has definitions like SIMD_FORCE_INLINE
20 #include "btHashMap.h"
21 
22 #if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
23 #include <memory.h>
24 #endif
25 #include <string.h>
26 
27 extern char sBulletDNAstr[];
28 extern int sBulletDNAlen;
29 extern char sBulletDNAstr64[];
30 extern int sBulletDNAlen64;
31 
btStrLen(const char * str)32 SIMD_FORCE_INLINE int btStrLen(const char* str)
33 {
34 	if (!str)
35 		return (0);
36 	int len = 0;
37 
38 	while (*str != 0)
39 	{
40 		str++;
41 		len++;
42 	}
43 
44 	return len;
45 }
46 
47 class btChunk
48 {
49 public:
50 	int m_chunkCode;
51 	int m_length;
52 	void* m_oldPtr;
53 	int m_dna_nr;
54 	int m_number;
55 };
56 
57 enum btSerializationFlags
58 {
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,
63 };
64 
65 class btSerializer
66 {
67 public:
~btSerializer()68 	virtual ~btSerializer() {}
69 
70 	virtual const unsigned char* getBufferPointer() const = 0;
71 
72 	virtual int getCurrentBufferSize() const = 0;
73 
74 	virtual btChunk* allocate(size_t size, int numElements) = 0;
75 
76 	virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr) = 0;
77 
78 	virtual void* findPointer(void* oldPtr) = 0;
79 
80 	virtual void* getUniquePointer(void* oldPtr) = 0;
81 
82 	virtual void startSerialization() = 0;
83 
84 	virtual void finishSerialization() = 0;
85 
86 	virtual const char* findNameForPointer(const void* ptr) const = 0;
87 
88 	virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
89 
90 	virtual void serializeName(const char* ptr) = 0;
91 
92 	virtual int getSerializationFlags() const = 0;
93 
94 	virtual void setSerializationFlags(int flags) = 0;
95 
96 	virtual int getNumChunks() const = 0;
97 
98 	virtual const btChunk* getChunk(int chunkIndex) const = 0;
99 };
100 
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))
104 #else
105 #define BT_MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
106 #endif
107 
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')
124 
125 struct btPointerUid
126 {
127 	union {
128 		void* m_ptr;
129 		int m_uniqueIds[2];
130 	};
131 };
132 
133 struct btBulletSerializedArrays
134 {
btBulletSerializedArraysbtBulletSerializedArrays135 	btBulletSerializedArrays()
136 	{
137 	}
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;
152 };
153 
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
157 {
158 protected:
159 	btAlignedObjectArray<char*> mTypes;
160 	btAlignedObjectArray<short*> mStructs;
161 	btAlignedObjectArray<short> mTlens;
162 	btHashMap<btHashInt, int> mStructReverse;
163 	btHashMap<btHashString, int> mTypeLookup;
164 
165 	btHashMap<btHashPtr, void*> m_chunkP;
166 
167 	btHashMap<btHashPtr, const char*> m_nameMap;
168 
169 	btHashMap<btHashPtr, btPointerUid> m_uniquePointers;
170 	int m_uniqueIdGenerator;
171 
172 	int m_totalSize;
173 	unsigned char* m_buffer;
174 	bool m_ownsBuffer;
175 	int m_currentSize;
176 	void* m_dna;
177 	int m_dnaLength;
178 
179 	int m_serializationFlags;
180 
181 	btAlignedObjectArray<btChunk*> m_chunkPtrs;
182 
183 protected:
findPointer(void * oldPtr)184 	virtual void* findPointer(void* oldPtr)
185 	{
186 		void** ptr = m_chunkP.find(oldPtr);
187 		if (ptr && *ptr)
188 			return *ptr;
189 		return 0;
190 	}
191 
writeDNA()192 	virtual void writeDNA()
193 	{
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);
197 	}
198 
getReverseType(const char * type)199 	int getReverseType(const char* type) const
200 	{
201 		btHashString key(type);
202 		const int* valuePtr = mTypeLookup.find(key);
203 		if (valuePtr)
204 			return *valuePtr;
205 
206 		return -1;
207 	}
208 
initDNA(const char * bdnaOrg,int dnalen)209 	void initDNA(const char* bdnaOrg, int dnalen)
210 	{
211 		///was already initialized
212 		if (m_dna)
213 			return;
214 
215 		int littleEndian = 1;
216 		littleEndian = ((char*)&littleEndian)[0];
217 
218 		m_dna = btAlignedAlloc(dnalen, 16);
219 		memcpy(m_dna, bdnaOrg, dnalen);
220 		m_dnaLength = dnalen;
221 
222 		int* intPtr = 0;
223 		short* shtPtr = 0;
224 		char* cp = 0;
225 		int dataLen = 0;
226 		intPtr = (int*)m_dna;
227 
228 		/*
229 				SDNA (4 bytes) (magic number)
230 				NAME (4 bytes)
231 				<nr> (4 bytes) amount of names (int)
232 				<string>
233 				<string>
234 			*/
235 
236 		if (strncmp((const char*)m_dna, "SDNA", 4) == 0)
237 		{
238 			// skip ++ NAME
239 			intPtr++;
240 			intPtr++;
241 		}
242 
243 		// Parse names
244 		if (!littleEndian)
245 			*intPtr = btSwapEndian(*intPtr);
246 
247 		dataLen = *intPtr;
248 
249 		intPtr++;
250 
251 		cp = (char*)intPtr;
252 		int i;
253 		for (i = 0; i < dataLen; i++)
254 		{
255 			while (*cp) cp++;
256 			cp++;
257 		}
258 		cp = btAlignPointer(cp, 4);
259 
260 		/*
261 				TYPE (4 bytes)
262 				<nr> amount of types (int)
263 				<string>
264 				<string>
265 			*/
266 
267 		intPtr = (int*)cp;
268 		btAssert(strncmp(cp, "TYPE", 4) == 0);
269 		intPtr++;
270 
271 		if (!littleEndian)
272 			*intPtr = btSwapEndian(*intPtr);
273 
274 		dataLen = *intPtr;
275 		intPtr++;
276 
277 		cp = (char*)intPtr;
278 		for (i = 0; i < dataLen; i++)
279 		{
280 			mTypes.push_back(cp);
281 			while (*cp) cp++;
282 			cp++;
283 		}
284 
285 		cp = btAlignPointer(cp, 4);
286 
287 		/*
288 				TLEN (4 bytes)
289 				<len> (short) the lengths of types
290 				<len>
291 			*/
292 
293 		// Parse type lens
294 		intPtr = (int*)cp;
295 		btAssert(strncmp(cp, "TLEN", 4) == 0);
296 		intPtr++;
297 
298 		dataLen = (int)mTypes.size();
299 
300 		shtPtr = (short*)intPtr;
301 		for (i = 0; i < dataLen; i++, shtPtr++)
302 		{
303 			if (!littleEndian)
304 				shtPtr[0] = btSwapEndian(shtPtr[0]);
305 			mTlens.push_back(shtPtr[0]);
306 		}
307 
308 		if (dataLen & 1) shtPtr++;
309 
310 		/*
311 				STRC (4 bytes)
312 				<nr> amount of structs (int)
313 				<typenr>
314 				<nr_of_elems>
315 				<typenr>
316 				<namenr>
317 				<typenr>
318 				<namenr>
319 			*/
320 
321 		intPtr = (int*)shtPtr;
322 		cp = (char*)intPtr;
323 		btAssert(strncmp(cp, "STRC", 4) == 0);
324 		intPtr++;
325 
326 		if (!littleEndian)
327 			*intPtr = btSwapEndian(*intPtr);
328 		dataLen = *intPtr;
329 		intPtr++;
330 
331 		shtPtr = (short*)intPtr;
332 		for (i = 0; i < dataLen; i++)
333 		{
334 			mStructs.push_back(shtPtr);
335 
336 			if (!littleEndian)
337 			{
338 				shtPtr[0] = btSwapEndian(shtPtr[0]);
339 				shtPtr[1] = btSwapEndian(shtPtr[1]);
340 
341 				int len = shtPtr[1];
342 				shtPtr += 2;
343 
344 				for (int a = 0; a < len; a++, shtPtr += 2)
345 				{
346 					shtPtr[0] = btSwapEndian(shtPtr[0]);
347 					shtPtr[1] = btSwapEndian(shtPtr[1]);
348 				}
349 			}
350 			else
351 			{
352 				shtPtr += (2 * shtPtr[1]) + 2;
353 			}
354 		}
355 
356 		// build reverse lookups
357 		for (i = 0; i < (int)mStructs.size(); i++)
358 		{
359 			short* strc = mStructs.at(i);
360 			mStructReverse.insert(strc[0], i);
361 			mTypeLookup.insert(btHashString(mTypes[strc[0]]), i);
362 		}
363 	}
364 
365 public:
366 	btHashMap<btHashPtr, void*> m_skipPointers;
367 
368 	btDefaultSerializer(int totalSize = 0, unsigned char* buffer = 0)
369 		: m_uniqueIdGenerator(0),
370 		  m_totalSize(totalSize),
371 		  m_currentSize(0),
372 		  m_dna(0),
373 		  m_dnaLength(0),
374 		  m_serializationFlags(0)
375 	{
376 		if (buffer == 0)
377 		{
378 			m_buffer = m_totalSize ? (unsigned char*)btAlignedAlloc(totalSize, 16) : 0;
379 			m_ownsBuffer = true;
380 		}
381 		else
382 		{
383 			m_buffer = buffer;
384 			m_ownsBuffer = false;
385 		}
386 
387 		const bool VOID_IS_8 = ((sizeof(void*) == 8));
388 
389 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
390 		if (VOID_IS_8)
391 		{
392 #if _WIN64
393 			initDNA((const char*)sBulletDNAstr64, sBulletDNAlen64);
394 #else
395 			btAssert(0);
396 #endif
397 		}
398 		else
399 		{
400 #ifndef _WIN64
401 			initDNA((const char*)sBulletDNAstr, sBulletDNAlen);
402 #else
403 			btAssert(0);
404 #endif
405 		}
406 
407 #else   //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
408 		if (VOID_IS_8)
409 		{
410 			initDNA((const char*)sBulletDNAstr64, sBulletDNAlen64);
411 		}
412 		else
413 		{
414 			initDNA((const char*)sBulletDNAstr, sBulletDNAlen);
415 		}
416 #endif  //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
417 	}
418 
~btDefaultSerializer()419 	virtual ~btDefaultSerializer()
420 	{
421 		if (m_buffer && m_ownsBuffer)
422 			btAlignedFree(m_buffer);
423 		if (m_dna)
424 			btAlignedFree(m_dna);
425 	}
426 
getMemoryDnaSizeInBytes()427 	static int getMemoryDnaSizeInBytes()
428 	{
429 		const bool VOID_IS_8 = ((sizeof(void*) == 8));
430 
431 		if (VOID_IS_8)
432 		{
433 			return sBulletDNAlen64;
434 		}
435 		return sBulletDNAlen;
436 	}
getMemoryDna()437 	static const char* getMemoryDna()
438 	{
439 		const bool VOID_IS_8 = ((sizeof(void*) == 8));
440 		if (VOID_IS_8)
441 		{
442 			return (const char*)sBulletDNAstr64;
443 		}
444 		return (const char*)sBulletDNAstr;
445 	}
446 
insertHeader()447 	void insertHeader()
448 	{
449 		writeHeader(m_buffer);
450 		m_currentSize += BT_HEADER_LENGTH;
451 	}
452 
writeHeader(unsigned char * buffer)453 	void writeHeader(unsigned char* buffer) const
454 	{
455 #ifdef BT_USE_DOUBLE_PRECISION
456 		memcpy(buffer, "BULLETd", 7);
457 #else
458 		memcpy(buffer, "BULLETf", 7);
459 #endif  //BT_USE_DOUBLE_PRECISION
460 
461 		int littleEndian = 1;
462 		littleEndian = ((char*)&littleEndian)[0];
463 
464 		if (sizeof(void*) == 8)
465 		{
466 			buffer[7] = '-';
467 		}
468 		else
469 		{
470 			buffer[7] = '_';
471 		}
472 
473 		if (littleEndian)
474 		{
475 			buffer[8] = 'v';
476 		}
477 		else
478 		{
479 			buffer[8] = 'V';
480 		}
481 
482 		buffer[9] = '2';
483 		buffer[10] = '8';
484 		buffer[11] = '9';
485 	}
486 
startSerialization()487 	virtual void startSerialization()
488 	{
489 		m_uniqueIdGenerator = 1;
490 		if (m_totalSize)
491 		{
492 			unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
493 			writeHeader(buffer);
494 		}
495 	}
496 
finishSerialization()497 	virtual void finishSerialization()
498 	{
499 		writeDNA();
500 
501 		//if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
502 		int mysize = 0;
503 		if (!m_totalSize)
504 		{
505 			if (m_buffer)
506 				btAlignedFree(m_buffer);
507 
508 			m_currentSize += BT_HEADER_LENGTH;
509 			m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize, 16);
510 
511 			unsigned char* currentPtr = m_buffer;
512 			writeHeader(m_buffer);
513 			currentPtr += BT_HEADER_LENGTH;
514 			mysize += BT_HEADER_LENGTH;
515 			for (int i = 0; i < m_chunkPtrs.size(); i++)
516 			{
517 				int curLength = sizeof(btChunk) + m_chunkPtrs[i]->m_length;
518 				memcpy(currentPtr, m_chunkPtrs[i], curLength);
519 				btAlignedFree(m_chunkPtrs[i]);
520 				currentPtr += curLength;
521 				mysize += curLength;
522 			}
523 		}
524 
525 		mTypes.clear();
526 		mStructs.clear();
527 		mTlens.clear();
528 		mStructReverse.clear();
529 		mTypeLookup.clear();
530 		m_skipPointers.clear();
531 		m_chunkP.clear();
532 		m_nameMap.clear();
533 		m_uniquePointers.clear();
534 		m_chunkPtrs.clear();
535 	}
536 
getUniquePointer(void * oldPtr)537 	virtual void* getUniquePointer(void* oldPtr)
538 	{
539 		btAssert(m_uniqueIdGenerator >= 0);
540 		if (!oldPtr)
541 			return 0;
542 
543 		btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
544 		if (uptr)
545 		{
546 			return uptr->m_ptr;
547 		}
548 
549 		void** ptr2 = m_skipPointers[oldPtr];
550 		if (ptr2)
551 		{
552 			return 0;
553 		}
554 
555 		m_uniqueIdGenerator++;
556 
557 		btPointerUid uid;
558 		uid.m_uniqueIds[0] = m_uniqueIdGenerator;
559 		uid.m_uniqueIds[1] = m_uniqueIdGenerator;
560 		m_uniquePointers.insert(oldPtr, uid);
561 		return uid.m_ptr;
562 	}
563 
getBufferPointer()564 	virtual const unsigned char* getBufferPointer() const
565 	{
566 		return m_buffer;
567 	}
568 
getCurrentBufferSize()569 	virtual int getCurrentBufferSize() const
570 	{
571 		return m_currentSize;
572 	}
573 
finalizeChunk(btChunk * chunk,const char * structType,int chunkCode,void * oldPtr)574 	virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
575 	{
576 		if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
577 		{
578 			btAssert(!findPointer(oldPtr));
579 		}
580 
581 		chunk->m_dna_nr = getReverseType(structType);
582 
583 		chunk->m_chunkCode = chunkCode;
584 
585 		void* uniquePtr = getUniquePointer(oldPtr);
586 
587 		m_chunkP.insert(oldPtr, uniquePtr);  //chunk->m_oldPtr);
588 		chunk->m_oldPtr = uniquePtr;         //oldPtr;
589 	}
590 
internalAlloc(size_t size)591 	virtual unsigned char* internalAlloc(size_t size)
592 	{
593 		unsigned char* ptr = 0;
594 
595 		if (m_totalSize)
596 		{
597 			ptr = m_buffer + m_currentSize;
598 			m_currentSize += int(size);
599 			btAssert(m_currentSize < m_totalSize);
600 		}
601 		else
602 		{
603 			ptr = (unsigned char*)btAlignedAlloc(size, 16);
604 			m_currentSize += int(size);
605 		}
606 		return ptr;
607 	}
608 
allocate(size_t size,int numElements)609 	virtual btChunk* allocate(size_t size, int numElements)
610 	{
611 		unsigned char* ptr = internalAlloc(int(size) * numElements + sizeof(btChunk));
612 
613 		unsigned char* data = ptr + sizeof(btChunk);
614 
615 		btChunk* chunk = (btChunk*)ptr;
616 		chunk->m_chunkCode = 0;
617 		chunk->m_oldPtr = data;
618 		chunk->m_length = int(size) * numElements;
619 		chunk->m_number = numElements;
620 
621 		m_chunkPtrs.push_back(chunk);
622 
623 		return chunk;
624 	}
625 
findNameForPointer(const void * ptr)626 	virtual const char* findNameForPointer(const void* ptr) const
627 	{
628 		const char* const* namePtr = m_nameMap.find(ptr);
629 		if (namePtr && *namePtr)
630 			return *namePtr;
631 		return 0;
632 	}
633 
registerNameForPointer(const void * ptr,const char * name)634 	virtual void registerNameForPointer(const void* ptr, const char* name)
635 	{
636 		m_nameMap.insert(ptr, name);
637 	}
638 
serializeName(const char * name)639 	virtual void serializeName(const char* name)
640 	{
641 		if (name)
642 		{
643 			//don't serialize name twice
644 			if (findPointer((void*)name))
645 				return;
646 
647 			int len = btStrLen(name);
648 			if (len)
649 			{
650 				int newLen = len + 1;
651 				int padding = ((newLen + 3) & ~3) - newLen;
652 				newLen += padding;
653 
654 				//serialize name string now
655 				btChunk* chunk = allocate(sizeof(char), newLen);
656 				char* destinationName = (char*)chunk->m_oldPtr;
657 				for (int i = 0; i < len; i++)
658 				{
659 					destinationName[i] = name[i];
660 				}
661 				destinationName[len] = 0;
662 				finalizeChunk(chunk, "char", BT_ARRAY_CODE, (void*)name);
663 			}
664 		}
665 	}
666 
getSerializationFlags()667 	virtual int getSerializationFlags() const
668 	{
669 		return m_serializationFlags;
670 	}
671 
setSerializationFlags(int flags)672 	virtual void setSerializationFlags(int flags)
673 	{
674 		m_serializationFlags = flags;
675 	}
getNumChunks()676 	int getNumChunks() const
677 	{
678 		return m_chunkPtrs.size();
679 	}
680 
getChunk(int chunkIndex)681 	const btChunk* getChunk(int chunkIndex) const
682 	{
683 		return m_chunkPtrs[chunkIndex];
684 	}
685 };
686 
687 ///In general it is best to use btDefaultSerializer,
688 ///in particular when writing the data to disk or sending it over the network.
689 ///The btInMemorySerializer is experimental and only suitable in a few cases.
690 ///The btInMemorySerializer takes a shortcut and can be useful to create a deep-copy
691 ///of objects. There will be a demo on how to use the btInMemorySerializer.
692 #ifdef ENABLE_INMEMORY_SERIALIZER
693 
694 struct btInMemorySerializer : public btDefaultSerializer
695 {
696 	btHashMap<btHashPtr, btChunk*> m_uid2ChunkPtr;
697 	btHashMap<btHashPtr, void*> m_orgPtr2UniqueDataPtr;
698 	btHashMap<btHashString, const void*> m_names2Ptr;
699 
700 	btBulletSerializedArrays m_arrays;
701 
702 	btInMemorySerializer(int totalSize = 0, unsigned char* buffer = 0)
btDefaultSerializerbtInMemorySerializer703 		: btDefaultSerializer(totalSize, buffer)
704 	{
705 	}
706 
startSerializationbtInMemorySerializer707 	virtual void startSerialization()
708 	{
709 		m_uid2ChunkPtr.clear();
710 		//todo: m_arrays.clear();
711 		btDefaultSerializer::startSerialization();
712 	}
713 
findChunkFromUniquePointerbtInMemorySerializer714 	btChunk* findChunkFromUniquePointer(void* uniquePointer)
715 	{
716 		btChunk** chkPtr = m_uid2ChunkPtr[uniquePointer];
717 		if (chkPtr)
718 		{
719 			return *chkPtr;
720 		}
721 		return 0;
722 	}
723 
registerNameForPointerbtInMemorySerializer724 	virtual void registerNameForPointer(const void* ptr, const char* name)
725 	{
726 		btDefaultSerializer::registerNameForPointer(ptr, name);
727 		m_names2Ptr.insert(name, ptr);
728 	}
729 
finishSerializationbtInMemorySerializer730 	virtual void finishSerialization()
731 	{
732 	}
733 
getUniquePointerbtInMemorySerializer734 	virtual void* getUniquePointer(void* oldPtr)
735 	{
736 		if (oldPtr == 0)
737 			return 0;
738 
739 		// void* uniquePtr = getUniquePointer(oldPtr);
740 		btChunk* chunk = findChunkFromUniquePointer(oldPtr);
741 		if (chunk)
742 		{
743 			return chunk->m_oldPtr;
744 		}
745 		else
746 		{
747 			const char* n = (const char*)oldPtr;
748 			const void** ptr = m_names2Ptr[n];
749 			if (ptr)
750 			{
751 				return oldPtr;
752 			}
753 			else
754 			{
755 				void** ptr2 = m_skipPointers[oldPtr];
756 				if (ptr2)
757 				{
758 					return 0;
759 				}
760 				else
761 				{
762 					//If this assert hit, serialization happened in the wrong order
763 					// 'getUniquePointer'
764 					btAssert(0);
765 				}
766 			}
767 			return 0;
768 		}
769 		return oldPtr;
770 	}
771 
finalizeChunkbtInMemorySerializer772 	virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
773 	{
774 		if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
775 		{
776 			btAssert(!findPointer(oldPtr));
777 		}
778 
779 		chunk->m_dna_nr = getReverseType(structType);
780 		chunk->m_chunkCode = chunkCode;
781 		//void* uniquePtr = getUniquePointer(oldPtr);
782 		m_chunkP.insert(oldPtr, oldPtr);  //chunk->m_oldPtr);
783 		// chunk->m_oldPtr = uniquePtr;//oldPtr;
784 
785 		void* uid = findPointer(oldPtr);
786 		m_uid2ChunkPtr.insert(uid, chunk);
787 
788 		switch (chunk->m_chunkCode)
789 		{
790 			case BT_SOFTBODY_CODE:
791 			{
792 #ifdef BT_USE_DOUBLE_PRECISION
793 				m_arrays.m_softBodyDoubleData.push_back((btSoftBodyDoubleData*)chunk->m_oldPtr);
794 #else
795 				m_arrays.m_softBodyFloatData.push_back((btSoftBodyFloatData*)chunk->m_oldPtr);
796 #endif
797 				break;
798 			}
799 			case BT_COLLISIONOBJECT_CODE:
800 			{
801 #ifdef BT_USE_DOUBLE_PRECISION
802 				m_arrays.m_collisionObjectDataDouble.push_back((btCollisionObjectDoubleData*)chunk->m_oldPtr);
803 #else   //BT_USE_DOUBLE_PRECISION
804 				m_arrays.m_collisionObjectDataFloat.push_back((btCollisionObjectFloatData*)chunk->m_oldPtr);
805 #endif  //BT_USE_DOUBLE_PRECISION
806 				break;
807 			}
808 			case BT_RIGIDBODY_CODE:
809 			{
810 #ifdef BT_USE_DOUBLE_PRECISION
811 				m_arrays.m_rigidBodyDataDouble.push_back((btRigidBodyDoubleData*)chunk->m_oldPtr);
812 #else
813 				m_arrays.m_rigidBodyDataFloat.push_back((btRigidBodyFloatData*)chunk->m_oldPtr);
814 #endif  //BT_USE_DOUBLE_PRECISION
815 				break;
816 			};
817 			case BT_CONSTRAINT_CODE:
818 			{
819 #ifdef BT_USE_DOUBLE_PRECISION
820 				m_arrays.m_constraintDataDouble.push_back((btTypedConstraintDoubleData*)chunk->m_oldPtr);
821 #else
822 				m_arrays.m_constraintDataFloat.push_back((btTypedConstraintFloatData*)chunk->m_oldPtr);
823 #endif
824 				break;
825 			}
826 			case BT_QUANTIZED_BVH_CODE:
827 			{
828 #ifdef BT_USE_DOUBLE_PRECISION
829 				m_arrays.m_bvhsDouble.push_back((btQuantizedBvhDoubleData*)chunk->m_oldPtr);
830 #else
831 				m_arrays.m_bvhsFloat.push_back((btQuantizedBvhFloatData*)chunk->m_oldPtr);
832 #endif
833 				break;
834 			}
835 
836 			case BT_SHAPE_CODE:
837 			{
838 				btCollisionShapeData* shapeData = (btCollisionShapeData*)chunk->m_oldPtr;
839 				m_arrays.m_colShapeData.push_back(shapeData);
840 				break;
841 			}
842 			case BT_TRIANLGE_INFO_MAP:
843 			case BT_ARRAY_CODE:
844 			case BT_SBMATERIAL_CODE:
845 			case BT_SBNODE_CODE:
846 			case BT_DYNAMICSWORLD_CODE:
847 			case BT_DNA_CODE:
848 			{
849 				break;
850 			}
851 			default:
852 			{
853 			}
854 		};
855 	}
856 
getNumChunksbtInMemorySerializer857 	int getNumChunks() const
858 	{
859 		return m_uid2ChunkPtr.size();
860 	}
861 
getChunkbtInMemorySerializer862 	const btChunk* getChunk(int chunkIndex) const
863 	{
864 		return *m_uid2ChunkPtr.getAtIndex(chunkIndex);
865 	}
866 };
867 #endif  //ENABLE_INMEMORY_SERIALIZER
868 
869 #endif  //BT_SERIALIZER_H
870