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 29 ///only the 32bit versions for now 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: 54 int m_chunkCode; 55 int m_length; 56 void *m_oldPtr; 57 int m_dna_nr; 58 int m_number; 59 }; 60 61 enum btSerializationFlags 62 { 63 BT_SERIALIZE_NO_BVH = 1, 64 BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2, 65 BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4 66 }; 67 68 class btSerializer 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 virtual int getNumChunks() const = 0; 102 103 virtual const btChunk* getChunk(int chunkIndex) const = 0; 104 105 }; 106 107 108 109 #define BT_HEADER_LENGTH 12 110 #if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) 111 # define BT_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) ) 112 #else 113 # define BT_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) ) 114 #endif 115 116 117 #define BT_MULTIBODY_CODE BT_MAKE_ID('M','B','D','Y') 118 #define BT_SOFTBODY_CODE BT_MAKE_ID('S','B','D','Y') 119 #define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C','O','B','J') 120 #define BT_RIGIDBODY_CODE BT_MAKE_ID('R','B','D','Y') 121 #define BT_CONSTRAINT_CODE BT_MAKE_ID('C','O','N','S') 122 #define BT_BOXSHAPE_CODE BT_MAKE_ID('B','O','X','S') 123 #define BT_QUANTIZED_BVH_CODE BT_MAKE_ID('Q','B','V','H') 124 #define BT_TRIANLGE_INFO_MAP BT_MAKE_ID('T','M','A','P') 125 #define BT_SHAPE_CODE BT_MAKE_ID('S','H','A','P') 126 #define BT_ARRAY_CODE BT_MAKE_ID('A','R','A','Y') 127 #define BT_SBMATERIAL_CODE BT_MAKE_ID('S','B','M','T') 128 #define BT_SBNODE_CODE BT_MAKE_ID('S','B','N','D') 129 #define BT_DYNAMICSWORLD_CODE BT_MAKE_ID('D','W','L','D') 130 #define BT_DNA_CODE BT_MAKE_ID('D','N','A','1') 131 132 133 struct btPointerUid 134 { 135 union 136 { 137 void* m_ptr; 138 int m_uniqueIds[2]; 139 }; 140 }; 141 142 struct btBulletSerializedArrays 143 { 144 btBulletSerializedArrays() 145 { 146 } 147 btAlignedObjectArray<struct btQuantizedBvhDoubleData*> m_bvhsDouble; 148 btAlignedObjectArray<struct btQuantizedBvhFloatData*> m_bvhsFloat; 149 btAlignedObjectArray<struct btCollisionShapeData*> m_colShapeData; 150 btAlignedObjectArray<struct btDynamicsWorldDoubleData*> m_dynamicWorldInfoDataDouble; 151 btAlignedObjectArray<struct btDynamicsWorldFloatData*> m_dynamicWorldInfoDataFloat; 152 btAlignedObjectArray<struct btRigidBodyDoubleData*> m_rigidBodyDataDouble; 153 btAlignedObjectArray<struct btRigidBodyFloatData*> m_rigidBodyDataFloat; 154 btAlignedObjectArray<struct btCollisionObjectDoubleData*> m_collisionObjectDataDouble; 155 btAlignedObjectArray<struct btCollisionObjectFloatData*> m_collisionObjectDataFloat; 156 btAlignedObjectArray<struct btTypedConstraintFloatData*> m_constraintDataFloat; 157 btAlignedObjectArray<struct btTypedConstraintDoubleData*> m_constraintDataDouble; 158 btAlignedObjectArray<struct btTypedConstraintData*> m_constraintData;//for backwards compatibility 159 btAlignedObjectArray<struct btSoftBodyFloatData*> m_softBodyFloatData; 160 btAlignedObjectArray<struct btSoftBodyDoubleData*> m_softBodyDoubleData; 161 162 }; 163 164 165 ///The btDefaultSerializer is the main Bullet serialization class. 166 ///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero. 167 class btDefaultSerializer : public btSerializer 168 { 169 170 protected: 171 172 btAlignedObjectArray<char*> mTypes; 173 btAlignedObjectArray<short*> mStructs; 174 btAlignedObjectArray<short> mTlens; 175 btHashMap<btHashInt, int> mStructReverse; 176 btHashMap<btHashString,int> mTypeLookup; 177 178 179 180 btHashMap<btHashPtr,void*> m_chunkP; 181 182 btHashMap<btHashPtr,const char*> m_nameMap; 183 184 btHashMap<btHashPtr,btPointerUid> m_uniquePointers; 185 int m_uniqueIdGenerator; 186 187 int m_totalSize; 188 unsigned char* m_buffer; 189 bool m_ownsBuffer; 190 int m_currentSize; 191 void* m_dna; 192 int m_dnaLength; 193 194 int m_serializationFlags; 195 196 197 btAlignedObjectArray<btChunk*> m_chunkPtrs; 198 199 protected: 200 201 202 virtual void* findPointer(void* oldPtr) 203 { 204 void** ptr = m_chunkP.find(oldPtr); 205 if (ptr && *ptr) 206 return *ptr; 207 return 0; 208 } 209 210 211 212 213 214 virtual void writeDNA() 215 { 216 btChunk* dnaChunk = allocate(m_dnaLength,1); 217 memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength); 218 finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna); 219 } 220 221 int getReverseType(const char *type) const 222 { 223 224 btHashString key(type); 225 const int* valuePtr = mTypeLookup.find(key); 226 if (valuePtr) 227 return *valuePtr; 228 229 return -1; 230 } 231 232 void initDNA(const char* bdnaOrg,int dnalen) 233 { 234 ///was already initialized 235 if (m_dna) 236 return; 237 238 int littleEndian= 1; 239 littleEndian= ((char*)&littleEndian)[0]; 240 241 242 m_dna = btAlignedAlloc(dnalen,16); 243 memcpy(m_dna,bdnaOrg,dnalen); 244 m_dnaLength = dnalen; 245 246 int *intPtr=0; 247 short *shtPtr=0; 248 char *cp = 0;int dataLen =0; 249 intPtr = (int*)m_dna; 250 251 /* 252 SDNA (4 bytes) (magic number) 253 NAME (4 bytes) 254 <nr> (4 bytes) amount of names (int) 255 <string> 256 <string> 257 */ 258 259 if (strncmp((const char*)m_dna, "SDNA", 4)==0) 260 { 261 // skip ++ NAME 262 intPtr++; intPtr++; 263 } 264 265 // Parse names 266 if (!littleEndian) 267 *intPtr = btSwapEndian(*intPtr); 268 269 dataLen = *intPtr; 270 271 intPtr++; 272 273 cp = (char*)intPtr; 274 int i; 275 for ( i=0; i<dataLen; i++) 276 { 277 278 while (*cp)cp++; 279 cp++; 280 } 281 cp = btAlignPointer(cp,4); 282 283 /* 284 TYPE (4 bytes) 285 <nr> amount of types (int) 286 <string> 287 <string> 288 */ 289 290 intPtr = (int*)cp; 291 btAssert(strncmp(cp, "TYPE", 4)==0); intPtr++; 292 293 if (!littleEndian) 294 *intPtr = btSwapEndian(*intPtr); 295 296 dataLen = *intPtr; 297 intPtr++; 298 299 300 cp = (char*)intPtr; 301 for (i=0; i<dataLen; i++) 302 { 303 mTypes.push_back(cp); 304 while (*cp)cp++; 305 cp++; 306 } 307 308 cp = btAlignPointer(cp,4); 309 310 311 /* 312 TLEN (4 bytes) 313 <len> (short) the lengths of types 314 <len> 315 */ 316 317 // Parse type lens 318 intPtr = (int*)cp; 319 btAssert(strncmp(cp, "TLEN", 4)==0); intPtr++; 320 321 dataLen = (int)mTypes.size(); 322 323 shtPtr = (short*)intPtr; 324 for (i=0; i<dataLen; i++, shtPtr++) 325 { 326 if (!littleEndian) 327 shtPtr[0] = btSwapEndian(shtPtr[0]); 328 mTlens.push_back(shtPtr[0]); 329 } 330 331 if (dataLen & 1) shtPtr++; 332 333 /* 334 STRC (4 bytes) 335 <nr> amount of structs (int) 336 <typenr> 337 <nr_of_elems> 338 <typenr> 339 <namenr> 340 <typenr> 341 <namenr> 342 */ 343 344 intPtr = (int*)shtPtr; 345 cp = (char*)intPtr; 346 btAssert(strncmp(cp, "STRC", 4)==0); intPtr++; 347 348 if (!littleEndian) 349 *intPtr = btSwapEndian(*intPtr); 350 dataLen = *intPtr ; 351 intPtr++; 352 353 354 shtPtr = (short*)intPtr; 355 for (i=0; i<dataLen; i++) 356 { 357 mStructs.push_back (shtPtr); 358 359 if (!littleEndian) 360 { 361 shtPtr[0]= btSwapEndian(shtPtr[0]); 362 shtPtr[1]= btSwapEndian(shtPtr[1]); 363 364 int len = shtPtr[1]; 365 shtPtr+= 2; 366 367 for (int a=0; a<len; a++, shtPtr+=2) 368 { 369 shtPtr[0]= btSwapEndian(shtPtr[0]); 370 shtPtr[1]= btSwapEndian(shtPtr[1]); 371 } 372 373 } else 374 { 375 shtPtr+= (2*shtPtr[1])+2; 376 } 377 } 378 379 // build reverse lookups 380 for (i=0; i<(int)mStructs.size(); i++) 381 { 382 short *strc = mStructs.at(i); 383 mStructReverse.insert(strc[0], i); 384 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i); 385 } 386 } 387 388 public: 389 390 btHashMap<btHashPtr,void*> m_skipPointers; 391 392 393 btDefaultSerializer(int totalSize=0, unsigned char* buffer=0) 394 :m_totalSize(totalSize), 395 m_currentSize(0), 396 m_dna(0), 397 m_dnaLength(0), 398 m_serializationFlags(0) 399 { 400 if (buffer==0) 401 { 402 m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0; 403 m_ownsBuffer = true; 404 } else 405 { 406 m_buffer = buffer; 407 m_ownsBuffer = false; 408 } 409 410 const bool VOID_IS_8 = ((sizeof(void*)==8)); 411 412 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 413 if (VOID_IS_8) 414 { 415 #if _WIN64 416 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64); 417 #else 418 btAssert(0); 419 #endif 420 } else 421 { 422 #ifndef _WIN64 423 initDNA((const char*)sBulletDNAstr,sBulletDNAlen); 424 #else 425 btAssert(0); 426 #endif 427 } 428 429 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 430 if (VOID_IS_8) 431 { 432 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64); 433 } else 434 { 435 initDNA((const char*)sBulletDNAstr,sBulletDNAlen); 436 } 437 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 438 439 } 440 441 virtual ~btDefaultSerializer() 442 { 443 if (m_buffer && m_ownsBuffer) 444 btAlignedFree(m_buffer); 445 if (m_dna) 446 btAlignedFree(m_dna); 447 } 448 449 void insertHeader() 450 { 451 writeHeader(m_buffer); 452 m_currentSize += BT_HEADER_LENGTH; 453 } 454 455 void writeHeader(unsigned char* buffer) const 456 { 457 458 459 #ifdef BT_USE_DOUBLE_PRECISION 460 memcpy(buffer, "BULLETd", 7); 461 #else 462 memcpy(buffer, "BULLETf", 7); 463 #endif //BT_USE_DOUBLE_PRECISION 464 465 int littleEndian= 1; 466 littleEndian= ((char*)&littleEndian)[0]; 467 468 if (sizeof(void*)==8) 469 { 470 buffer[7] = '-'; 471 } else 472 { 473 buffer[7] = '_'; 474 } 475 476 if (littleEndian) 477 { 478 buffer[8]='v'; 479 } else 480 { 481 buffer[8]='V'; 482 } 483 484 485 buffer[9] = '2'; 486 buffer[10] = '8'; 487 buffer[11] = '4'; 488 489 } 490 491 virtual void startSerialization() 492 { 493 m_uniqueIdGenerator= 1; 494 if (m_totalSize) 495 { 496 unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH); 497 writeHeader(buffer); 498 } 499 500 } 501 502 virtual void finishSerialization() 503 { 504 writeDNA(); 505 506 //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now 507 int mysize = 0; 508 if (!m_totalSize) 509 { 510 if (m_buffer) 511 btAlignedFree(m_buffer); 512 513 m_currentSize += BT_HEADER_LENGTH; 514 m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize,16); 515 516 unsigned char* currentPtr = m_buffer; 517 writeHeader(m_buffer); 518 currentPtr += BT_HEADER_LENGTH; 519 mysize+=BT_HEADER_LENGTH; 520 for (int i=0;i< m_chunkPtrs.size();i++) 521 { 522 int curLength = sizeof(btChunk)+m_chunkPtrs[i]->m_length; 523 memcpy(currentPtr,m_chunkPtrs[i], curLength); 524 btAlignedFree(m_chunkPtrs[i]); 525 currentPtr+=curLength; 526 mysize+=curLength; 527 } 528 } 529 530 mTypes.clear(); 531 mStructs.clear(); 532 mTlens.clear(); 533 mStructReverse.clear(); 534 mTypeLookup.clear(); 535 m_skipPointers.clear(); 536 m_chunkP.clear(); 537 m_nameMap.clear(); 538 m_uniquePointers.clear(); 539 m_chunkPtrs.clear(); 540 } 541 542 virtual void* getUniquePointer(void*oldPtr) 543 { 544 if (!oldPtr) 545 return 0; 546 547 btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr); 548 if (uptr) 549 { 550 return uptr->m_ptr; 551 } 552 553 void** ptr2 = m_skipPointers[oldPtr]; 554 if (ptr2) 555 { 556 return 0; 557 } 558 559 m_uniqueIdGenerator++; 560 561 btPointerUid uid; 562 uid.m_uniqueIds[0] = m_uniqueIdGenerator; 563 uid.m_uniqueIds[1] = m_uniqueIdGenerator; 564 m_uniquePointers.insert(oldPtr,uid); 565 return uid.m_ptr; 566 567 } 568 569 virtual const unsigned char* getBufferPointer() const 570 { 571 return m_buffer; 572 } 573 574 virtual int getCurrentBufferSize() const 575 { 576 return m_currentSize; 577 } 578 579 virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr) 580 { 581 if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT)) 582 { 583 btAssert(!findPointer(oldPtr)); 584 } 585 586 chunk->m_dna_nr = getReverseType(structType); 587 588 chunk->m_chunkCode = chunkCode; 589 590 void* uniquePtr = getUniquePointer(oldPtr); 591 592 m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr); 593 chunk->m_oldPtr = uniquePtr;//oldPtr; 594 595 } 596 597 598 virtual unsigned char* internalAlloc(size_t size) 599 { 600 unsigned char* ptr = 0; 601 602 if (m_totalSize) 603 { 604 ptr = m_buffer+m_currentSize; 605 m_currentSize += int(size); 606 btAssert(m_currentSize<m_totalSize); 607 } else 608 { 609 ptr = (unsigned char*)btAlignedAlloc(size,16); 610 m_currentSize += int(size); 611 } 612 return ptr; 613 } 614 615 616 617 virtual btChunk* allocate(size_t size, int numElements) 618 { 619 620 unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(btChunk)); 621 622 unsigned char* data = ptr + sizeof(btChunk); 623 624 btChunk* chunk = (btChunk*)ptr; 625 chunk->m_chunkCode = 0; 626 chunk->m_oldPtr = data; 627 chunk->m_length = int(size)*numElements; 628 chunk->m_number = numElements; 629 630 m_chunkPtrs.push_back(chunk); 631 632 633 return chunk; 634 } 635 636 virtual const char* findNameForPointer(const void* ptr) const 637 { 638 const char*const * namePtr = m_nameMap.find(ptr); 639 if (namePtr && *namePtr) 640 return *namePtr; 641 return 0; 642 643 } 644 645 virtual void registerNameForPointer(const void* ptr, const char* name) 646 { 647 m_nameMap.insert(ptr,name); 648 } 649 650 virtual void serializeName(const char* name) 651 { 652 if (name) 653 { 654 //don't serialize name twice 655 if (findPointer((void*)name)) 656 return; 657 658 int len = btStrLen(name); 659 if (len) 660 { 661 662 int newLen = len+1; 663 int padding = ((newLen+3)&~3)-newLen; 664 newLen += padding; 665 666 //serialize name string now 667 btChunk* chunk = allocate(sizeof(char),newLen); 668 char* destinationName = (char*)chunk->m_oldPtr; 669 for (int i=0;i<len;i++) 670 { 671 destinationName[i] = name[i]; 672 } 673 destinationName[len] = 0; 674 finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name); 675 } 676 } 677 } 678 679 virtual int getSerializationFlags() const 680 { 681 return m_serializationFlags; 682 } 683 684 virtual void setSerializationFlags(int flags) 685 { 686 m_serializationFlags = flags; 687 } 688 int getNumChunks() const 689 { 690 return m_chunkPtrs.size(); 691 } 692 693 const btChunk* getChunk(int chunkIndex) const 694 { 695 return m_chunkPtrs[chunkIndex]; 696 } 697 }; 698 699 700 ///In general it is best to use btDefaultSerializer, 701 ///in particular when writing the data to disk or sending it over the network. 702 ///The btInMemorySerializer is experimental and only suitable in a few cases. 703 ///The btInMemorySerializer takes a shortcut and can be useful to create a deep-copy 704 ///of objects. There will be a demo on how to use the btInMemorySerializer. 705 #ifdef ENABLE_INMEMORY_SERIALIZER 706 707 struct btInMemorySerializer : public btDefaultSerializer 708 { 709 btHashMap<btHashPtr,btChunk*> m_uid2ChunkPtr; 710 btHashMap<btHashPtr,void*> m_orgPtr2UniqueDataPtr; 711 btHashMap<btHashString,const void*> m_names2Ptr; 712 713 714 btBulletSerializedArrays m_arrays; 715 716 btInMemorySerializer(int totalSize=0, unsigned char* buffer=0) 717 :btDefaultSerializer(totalSize,buffer) 718 { 719 720 } 721 722 virtual void startSerialization() 723 { 724 m_uid2ChunkPtr.clear(); 725 //todo: m_arrays.clear(); 726 btDefaultSerializer::startSerialization(); 727 } 728 729 730 731 btChunk* findChunkFromUniquePointer(void* uniquePointer) 732 { 733 btChunk** chkPtr = m_uid2ChunkPtr[uniquePointer]; 734 if (chkPtr) 735 { 736 return *chkPtr; 737 } 738 return 0; 739 } 740 741 virtual void registerNameForPointer(const void* ptr, const char* name) 742 { 743 btDefaultSerializer::registerNameForPointer(ptr,name); 744 m_names2Ptr.insert(name,ptr); 745 } 746 747 virtual void finishSerialization() 748 { 749 } 750 751 virtual void* getUniquePointer(void*oldPtr) 752 { 753 if (oldPtr==0) 754 return 0; 755 756 // void* uniquePtr = getUniquePointer(oldPtr); 757 btChunk* chunk = findChunkFromUniquePointer(oldPtr); 758 if (chunk) 759 { 760 return chunk->m_oldPtr; 761 } else 762 { 763 const char* n = (const char*) oldPtr; 764 const void** ptr = m_names2Ptr[n]; 765 if (ptr) 766 { 767 return oldPtr; 768 } else 769 { 770 void** ptr2 = m_skipPointers[oldPtr]; 771 if (ptr2) 772 { 773 return 0; 774 } else 775 { 776 //If this assert hit, serialization happened in the wrong order 777 // 'getUniquePointer' 778 btAssert(0); 779 } 780 781 } 782 return 0; 783 } 784 return oldPtr; 785 } 786 787 virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr) 788 { 789 if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT)) 790 { 791 btAssert(!findPointer(oldPtr)); 792 } 793 794 chunk->m_dna_nr = getReverseType(structType); 795 chunk->m_chunkCode = chunkCode; 796 //void* uniquePtr = getUniquePointer(oldPtr); 797 m_chunkP.insert(oldPtr,oldPtr);//chunk->m_oldPtr); 798 // chunk->m_oldPtr = uniquePtr;//oldPtr; 799 800 void* uid = findPointer(oldPtr); 801 m_uid2ChunkPtr.insert(uid,chunk); 802 803 switch (chunk->m_chunkCode) 804 { 805 case BT_SOFTBODY_CODE: 806 { 807 #ifdef BT_USE_DOUBLE_PRECISION 808 m_arrays.m_softBodyDoubleData.push_back((btSoftBodyDoubleData*) chunk->m_oldPtr); 809 #else 810 m_arrays.m_softBodyFloatData.push_back((btSoftBodyFloatData*) chunk->m_oldPtr); 811 #endif 812 break; 813 } 814 case BT_COLLISIONOBJECT_CODE: 815 { 816 #ifdef BT_USE_DOUBLE_PRECISION 817 m_arrays.m_collisionObjectDataDouble.push_back((btCollisionObjectDoubleData*)chunk->m_oldPtr); 818 #else//BT_USE_DOUBLE_PRECISION 819 m_arrays.m_collisionObjectDataFloat.push_back((btCollisionObjectFloatData*)chunk->m_oldPtr); 820 #endif //BT_USE_DOUBLE_PRECISION 821 break; 822 } 823 case BT_RIGIDBODY_CODE: 824 { 825 #ifdef BT_USE_DOUBLE_PRECISION 826 m_arrays.m_rigidBodyDataDouble.push_back((btRigidBodyDoubleData*)chunk->m_oldPtr); 827 #else 828 m_arrays.m_rigidBodyDataFloat.push_back((btRigidBodyFloatData*)chunk->m_oldPtr); 829 #endif//BT_USE_DOUBLE_PRECISION 830 break; 831 }; 832 case BT_CONSTRAINT_CODE: 833 { 834 #ifdef BT_USE_DOUBLE_PRECISION 835 m_arrays.m_constraintDataDouble.push_back((btTypedConstraintDoubleData*)chunk->m_oldPtr); 836 #else 837 m_arrays.m_constraintDataFloat.push_back((btTypedConstraintFloatData*)chunk->m_oldPtr); 838 #endif 839 break; 840 } 841 case BT_QUANTIZED_BVH_CODE: 842 { 843 #ifdef BT_USE_DOUBLE_PRECISION 844 m_arrays.m_bvhsDouble.push_back((btQuantizedBvhDoubleData*) chunk->m_oldPtr); 845 #else 846 m_arrays.m_bvhsFloat.push_back((btQuantizedBvhFloatData*) chunk->m_oldPtr); 847 #endif 848 break; 849 } 850 851 case BT_SHAPE_CODE: 852 { 853 btCollisionShapeData* shapeData = (btCollisionShapeData*) chunk->m_oldPtr; 854 m_arrays.m_colShapeData.push_back(shapeData); 855 break; 856 } 857 case BT_TRIANLGE_INFO_MAP: 858 case BT_ARRAY_CODE: 859 case BT_SBMATERIAL_CODE: 860 case BT_SBNODE_CODE: 861 case BT_DYNAMICSWORLD_CODE: 862 case BT_DNA_CODE: 863 { 864 break; 865 } 866 default: 867 { 868 } 869 }; 870 } 871 872 int getNumChunks() const 873 { 874 return m_uid2ChunkPtr.size(); 875 } 876 877 const btChunk* getChunk(int chunkIndex) const 878 { 879 return *m_uid2ChunkPtr.getAtIndex(chunkIndex); 880 } 881 882 }; 883 #endif //ENABLE_INMEMORY_SERIALIZER 884 885 #endif //BT_SERIALIZER_H 886 887