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