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