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