Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/external/bullet/LinearMath/btSerializer.h @ 12089

Last change on this file since 12089 was 11115, checked in by landauf, 9 years ago

fixed code to compile in 64bit mode

  • Property svn:eol-style set to native
File size: 13.1 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 unsigned char sBulletDNAstr[];
32extern int sBulletDNAlen;
33extern unsigned 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;long nr=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                        {
250                                nr= (long long)cp;
251                        //      long mask=3;
252                                nr= ((nr+3)&~3)-nr;
253                                while (nr--)
254                                {
255                                        cp++;
256                                }
257                        }
258
259                        /*
260                                TYPE (4 bytes)
261                                <nr> amount of types (int)
262                                <string>
263                                <string>
264                        */
265
266                        intPtr = (int*)cp;
267                        assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
268
269                        if (!littleEndian)
270                                *intPtr =  btSwapEndian(*intPtr);
271                       
272                        dataLen = *intPtr;
273                        intPtr++;
274
275                       
276                        cp = (char*)intPtr;
277                        for (i=0; i<dataLen; i++)
278                        {
279                                mTypes.push_back(cp);
280                                while (*cp)cp++;
281                                cp++;
282                        }
283
284                {
285                                nr= (long long)cp;
286                        //      long mask=3;
287                                nr= ((nr+3)&~3)-nr;
288                                while (nr--)
289                                {
290                                        cp++;
291                                }
292                        }
293
294
295                        /*
296                                TLEN (4 bytes)
297                                <len> (short) the lengths of types
298                                <len>
299                        */
300
301                        // Parse type lens
302                        intPtr = (int*)cp;
303                        assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
304
305                        dataLen = (int)mTypes.size();
306
307                        shtPtr = (short*)intPtr;
308                        for (i=0; i<dataLen; i++, shtPtr++)
309                        {
310                                if (!littleEndian)
311                                        shtPtr[0] = btSwapEndian(shtPtr[0]);
312                                mTlens.push_back(shtPtr[0]);
313                        }
314
315                        if (dataLen & 1) shtPtr++;
316
317                        /*
318                                STRC (4 bytes)
319                                <nr> amount of structs (int)
320                                <typenr>
321                                <nr_of_elems>
322                                <typenr>
323                                <namenr>
324                                <typenr>
325                                <namenr>
326                        */
327
328                        intPtr = (int*)shtPtr;
329                        cp = (char*)intPtr;
330                        assert(strncmp(cp, "STRC", 4)==0); intPtr++;
331
332                        if (!littleEndian)
333                                *intPtr = btSwapEndian(*intPtr);
334                        dataLen = *intPtr ; 
335                        intPtr++;
336
337
338                        shtPtr = (short*)intPtr;
339                        for (i=0; i<dataLen; i++)
340                        {
341                                mStructs.push_back (shtPtr);
342                               
343                                if (!littleEndian)
344                                {
345                                        shtPtr[0]= btSwapEndian(shtPtr[0]);
346                                        shtPtr[1]= btSwapEndian(shtPtr[1]);
347
348                                        int len = shtPtr[1];
349                                        shtPtr+= 2;
350
351                                        for (int a=0; a<len; a++, shtPtr+=2)
352                                        {
353                                                        shtPtr[0]= btSwapEndian(shtPtr[0]);
354                                                        shtPtr[1]= btSwapEndian(shtPtr[1]);
355                                        }
356
357                                } else
358                                {
359                                        shtPtr+= (2*shtPtr[1])+2;
360                                }
361                        }
362
363                        // build reverse lookups
364                        for (i=0; i<(int)mStructs.size(); i++)
365                        {
366                                short *strc = mStructs.at(i);
367                                mStructReverse.insert(strc[0], i);
368                                mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
369                        }
370                }
371
372public: 
373       
374
375       
376
377                btDefaultSerializer(int totalSize=0)
378                        :m_totalSize(totalSize),
379                        m_currentSize(0),
380                        m_dna(0),
381                        m_dnaLength(0),
382                        m_serializationFlags(0)
383                {
384                        m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0;
385                       
386                        const bool VOID_IS_8 = ((sizeof(void*)==8));
387
388#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
389                        if (VOID_IS_8)
390                        {
391#if _WIN64
392                                initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
393#else
394                                btAssert(0);
395#endif
396                        } else
397                        {
398#ifndef _WIN64
399                                initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
400#else
401                                btAssert(0);
402#endif
403                        }
404       
405#else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
406                        if (VOID_IS_8)
407                        {
408                                initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
409                        } else
410                        {
411                                initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
412                        }
413#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
414       
415                }
416
417                virtual ~btDefaultSerializer() 
418                {
419                        if (m_buffer)
420                                btAlignedFree(m_buffer);
421                        if (m_dna)
422                                btAlignedFree(m_dna);
423                }
424
425                void    writeHeader(unsigned char* buffer) const
426                {
427                       
428
429#ifdef  BT_USE_DOUBLE_PRECISION
430                        memcpy(buffer, "BULLETd", 7);
431#else
432                        memcpy(buffer, "BULLETf", 7);
433#endif //BT_USE_DOUBLE_PRECISION
434       
435                        int littleEndian= 1;
436                        littleEndian= ((char*)&littleEndian)[0];
437
438                        if (sizeof(void*)==8)
439                        {
440                                buffer[7] = '-';
441                        } else
442                        {
443                                buffer[7] = '_';
444                        }
445
446                        if (littleEndian)
447                        {
448                                buffer[8]='v';                         
449                        } else
450                        {
451                                buffer[8]='V';
452                        }
453
454
455                        buffer[9] = '2';
456                        buffer[10] = '7';
457                        buffer[11] = '8';
458
459                }
460
461                virtual void    startSerialization()
462                {
463                        m_uniqueIdGenerator= 1;
464                        if (m_totalSize)
465                        {
466                                unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
467                                writeHeader(buffer);
468                        }
469                       
470                }
471
472                virtual void    finishSerialization()
473                {
474                        writeDNA();
475
476                        //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
477                        int mysize = 0;
478                        if (!m_totalSize)
479                        {
480                                if (m_buffer)
481                                        btAlignedFree(m_buffer);
482
483                                m_currentSize += BT_HEADER_LENGTH;
484                                m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize,16);
485
486                                unsigned char* currentPtr = m_buffer;
487                                writeHeader(m_buffer);
488                                currentPtr += BT_HEADER_LENGTH;
489                                mysize+=BT_HEADER_LENGTH;
490                                for (int i=0;i< m_chunkPtrs.size();i++)
491                                {
492                                        int curLength = sizeof(btChunk)+m_chunkPtrs[i]->m_length;
493                                        memcpy(currentPtr,m_chunkPtrs[i], curLength);
494                                        btAlignedFree(m_chunkPtrs[i]);
495                                        currentPtr+=curLength;
496                                        mysize+=curLength;
497                                }
498                        }
499
500                        mTypes.clear();
501                        mStructs.clear();
502                        mTlens.clear();
503                        mStructReverse.clear();
504                        mTypeLookup.clear();
505                        m_chunkP.clear();
506                        m_nameMap.clear();
507                        m_uniquePointers.clear();
508                        m_chunkPtrs.clear();
509                }
510
511                virtual void*   getUniquePointer(void*oldPtr)
512                {
513                        if (!oldPtr)
514                                return 0;
515
516                        btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
517                        if (uptr)
518                        {
519                                return uptr->m_ptr;
520                        }
521                        m_uniqueIdGenerator++;
522                       
523                        btPointerUid uid;
524                        uid.m_uniqueIds[0] = m_uniqueIdGenerator;
525                        uid.m_uniqueIds[1] = m_uniqueIdGenerator;
526                        m_uniquePointers.insert(oldPtr,uid);
527                        return uid.m_ptr;
528
529                }
530
531                virtual const unsigned char*            getBufferPointer() const
532                {
533                        return m_buffer;
534                }
535
536                virtual int                                     getCurrentBufferSize() const
537                {
538                        return  m_currentSize;
539                }
540
541                virtual void    finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
542                {
543                        if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
544                        {
545                                btAssert(!findPointer(oldPtr));
546                        }
547
548                        chunk->m_dna_nr = getReverseType(structType);
549                       
550                        chunk->m_chunkCode = chunkCode;
551                       
552                        void* uniquePtr = getUniquePointer(oldPtr);
553                       
554                        m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
555                        chunk->m_oldPtr = uniquePtr;//oldPtr;
556                       
557                }
558
559               
560                virtual unsigned char* internalAlloc(size_t size)
561                {
562                        unsigned char* ptr = 0;
563
564                        if (m_totalSize)
565                        {
566                                ptr = m_buffer+m_currentSize;
567                                m_currentSize += int(size);
568                                btAssert(m_currentSize<m_totalSize);
569                        } else
570                        {
571                                ptr = (unsigned char*)btAlignedAlloc(size,16);
572                                m_currentSize += int(size);
573                        }
574                        return ptr;
575                }
576
577               
578
579                virtual btChunk*        allocate(size_t size, int numElements)
580                {
581
582                        unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(btChunk));
583
584                        unsigned char* data = ptr + sizeof(btChunk);
585                       
586                        btChunk* chunk = (btChunk*)ptr;
587                        chunk->m_chunkCode = 0;
588                        chunk->m_oldPtr = data;
589                        chunk->m_length = int(size)*numElements;
590                        chunk->m_number = numElements;
591                       
592                        m_chunkPtrs.push_back(chunk);
593                       
594
595                        return chunk;
596                }
597
598                virtual const char*     findNameForPointer(const void* ptr) const
599                {
600                        const char*const * namePtr = m_nameMap.find(ptr);
601                        if (namePtr && *namePtr)
602                                return *namePtr;
603                        return 0;
604
605                }
606
607                virtual void    registerNameForPointer(const void* ptr, const char* name)
608                {
609                        m_nameMap.insert(ptr,name);
610                }
611
612                virtual void    serializeName(const char* name)
613                {
614                        if (name)
615                        {
616                                //don't serialize name twice
617                                if (findPointer((void*)name))
618                                        return;
619
620                                int len = btStrLen(name);
621                                if (len)
622                                {
623
624                                        int newLen = len+1;
625                                        int padding = ((newLen+3)&~3)-newLen;
626                                        newLen += padding;
627
628                                        //serialize name string now
629                                        btChunk* chunk = allocate(sizeof(char),newLen);
630                                        char* destinationName = (char*)chunk->m_oldPtr;
631                                        for (int i=0;i<len;i++)
632                                        {
633                                                destinationName[i] = name[i];
634                                        }
635                                        destinationName[len] = 0;
636                                        finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
637                                }
638                        }
639                }
640
641                virtual int             getSerializationFlags() const
642                {
643                        return m_serializationFlags;
644                }
645
646                virtual void    setSerializationFlags(int flags)
647                {
648                        m_serializationFlags = flags;
649                }
650
651};
652
653
654#endif //BT_SERIALIZER_H
655
Note: See TracBrowser for help on using the repository browser.