[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-physics / third-party / bullet3 / src / LinearMath / btSerializer.h
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
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:
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 {
135         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:
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
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
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
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
419         virtual ~btDefaultSerializer()
420         {
421                 if (m_buffer && m_ownsBuffer)
422                         btAlignedFree(m_buffer);
423                 if (m_dna)
424                         btAlignedFree(m_dna);
425         }
426
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         }
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
447         void insertHeader()
448         {
449                 writeHeader(m_buffer);
450                 m_currentSize += BT_HEADER_LENGTH;
451         }
452
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] = '3';
483                 buffer[10] = '2';
484                 buffer[11] = '5';
485         }
486
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
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                 if (!m_totalSize)
503                 {
504                         if (m_buffer)
505                                 btAlignedFree(m_buffer);
506
507                         m_currentSize += BT_HEADER_LENGTH;
508                         m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize, 16);
509
510                         unsigned char* currentPtr = m_buffer;
511                         writeHeader(m_buffer);
512                         currentPtr += BT_HEADER_LENGTH;
513                         for (int i = 0; i < m_chunkPtrs.size(); i++)
514                         {
515                                 int curLength = (int)sizeof(btChunk) + m_chunkPtrs[i]->m_length;
516                                 memcpy(currentPtr, m_chunkPtrs[i], curLength);
517                                 btAlignedFree(m_chunkPtrs[i]);
518                                 currentPtr += curLength;
519                         }
520                 }
521
522                 mTypes.clear();
523                 mStructs.clear();
524                 mTlens.clear();
525                 mStructReverse.clear();
526                 mTypeLookup.clear();
527                 m_skipPointers.clear();
528                 m_chunkP.clear();
529                 m_nameMap.clear();
530                 m_uniquePointers.clear();
531                 m_chunkPtrs.clear();
532         }
533
534         virtual void* getUniquePointer(void* oldPtr)
535         {
536                 btAssert(m_uniqueIdGenerator >= 0);
537                 if (!oldPtr)
538                         return 0;
539
540                 btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
541                 if (uptr)
542                 {
543                         return uptr->m_ptr;
544                 }
545
546                 void** ptr2 = m_skipPointers[oldPtr];
547                 if (ptr2)
548                 {
549                         return 0;
550                 }
551
552                 m_uniqueIdGenerator++;
553
554                 btPointerUid uid;
555                 uid.m_uniqueIds[0] = m_uniqueIdGenerator;
556                 uid.m_uniqueIds[1] = m_uniqueIdGenerator;
557                 m_uniquePointers.insert(oldPtr, uid);
558                 return uid.m_ptr;
559         }
560
561         virtual const unsigned char* getBufferPointer() const
562         {
563                 return m_buffer;
564         }
565
566         virtual int getCurrentBufferSize() const
567         {
568                 return m_currentSize;
569         }
570
571         virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
572         {
573                 if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
574                 {
575                         btAssert(!findPointer(oldPtr));
576                 }
577
578                 chunk->m_dna_nr = getReverseType(structType);
579
580                 chunk->m_chunkCode = chunkCode;
581
582                 void* uniquePtr = getUniquePointer(oldPtr);
583
584                 m_chunkP.insert(oldPtr, uniquePtr);  //chunk->m_oldPtr);
585                 chunk->m_oldPtr = uniquePtr;         //oldPtr;
586         }
587
588         virtual unsigned char* internalAlloc(size_t size)
589         {
590                 unsigned char* ptr = 0;
591
592                 if (m_totalSize)
593                 {
594                         ptr = m_buffer + m_currentSize;
595                         m_currentSize += int(size);
596                         btAssert(m_currentSize < m_totalSize);
597                 }
598                 else
599                 {
600                         ptr = (unsigned char*)btAlignedAlloc(size, 16);
601                         m_currentSize += int(size);
602                 }
603                 return ptr;
604         }
605
606         virtual btChunk* allocate(size_t size, int numElements)
607         {
608                 unsigned char* ptr = internalAlloc(int(size) * numElements + sizeof(btChunk));
609
610                 unsigned char* data = ptr + sizeof(btChunk);
611
612                 btChunk* chunk = (btChunk*)ptr;
613                 chunk->m_chunkCode = 0;
614                 chunk->m_oldPtr = data;
615                 chunk->m_length = int(size) * numElements;
616                 chunk->m_number = numElements;
617
618                 m_chunkPtrs.push_back(chunk);
619
620                 return chunk;
621         }
622
623         virtual const char* findNameForPointer(const void* ptr) const
624         {
625                 const char* const* namePtr = m_nameMap.find(ptr);
626                 if (namePtr && *namePtr)
627                         return *namePtr;
628                 return 0;
629         }
630
631         virtual void registerNameForPointer(const void* ptr, const char* name)
632         {
633                 m_nameMap.insert(ptr, name);
634         }
635
636         virtual void serializeName(const char* name)
637         {
638                 if (name)
639                 {
640                         //don't serialize name twice
641                         if (findPointer((void*)name))
642                                 return;
643
644                         int len = btStrLen(name);
645                         if (len)
646                         {
647                                 int newLen = len + 1;
648                                 int padding = ((newLen + 3) & ~3) - newLen;
649                                 newLen += padding;
650
651                                 //serialize name string now
652                                 btChunk* chunk = allocate(sizeof(char), newLen);
653                                 char* destinationName = (char*)chunk->m_oldPtr;
654                                 for (int i = 0; i < len; i++)
655                                 {
656                                         destinationName[i] = name[i];
657                                 }
658                                 destinationName[len] = 0;
659                                 finalizeChunk(chunk, "char", BT_ARRAY_CODE, (void*)name);
660                         }
661                 }
662         }
663
664         virtual int getSerializationFlags() const
665         {
666                 return m_serializationFlags;
667         }
668
669         virtual void setSerializationFlags(int flags)
670         {
671                 m_serializationFlags = flags;
672         }
673         int getNumChunks() const
674         {
675                 return m_chunkPtrs.size();
676         }
677
678         const btChunk* getChunk(int chunkIndex) const
679         {
680                 return m_chunkPtrs[chunkIndex];
681         }
682 };
683
684 ///In general it is best to use btDefaultSerializer,
685 ///in particular when writing the data to disk or sending it over the network.
686 ///The btInMemorySerializer is experimental and only suitable in a few cases.
687 ///The btInMemorySerializer takes a shortcut and can be useful to create a deep-copy
688 ///of objects. There will be a demo on how to use the btInMemorySerializer.
689 #ifdef ENABLE_INMEMORY_SERIALIZER
690
691 struct btInMemorySerializer : public btDefaultSerializer
692 {
693         btHashMap<btHashPtr, btChunk*> m_uid2ChunkPtr;
694         btHashMap<btHashPtr, void*> m_orgPtr2UniqueDataPtr;
695         btHashMap<btHashString, const void*> m_names2Ptr;
696
697         btBulletSerializedArrays m_arrays;
698
699         btInMemorySerializer(int totalSize = 0, unsigned char* buffer = 0)
700                 : btDefaultSerializer(totalSize, buffer)
701         {
702         }
703
704         virtual void startSerialization()
705         {
706                 m_uid2ChunkPtr.clear();
707                 //todo: m_arrays.clear();
708                 btDefaultSerializer::startSerialization();
709         }
710
711         btChunk* findChunkFromUniquePointer(void* uniquePointer)
712         {
713                 btChunk** chkPtr = m_uid2ChunkPtr[uniquePointer];
714                 if (chkPtr)
715                 {
716                         return *chkPtr;
717                 }
718                 return 0;
719         }
720
721         virtual void registerNameForPointer(const void* ptr, const char* name)
722         {
723                 btDefaultSerializer::registerNameForPointer(ptr, name);
724                 m_names2Ptr.insert(name, ptr);
725         }
726
727         virtual void finishSerialization()
728         {
729         }
730
731         virtual void* getUniquePointer(void* oldPtr)
732         {
733                 if (oldPtr == 0)
734                         return 0;
735
736                 // void* uniquePtr = getUniquePointer(oldPtr);
737                 btChunk* chunk = findChunkFromUniquePointer(oldPtr);
738                 if (chunk)
739                 {
740                         return chunk->m_oldPtr;
741                 }
742                 else
743                 {
744                         const char* n = (const char*)oldPtr;
745                         const void** ptr = m_names2Ptr[n];
746                         if (ptr)
747                         {
748                                 return oldPtr;
749                         }
750                         else
751                         {
752                                 void** ptr2 = m_skipPointers[oldPtr];
753                                 if (ptr2)
754                                 {
755                                         return 0;
756                                 }
757                                 else
758                                 {
759                                         //If this assert hit, serialization happened in the wrong order
760                                         // 'getUniquePointer'
761                                         btAssert(0);
762                                 }
763                         }
764                         return 0;
765                 }
766                 return oldPtr;
767         }
768
769         virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
770         {
771                 if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
772                 {
773                         btAssert(!findPointer(oldPtr));
774                 }
775
776                 chunk->m_dna_nr = getReverseType(structType);
777                 chunk->m_chunkCode = chunkCode;
778                 //void* uniquePtr = getUniquePointer(oldPtr);
779                 m_chunkP.insert(oldPtr, oldPtr);  //chunk->m_oldPtr);
780                 // chunk->m_oldPtr = uniquePtr;//oldPtr;
781
782                 void* uid = findPointer(oldPtr);
783                 m_uid2ChunkPtr.insert(uid, chunk);
784
785                 switch (chunk->m_chunkCode)
786                 {
787                         case BT_SOFTBODY_CODE:
788                         {
789 #ifdef BT_USE_DOUBLE_PRECISION
790                                 m_arrays.m_softBodyDoubleData.push_back((btSoftBodyDoubleData*)chunk->m_oldPtr);
791 #else
792                                 m_arrays.m_softBodyFloatData.push_back((btSoftBodyFloatData*)chunk->m_oldPtr);
793 #endif
794                                 break;
795                         }
796                         case BT_COLLISIONOBJECT_CODE:
797                         {
798 #ifdef BT_USE_DOUBLE_PRECISION
799                                 m_arrays.m_collisionObjectDataDouble.push_back((btCollisionObjectDoubleData*)chunk->m_oldPtr);
800 #else   //BT_USE_DOUBLE_PRECISION
801                                 m_arrays.m_collisionObjectDataFloat.push_back((btCollisionObjectFloatData*)chunk->m_oldPtr);
802 #endif  //BT_USE_DOUBLE_PRECISION
803                                 break;
804                         }
805                         case BT_RIGIDBODY_CODE:
806                         {
807 #ifdef BT_USE_DOUBLE_PRECISION
808                                 m_arrays.m_rigidBodyDataDouble.push_back((btRigidBodyDoubleData*)chunk->m_oldPtr);
809 #else
810                                 m_arrays.m_rigidBodyDataFloat.push_back((btRigidBodyFloatData*)chunk->m_oldPtr);
811 #endif  //BT_USE_DOUBLE_PRECISION
812                                 break;
813                         };
814                         case BT_CONSTRAINT_CODE:
815                         {
816 #ifdef BT_USE_DOUBLE_PRECISION
817                                 m_arrays.m_constraintDataDouble.push_back((btTypedConstraintDoubleData*)chunk->m_oldPtr);
818 #else
819                                 m_arrays.m_constraintDataFloat.push_back((btTypedConstraintFloatData*)chunk->m_oldPtr);
820 #endif
821                                 break;
822                         }
823                         case BT_QUANTIZED_BVH_CODE:
824                         {
825 #ifdef BT_USE_DOUBLE_PRECISION
826                                 m_arrays.m_bvhsDouble.push_back((btQuantizedBvhDoubleData*)chunk->m_oldPtr);
827 #else
828                                 m_arrays.m_bvhsFloat.push_back((btQuantizedBvhFloatData*)chunk->m_oldPtr);
829 #endif
830                                 break;
831                         }
832
833                         case BT_SHAPE_CODE:
834                         {
835                                 btCollisionShapeData* shapeData = (btCollisionShapeData*)chunk->m_oldPtr;
836                                 m_arrays.m_colShapeData.push_back(shapeData);
837                                 break;
838                         }
839                         case BT_TRIANLGE_INFO_MAP:
840                         case BT_ARRAY_CODE:
841                         case BT_SBMATERIAL_CODE:
842                         case BT_SBNODE_CODE:
843                         case BT_DYNAMICSWORLD_CODE:
844                         case BT_DNA_CODE:
845                         {
846                                 break;
847                         }
848                         default:
849                         {
850                         }
851                 };
852         }
853
854         int getNumChunks() const
855         {
856                 return m_uid2ChunkPtr.size();
857         }
858
859         const btChunk* getChunk(int chunkIndex) const
860         {
861                 return *m_uid2ChunkPtr.getAtIndex(chunkIndex);
862         }
863 };
864 #endif  //ENABLE_INMEMORY_SERIALIZER
865
866 #endif  //BT_SERIALIZER_H