source: trunk/src/bullet/LinearMath/btSerializer.h @ 1570

Last change on this file since 1570 was 1570, checked in by sam, 10 years ago

core: add the whole BulletPhysics source code to the engine core, because
that’s precisely how they want us to use it.

  • Property svn:keywords set to Id
File size: 12.9 KB
Line 
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. 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
31extern char sBulletDNAstr[];
32extern int sBulletDNAlen;
33extern char sBulletDNAstr64[];
34extern int sBulletDNAlen64;
35
36SIMD_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
52class btChunk
53{
54public:
55        int             m_chunkCode;
56        int             m_length;
57        void    *m_oldPtr;
58        int             m_dna_nr;
59        int             m_number;
60};
61
62enum    btSerializationFlags
63{
64        BT_SERIALIZE_NO_BVH = 1,
65        BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
66        BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4
67};
68
69class   btSerializer
70{
71
72public:
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
128struct  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.
139class 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       
168protected:
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
356public:
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
Note: See TracBrowser for help on using the repository browser.