Initialize libbullet git in 2.0_beta.
[platform/upstream/libbullet.git] / 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 "btStackAlloc.h"
21 #include "btHashMap.h"
22
23 #if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
24 #include <memory.h>
25 #endif
26 #include <string.h>
27
28
29
30 ///only the 32bit versions for now
31 extern char sBulletDNAstr[];
32 extern int sBulletDNAlen;
33 extern char sBulletDNAstr64[];
34 extern int sBulletDNAlen64;
35
36 SIMD_FORCE_INLINE       int btStrLen(const char* str) 
37 {
38     if (!str) 
39                 return(0);
40         int len = 0;
41     
42         while (*str != 0)
43         {
44         str++;
45         len++;
46     }
47
48     return len;
49 }
50
51
52 class btChunk
53 {
54 public:
55         int             m_chunkCode;
56         int             m_length;
57         void    *m_oldPtr;
58         int             m_dna_nr;
59         int             m_number;
60 };
61
62 enum    btSerializationFlags
63 {
64         BT_SERIALIZE_NO_BVH = 1,
65         BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
66         BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4
67 };
68
69 class   btSerializer
70 {
71
72 public:
73
74         virtual ~btSerializer() {}
75
76         virtual const unsigned char*            getBufferPointer() const = 0;
77
78         virtual int             getCurrentBufferSize() const = 0;
79
80         virtual btChunk*        allocate(size_t size, int numElements) = 0;
81
82         virtual void    finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
83
84         virtual  void*  findPointer(void* oldPtr)  = 0;
85
86         virtual void*   getUniquePointer(void*oldPtr) = 0;
87
88         virtual void    startSerialization() = 0;
89         
90         virtual void    finishSerialization() = 0;
91
92         virtual const char*     findNameForPointer(const void* ptr) const = 0;
93
94         virtual void    registerNameForPointer(const void* ptr, const char* name) = 0;
95
96         virtual void    serializeName(const char* ptr) = 0;
97
98         virtual int             getSerializationFlags() const = 0;
99
100         virtual void    setSerializationFlags(int flags) = 0;
101
102
103 };
104
105
106
107 #define BT_HEADER_LENGTH 12
108 #if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
109 #       define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
110 #else
111 #       define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
112 #endif
113
114 #define BT_SOFTBODY_CODE                MAKE_ID('S','B','D','Y')
115 #define BT_COLLISIONOBJECT_CODE MAKE_ID('C','O','B','J')
116 #define BT_RIGIDBODY_CODE               MAKE_ID('R','B','D','Y')
117 #define BT_CONSTRAINT_CODE              MAKE_ID('C','O','N','S')
118 #define BT_BOXSHAPE_CODE                MAKE_ID('B','O','X','S')
119 #define BT_QUANTIZED_BVH_CODE   MAKE_ID('Q','B','V','H')
120 #define BT_TRIANLGE_INFO_MAP    MAKE_ID('T','M','A','P')
121 #define BT_SHAPE_CODE                   MAKE_ID('S','H','A','P')
122 #define BT_ARRAY_CODE                   MAKE_ID('A','R','A','Y')
123 #define BT_SBMATERIAL_CODE              MAKE_ID('S','B','M','T')
124 #define BT_SBNODE_CODE                  MAKE_ID('S','B','N','D')
125 #define BT_DNA_CODE                             MAKE_ID('D','N','A','1')
126
127
128 struct  btPointerUid
129 {
130         union
131         {
132                 void*   m_ptr;
133                 int             m_uniqueIds[2];
134         };
135 };
136
137 ///The btDefaultSerializer is the main Bullet serialization class.
138 ///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
139 class btDefaultSerializer       :       public btSerializer
140 {
141
142
143         btAlignedObjectArray<char*>                     mTypes;
144         btAlignedObjectArray<short*>                    mStructs;
145         btAlignedObjectArray<short>                     mTlens;
146         btHashMap<btHashInt, int>                       mStructReverse;
147         btHashMap<btHashString,int>     mTypeLookup;
148
149         
150         btHashMap<btHashPtr,void*>      m_chunkP;
151         
152         btHashMap<btHashPtr,const char*>        m_nameMap;
153
154         btHashMap<btHashPtr,btPointerUid>       m_uniquePointers;
155         int     m_uniqueIdGenerator;
156
157         int                                     m_totalSize;
158         unsigned char*          m_buffer;
159         int                                     m_currentSize;
160         void*                           m_dna;
161         int                                     m_dnaLength;
162
163         int                                     m_serializationFlags;
164
165
166         btAlignedObjectArray<btChunk*>  m_chunkPtrs;
167         
168 protected:
169
170         virtual void*   findPointer(void* oldPtr) 
171         {
172                 void** ptr = m_chunkP.find(oldPtr);
173                 if (ptr && *ptr)
174                         return *ptr;
175                 return 0;
176         }
177
178         
179
180
181
182                 void    writeDNA()
183                 {
184                         btChunk* dnaChunk = allocate(m_dnaLength,1);
185                         memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
186                         finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna);
187                 }
188
189                 int getReverseType(const char *type) const
190                 {
191
192                         btHashString key(type);
193                         const int* valuePtr = mTypeLookup.find(key);
194                         if (valuePtr)
195                                 return *valuePtr;
196                         
197                         return -1;
198                 }
199
200                 void initDNA(const char* bdnaOrg,int dnalen)
201                 {
202                         ///was already initialized
203                         if (m_dna)
204                                 return;
205
206                         int littleEndian= 1;
207                         littleEndian= ((char*)&littleEndian)[0];
208                         
209
210                         m_dna = btAlignedAlloc(dnalen,16);
211                         memcpy(m_dna,bdnaOrg,dnalen);
212                         m_dnaLength = dnalen;
213
214                         int *intPtr=0;
215                         short *shtPtr=0;
216                         char *cp = 0;int dataLen =0;
217                         intPtr = (int*)m_dna;
218
219                         /*
220                                 SDNA (4 bytes) (magic number)
221                                 NAME (4 bytes)
222                                 <nr> (4 bytes) amount of names (int)
223                                 <string>
224                                 <string>
225                         */
226
227                         if (strncmp((const char*)m_dna, "SDNA", 4)==0)
228                         {
229                                 // skip ++ NAME
230                                 intPtr++; intPtr++;
231                         }
232
233                         // Parse names
234                         if (!littleEndian)
235                                 *intPtr = btSwapEndian(*intPtr);
236                                 
237                         dataLen = *intPtr;
238                         
239                         intPtr++;
240
241                         cp = (char*)intPtr;
242                         int i;
243                         for ( i=0; i<dataLen; i++)
244                         {
245                                 
246                                 while (*cp)cp++;
247                                 cp++;
248                         }
249                         cp = btAlignPointer(cp,4);
250
251                         /*
252                                 TYPE (4 bytes)
253                                 <nr> amount of types (int)
254                                 <string>
255                                 <string>
256                         */
257
258                         intPtr = (int*)cp;
259                         assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
260
261                         if (!littleEndian)
262                                 *intPtr =  btSwapEndian(*intPtr);
263                         
264                         dataLen = *intPtr;
265                         intPtr++;
266
267                         
268                         cp = (char*)intPtr;
269                         for (i=0; i<dataLen; i++)
270                         {
271                                 mTypes.push_back(cp);
272                                 while (*cp)cp++;
273                                 cp++;
274                         }
275
276                         cp = btAlignPointer(cp,4);
277
278
279                         /*
280                                 TLEN (4 bytes)
281                                 <len> (short) the lengths of types
282                                 <len>
283                         */
284
285                         // Parse type lens
286                         intPtr = (int*)cp;
287                         assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
288
289                         dataLen = (int)mTypes.size();
290
291                         shtPtr = (short*)intPtr;
292                         for (i=0; i<dataLen; i++, shtPtr++)
293                         {
294                                 if (!littleEndian)
295                                         shtPtr[0] = btSwapEndian(shtPtr[0]);
296                                 mTlens.push_back(shtPtr[0]);
297                         }
298
299                         if (dataLen & 1) shtPtr++;
300
301                         /*
302                                 STRC (4 bytes)
303                                 <nr> amount of structs (int)
304                                 <typenr>
305                                 <nr_of_elems>
306                                 <typenr>
307                                 <namenr>
308                                 <typenr>
309                                 <namenr>
310                         */
311
312                         intPtr = (int*)shtPtr;
313                         cp = (char*)intPtr;
314                         assert(strncmp(cp, "STRC", 4)==0); intPtr++;
315
316                         if (!littleEndian)
317                                 *intPtr = btSwapEndian(*intPtr);
318                         dataLen = *intPtr ; 
319                         intPtr++;
320
321
322                         shtPtr = (short*)intPtr;
323                         for (i=0; i<dataLen; i++)
324                         {
325                                 mStructs.push_back (shtPtr);
326                                 
327                                 if (!littleEndian)
328                                 {
329                                         shtPtr[0]= btSwapEndian(shtPtr[0]);
330                                         shtPtr[1]= btSwapEndian(shtPtr[1]);
331
332                                         int len = shtPtr[1];
333                                         shtPtr+= 2;
334
335                                         for (int a=0; a<len; a++, shtPtr+=2)
336                                         {
337                                                         shtPtr[0]= btSwapEndian(shtPtr[0]);
338                                                         shtPtr[1]= btSwapEndian(shtPtr[1]);
339                                         }
340
341                                 } else
342                                 {
343                                         shtPtr+= (2*shtPtr[1])+2;
344                                 }
345                         }
346
347                         // build reverse lookups
348                         for (i=0; i<(int)mStructs.size(); i++)
349                         {
350                                 short *strc = mStructs.at(i);
351                                 mStructReverse.insert(strc[0], i);
352                                 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
353                         }
354                 }
355
356 public: 
357         
358
359         
360
361                 btDefaultSerializer(int totalSize=0)
362                         :m_totalSize(totalSize),
363                         m_currentSize(0),
364                         m_dna(0),
365                         m_dnaLength(0),
366                         m_serializationFlags(0)
367                 {
368                         m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0;
369                         
370                         const bool VOID_IS_8 = ((sizeof(void*)==8));
371
372 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
373                         if (VOID_IS_8)
374                         {
375 #if _WIN64
376                                 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
377 #else
378                                 btAssert(0);
379 #endif
380                         } else
381                         {
382 #ifndef _WIN64
383                                 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
384 #else
385                                 btAssert(0);
386 #endif
387                         }
388         
389 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
390                         if (VOID_IS_8)
391                         {
392                                 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
393                         } else
394                         {
395                                 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
396                         }
397 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
398         
399                 }
400
401                 virtual ~btDefaultSerializer() 
402                 {
403                         if (m_buffer)
404                                 btAlignedFree(m_buffer);
405                         if (m_dna)
406                                 btAlignedFree(m_dna);
407                 }
408
409                 void    writeHeader(unsigned char* buffer) const
410                 {
411                         
412
413 #ifdef  BT_USE_DOUBLE_PRECISION
414                         memcpy(buffer, "BULLETd", 7);
415 #else
416                         memcpy(buffer, "BULLETf", 7);
417 #endif //BT_USE_DOUBLE_PRECISION
418         
419                         int littleEndian= 1;
420                         littleEndian= ((char*)&littleEndian)[0];
421
422                         if (sizeof(void*)==8)
423                         {
424                                 buffer[7] = '-';
425                         } else
426                         {
427                                 buffer[7] = '_';
428                         }
429
430                         if (littleEndian)
431                         {
432                                 buffer[8]='v';                          
433                         } else
434                         {
435                                 buffer[8]='V';
436                         }
437
438
439                         buffer[9] = '2';
440                         buffer[10] = '8';
441                         buffer[11] = '0';
442
443                 }
444
445                 virtual void    startSerialization()
446                 {
447                         m_uniqueIdGenerator= 1;
448                         if (m_totalSize)
449                         {
450                                 unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
451                                 writeHeader(buffer);
452                         }
453                         
454                 }
455
456                 virtual void    finishSerialization()
457                 {
458                         writeDNA();
459
460                         //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
461                         int mysize = 0;
462                         if (!m_totalSize)
463                         {
464                                 if (m_buffer)
465                                         btAlignedFree(m_buffer);
466
467                                 m_currentSize += BT_HEADER_LENGTH;
468                                 m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize,16);
469
470                                 unsigned char* currentPtr = m_buffer;
471                                 writeHeader(m_buffer);
472                                 currentPtr += BT_HEADER_LENGTH;
473                                 mysize+=BT_HEADER_LENGTH;
474                                 for (int i=0;i< m_chunkPtrs.size();i++)
475                                 {
476                                         int curLength = sizeof(btChunk)+m_chunkPtrs[i]->m_length;
477                                         memcpy(currentPtr,m_chunkPtrs[i], curLength);
478                                         btAlignedFree(m_chunkPtrs[i]);
479                                         currentPtr+=curLength;
480                                         mysize+=curLength;
481                                 }
482                         }
483
484                         mTypes.clear();
485                         mStructs.clear();
486                         mTlens.clear();
487                         mStructReverse.clear();
488                         mTypeLookup.clear();
489                         m_chunkP.clear();
490                         m_nameMap.clear();
491                         m_uniquePointers.clear();
492                         m_chunkPtrs.clear();
493                 }
494
495                 virtual void*   getUniquePointer(void*oldPtr)
496                 {
497                         if (!oldPtr)
498                                 return 0;
499
500                         btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
501                         if (uptr)
502                         {
503                                 return uptr->m_ptr;
504                         }
505                         m_uniqueIdGenerator++;
506                         
507                         btPointerUid uid;
508                         uid.m_uniqueIds[0] = m_uniqueIdGenerator;
509                         uid.m_uniqueIds[1] = m_uniqueIdGenerator;
510                         m_uniquePointers.insert(oldPtr,uid);
511                         return uid.m_ptr;
512
513                 }
514
515                 virtual const unsigned char*            getBufferPointer() const
516                 {
517                         return m_buffer;
518                 }
519
520                 virtual int                                     getCurrentBufferSize() const
521                 {
522                         return  m_currentSize;
523                 }
524
525                 virtual void    finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
526                 {
527                         if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
528                         {
529                                 btAssert(!findPointer(oldPtr));
530                         }
531
532                         chunk->m_dna_nr = getReverseType(structType);
533                         
534                         chunk->m_chunkCode = chunkCode;
535                         
536                         void* uniquePtr = getUniquePointer(oldPtr);
537                         
538                         m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
539                         chunk->m_oldPtr = uniquePtr;//oldPtr;
540                         
541                 }
542
543                 
544                 virtual unsigned char* internalAlloc(size_t size)
545                 {
546                         unsigned char* ptr = 0;
547
548                         if (m_totalSize)
549                         {
550                                 ptr = m_buffer+m_currentSize;
551                                 m_currentSize += int(size);
552                                 btAssert(m_currentSize<m_totalSize);
553                         } else
554                         {
555                                 ptr = (unsigned char*)btAlignedAlloc(size,16);
556                                 m_currentSize += int(size);
557                         }
558                         return ptr;
559                 }
560
561                 
562
563                 virtual btChunk*        allocate(size_t size, int numElements)
564                 {
565
566                         unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(btChunk));
567
568                         unsigned char* data = ptr + sizeof(btChunk);
569                         
570                         btChunk* chunk = (btChunk*)ptr;
571                         chunk->m_chunkCode = 0;
572                         chunk->m_oldPtr = data;
573                         chunk->m_length = int(size)*numElements;
574                         chunk->m_number = numElements;
575                         
576                         m_chunkPtrs.push_back(chunk);
577                         
578
579                         return chunk;
580                 }
581
582                 virtual const char*     findNameForPointer(const void* ptr) const
583                 {
584                         const char*const * namePtr = m_nameMap.find(ptr);
585                         if (namePtr && *namePtr)
586                                 return *namePtr;
587                         return 0;
588
589                 }
590
591                 virtual void    registerNameForPointer(const void* ptr, const char* name)
592                 {
593                         m_nameMap.insert(ptr,name);
594                 }
595
596                 virtual void    serializeName(const char* name)
597                 {
598                         if (name)
599                         {
600                                 //don't serialize name twice
601                                 if (findPointer((void*)name))
602                                         return;
603
604                                 int len = btStrLen(name);
605                                 if (len)
606                                 {
607
608                                         int newLen = len+1;
609                                         int padding = ((newLen+3)&~3)-newLen;
610                                         newLen += padding;
611
612                                         //serialize name string now
613                                         btChunk* chunk = allocate(sizeof(char),newLen);
614                                         char* destinationName = (char*)chunk->m_oldPtr;
615                                         for (int i=0;i<len;i++)
616                                         {
617                                                 destinationName[i] = name[i];
618                                         }
619                                         destinationName[len] = 0;
620                                         finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
621                                 }
622                         }
623                 }
624
625                 virtual int             getSerializationFlags() const
626                 {
627                         return m_serializationFlags;
628                 }
629
630                 virtual void    setSerializationFlags(int flags)
631                 {
632                         m_serializationFlags = flags;
633                 }
634
635 };
636
637
638 #endif //BT_SERIALIZER_H
639