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
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 {
btBulletSerializedArraysbtBulletSerializedArrays144 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
findPointer(void * oldPtr)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
writeDNA()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
getReverseType(const char * type)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
initDNA(const char * bdnaOrg,int dnalen)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)
m_totalSize(totalSize)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
~btDefaultSerializer()441 virtual ~btDefaultSerializer()
442 {
443 if (m_buffer && m_ownsBuffer)
444 btAlignedFree(m_buffer);
445 if (m_dna)
446 btAlignedFree(m_dna);
447 }
448
insertHeader()449 void insertHeader()
450 {
451 writeHeader(m_buffer);
452 m_currentSize += BT_HEADER_LENGTH;
453 }
454
writeHeader(unsigned char * buffer)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
startSerialization()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
finishSerialization()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
getUniquePointer(void * oldPtr)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
getBufferPointer()569 virtual const unsigned char* getBufferPointer() const
570 {
571 return m_buffer;
572 }
573
getCurrentBufferSize()574 virtual int getCurrentBufferSize() const
575 {
576 return m_currentSize;
577 }
578
finalizeChunk(btChunk * chunk,const char * structType,int chunkCode,void * oldPtr)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
internalAlloc(size_t size)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
allocate(size_t size,int numElements)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
findNameForPointer(const void * ptr)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
registerNameForPointer(const void * ptr,const char * name)645 virtual void registerNameForPointer(const void* ptr, const char* name)
646 {
647 m_nameMap.insert(ptr,name);
648 }
649
serializeName(const char * name)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
getSerializationFlags()679 virtual int getSerializationFlags() const
680 {
681 return m_serializationFlags;
682 }
683
setSerializationFlags(int flags)684 virtual void setSerializationFlags(int flags)
685 {
686 m_serializationFlags = flags;
687 }
getNumChunks()688 int getNumChunks() const
689 {
690 return m_chunkPtrs.size();
691 }
692
getChunk(int chunkIndex)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)
btDefaultSerializerbtInMemorySerializer717 :btDefaultSerializer(totalSize,buffer)
718 {
719
720 }
721
startSerializationbtInMemorySerializer722 virtual void startSerialization()
723 {
724 m_uid2ChunkPtr.clear();
725 //todo: m_arrays.clear();
726 btDefaultSerializer::startSerialization();
727 }
728
729
730
findChunkFromUniquePointerbtInMemorySerializer731 btChunk* findChunkFromUniquePointer(void* uniquePointer)
732 {
733 btChunk** chkPtr = m_uid2ChunkPtr[uniquePointer];
734 if (chkPtr)
735 {
736 return *chkPtr;
737 }
738 return 0;
739 }
740
registerNameForPointerbtInMemorySerializer741 virtual void registerNameForPointer(const void* ptr, const char* name)
742 {
743 btDefaultSerializer::registerNameForPointer(ptr,name);
744 m_names2Ptr.insert(name,ptr);
745 }
746
finishSerializationbtInMemorySerializer747 virtual void finishSerialization()
748 {
749 }
750
getUniquePointerbtInMemorySerializer751 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
finalizeChunkbtInMemorySerializer787 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
getNumChunksbtInMemorySerializer872 int getNumChunks() const
873 {
874 return m_uid2ChunkPtr.size();
875 }
876
getChunkbtInMemorySerializer877 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