Bullet Collision Detection & Physics Library
btSerializer.h
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
16 #ifndef BT_SERIALIZER_H
17 #define BT_SERIALIZER_H
18 
19 #include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
20 #include "btHashMap.h"
21 
22 #if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
23 #include <memory.h>
24 #endif
25 #include <string.h>
26 
27 
28 
30 extern char sBulletDNAstr[];
31 extern int sBulletDNAlen;
32 extern char sBulletDNAstr64[];
33 extern int sBulletDNAlen64;
34 
35 SIMD_FORCE_INLINE int btStrLen(const char* str)
36 {
37  if (!str)
38  return(0);
39  int len = 0;
40 
41  while (*str != 0)
42  {
43  str++;
44  len++;
45  }
46 
47  return len;
48 }
49 
50 
51 class btChunk
52 {
53 public:
55  int m_length;
56  void *m_oldPtr;
57  int m_dna_nr;
58  int m_number;
59 };
60 
62 {
66 };
67 
69 {
70 
71 public:
72 
73  virtual ~btSerializer() {}
74 
75  virtual const unsigned char* getBufferPointer() const = 0;
76 
77  virtual int getCurrentBufferSize() const = 0;
78 
79  virtual btChunk* allocate(size_t size, int numElements) = 0;
80 
81  virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
82 
83  virtual void* findPointer(void* oldPtr) = 0;
84 
85  virtual void* getUniquePointer(void*oldPtr) = 0;
86 
87  virtual void startSerialization() = 0;
88 
89  virtual void finishSerialization() = 0;
90 
91  virtual const char* findNameForPointer(const void* ptr) const = 0;
92 
93  virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
94 
95  virtual void serializeName(const char* ptr) = 0;
96 
97  virtual int getSerializationFlags() const = 0;
98 
99  virtual void setSerializationFlags(int flags) = 0;
100 
101 
102 };
103 
104 
105 
106 #define BT_HEADER_LENGTH 12
107 #if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
108 # define BT_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
109 #else
110 # define BT_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
111 #endif
112 
113 #define BT_SOFTBODY_CODE BT_MAKE_ID('S','B','D','Y')
114 #define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C','O','B','J')
115 #define BT_RIGIDBODY_CODE BT_MAKE_ID('R','B','D','Y')
116 #define BT_CONSTRAINT_CODE BT_MAKE_ID('C','O','N','S')
117 #define BT_BOXSHAPE_CODE BT_MAKE_ID('B','O','X','S')
118 #define BT_QUANTIZED_BVH_CODE BT_MAKE_ID('Q','B','V','H')
119 #define BT_TRIANLGE_INFO_MAP BT_MAKE_ID('T','M','A','P')
120 #define BT_SHAPE_CODE BT_MAKE_ID('S','H','A','P')
121 #define BT_ARRAY_CODE BT_MAKE_ID('A','R','A','Y')
122 #define BT_SBMATERIAL_CODE BT_MAKE_ID('S','B','M','T')
123 #define BT_SBNODE_CODE BT_MAKE_ID('S','B','N','D')
124 #define BT_DYNAMICSWORLD_CODE BT_MAKE_ID('D','W','L','D')
125 #define BT_DNA_CODE BT_MAKE_ID('D','N','A','1')
126 
127 
129 {
130  union
131  {
132  void* m_ptr;
133  int m_uniqueIds[2];
134  };
135 };
136 
140 {
141 
142 
148 
149 
151 
153 
156 
158  unsigned char* m_buffer;
160  void* m_dna;
162 
164 
165 
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  {
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  btAssert(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  btAssert(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  btAssert(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),
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
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  {
393  } else
394  {
395  initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
396  }
397 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
398 
399  }
400 
402  {
403  if (m_buffer)
405  if (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] = '2';
442 
443  }
444 
445  virtual void startSerialization()
446  {
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)
466 
468  m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize,16);
469 
470  unsigned char* currentPtr = 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);
479  currentPtr+=curLength;
480  mysize+=curLength;
481  }
482  }
483 
484  mTypes.clear();
485  mStructs.clear();
486  mTlens.clear();
488  mTypeLookup.clear();
489  m_chunkP.clear();
490  m_nameMap.clear();
492  m_chunkPtrs.clear();
493  }
494 
495  virtual void* getUniquePointer(void*oldPtr)
496  {
497  if (!oldPtr)
498  return 0;
499 
501  if (uptr)
502  {
503  return uptr->m_ptr;
504  }
506 
507  btPointerUid uid;
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  {
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 
void clear()
Definition: btHashMap.h:440
virtual void finishSerialization()=0
virtual int getCurrentBufferSize() const
Definition: btSerializer.h:520
virtual void serializeName(const char *name)
Definition: btSerializer.h:596
btAlignedObjectArray< btChunk * > m_chunkPtrs
Definition: btSerializer.h:166
void push_back(const T &_Val)
virtual int getSerializationFlags() const
Definition: btSerializer.h:625
int m_uniqueIds[2]
Definition: btSerializer.h:133
virtual void setSerializationFlags(int flags)
Definition: btSerializer.h:630
int m_number
Definition: btSerializer.h:58
virtual const unsigned char * getBufferPointer() const
Definition: btSerializer.h:515
virtual void finalizeChunk(btChunk *chunk, const char *structType, int chunkCode, void *oldPtr)
Definition: btSerializer.h:525
btHashMap< btHashPtr, const char * > m_nameMap
Definition: btSerializer.h:152
const T & at(int n) const
virtual void registerNameForPointer(const void *ptr, const char *name)
Definition: btSerializer.h:591
void writeHeader(unsigned char *buffer) const
Definition: btSerializer.h:409
virtual btChunk * allocate(size_t size, int numElements)
Definition: btSerializer.h:563
virtual void startSerialization()=0
virtual int getCurrentBufferSize() const =0
virtual void * getUniquePointer(void *oldPtr)=0
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:51
#define btAssert(x)
Definition: btScalar.h:101
#define SIMD_FORCE_INLINE
Definition: btScalar.h:58
virtual void setSerializationFlags(int flags)=0
btSerializationFlags
Definition: btSerializer.h:61
virtual void registerNameForPointer(const void *ptr, const char *name)=0
virtual void finishSerialization()
Definition: btSerializer.h:456
btHashMap< btHashString, int > mTypeLookup
Definition: btSerializer.h:147
virtual void * findPointer(void *oldPtr)
Definition: btSerializer.h:170
virtual void * getUniquePointer(void *oldPtr)
Definition: btSerializer.h:495
btHashMap< btHashInt, int > mStructReverse
Definition: btSerializer.h:146
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
The btDefaultSerializer is the main Bullet serialization class.
Definition: btSerializer.h:139
int m_chunkCode
Definition: btSerializer.h:54
virtual ~btSerializer()
Definition: btSerializer.h:73
virtual unsigned char * internalAlloc(size_t size)
Definition: btSerializer.h:544
int size() const
return the number of elements in the array
virtual int getSerializationFlags() const =0
unsigned char * m_buffer
Definition: btSerializer.h:158
virtual const unsigned char * getBufferPointer() const =0
#define BT_HEADER_LENGTH
Definition: btSerializer.h:106
int sBulletDNAlen
void initDNA(const char *bdnaOrg, int dnalen)
Definition: btSerializer.h:200
btAlignedObjectArray< short * > mStructs
Definition: btSerializer.h:144
#define btAlignedFree(ptr)
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:269
btAlignedObjectArray< char * > mTypes
Definition: btSerializer.h:143
int btStrLen(const char *str)
Definition: btSerializer.h:35
#define BT_ARRAY_CODE
Definition: btSerializer.h:121
btDefaultSerializer(int totalSize=0)
Definition: btSerializer.h:361
const Value * find(const Key &key) const
Definition: btHashMap.h:402
virtual void finalizeChunk(btChunk *chunk, const char *structType, int chunkCode, void *oldPtr)=0
very basic hashable string implementation, compatible with btHashMap
Definition: btHashMap.h:23
virtual void serializeName(const char *ptr)=0
int sBulletDNAlen64
virtual const char * findNameForPointer(const void *ptr) const
Definition: btSerializer.h:582
virtual void startSerialization()
Definition: btSerializer.h:445
btAlignedObjectArray< short > mTlens
Definition: btSerializer.h:145
int m_length
Definition: btSerializer.h:55
unsigned btSwapEndian(unsigned val)
Definition: btScalar.h:544
#define btAlignedAlloc(size, alignment)
int getReverseType(const char *type) const
Definition: btSerializer.h:189
T * btAlignPointer(T *unalignedPtr, size_t alignment)
align a pointer to the provided alignment, upwards
Definition: btScalar.h:710
virtual const char * findNameForPointer(const void *ptr) const =0
btHashMap< btHashPtr, btPointerUid > m_uniquePointers
Definition: btSerializer.h:154
virtual void * findPointer(void *oldPtr)=0
virtual ~btDefaultSerializer()
Definition: btSerializer.h:401
btHashMap< btHashPtr, void * > m_chunkP
Definition: btSerializer.h:150
#define BT_DNA_CODE
Definition: btSerializer.h:125
void * m_oldPtr
Definition: btSerializer.h:56
char sBulletDNAstr[]
only the 32bit versions for now
Definition: btSerializer.cpp:1
int m_dna_nr
Definition: btSerializer.h:57
virtual btChunk * allocate(size_t size, int numElements)=0
char sBulletDNAstr64[]