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