1 /*! \file btGImpactShape.h 2 \author Francisco Len Njera 3 */ 4 /* 5 This source file is part of GIMPACT Library. 6 7 For the latest info, see http://gimpact.sourceforge.net/ 8 9 Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. 10 email: projectileman (at) yahoo.com 11 12 13 This software is provided 'as-is', without any express or implied warranty. 14 In no event will the authors be held liable for any damages arising from the use of this software. 15 Permission is granted to anyone to use this software for any purpose, 16 including commercial applications, and to alter it and redistribute it freely, 17 subject to the following restrictions: 18 19 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. 20 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 21 3. This notice may not be removed or altered from any source distribution. 22 */ 23 24 25 #ifndef GIMPACT_SHAPE_H 26 #define GIMPACT_SHAPE_H 27 28 #include "BulletCollision/CollisionShapes/btCollisionShape.h" 29 #include "BulletCollision/CollisionShapes/btTriangleShape.h" 30 #include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" 31 #include "BulletCollision/CollisionShapes/btCollisionMargin.h" 32 #include "BulletCollision/CollisionDispatch/btCollisionWorld.h" 33 #include "BulletCollision/CollisionShapes/btConcaveShape.h" 34 #include "BulletCollision/CollisionShapes/btTetrahedronShape.h" 35 #include "LinearMath/btVector3.h" 36 #include "LinearMath/btTransform.h" 37 #include "LinearMath/btMatrix3x3.h" 38 #include "LinearMath/btAlignedObjectArray.h" 39 40 #include "btGImpactQuantizedBvh.h" // box tree class 41 42 43 //! declare Quantized trees, (you can change to float based trees) 44 typedef btGImpactQuantizedBvh btGImpactBoxSet; 45 46 enum eGIMPACT_SHAPE_TYPE 47 { 48 CONST_GIMPACT_COMPOUND_SHAPE = 0, 49 CONST_GIMPACT_TRIMESH_SHAPE_PART, 50 CONST_GIMPACT_TRIMESH_SHAPE 51 }; 52 53 54 55 //! Helper class for tetrahedrons 56 class btTetrahedronShapeEx:public btBU_Simplex1to4 57 { 58 public: 59 btTetrahedronShapeEx() 60 { 61 m_numVertices = 4; 62 } 63 64 65 SIMD_FORCE_INLINE void setVertices( 66 const btVector3 & v0,const btVector3 & v1, 67 const btVector3 & v2,const btVector3 & v3) 68 { 69 m_vertices[0] = v0; 70 m_vertices[1] = v1; 71 m_vertices[2] = v2; 72 m_vertices[3] = v3; 73 recalcLocalAabb(); 74 } 75 }; 76 77 78 //! Base class for gimpact shapes 79 class btGImpactShapeInterface : public btConcaveShape 80 { 81 protected: 82 btAABB m_localAABB; 83 bool m_needs_update; 84 btVector3 localScaling; 85 btGImpactBoxSet m_box_set;// optionally boxset 86 87 //! use this function for perfofm refit in bounding boxes 88 //! use this function for perfofm refit in bounding boxes 89 virtual void calcLocalAABB() 90 { 91 lockChildShapes(); 92 if(m_box_set.getNodeCount() == 0) 93 { 94 m_box_set.buildSet(); 95 } 96 else 97 { 98 m_box_set.update(); 99 } 100 unlockChildShapes(); 101 102 m_localAABB = m_box_set.getGlobalBox(); 103 } 104 105 106 public: 107 btGImpactShapeInterface() 108 { 109 m_shapeType=GIMPACT_SHAPE_PROXYTYPE; 110 m_localAABB.invalidate(); 111 m_needs_update = true; 112 localScaling.setValue(1.f,1.f,1.f); 113 } 114 115 116 //! performs refit operation 117 /*! 118 Updates the entire Box set of this shape. 119 \pre postUpdate() must be called for attemps to calculating the box set, else this function 120 will does nothing. 121 \post if m_needs_update == true, then it calls calcLocalAABB(); 122 */ 123 SIMD_FORCE_INLINE void updateBound() 124 { 125 if(!m_needs_update) return; 126 calcLocalAABB(); 127 m_needs_update = false; 128 } 129 130 //! If the Bounding box is not updated, then this class attemps to calculate it. 131 /*! 132 \post Calls updateBound() for update the box set. 133 */ 134 void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const 135 { 136 btAABB transformedbox = m_localAABB; 137 transformedbox.appy_transform(t); 138 aabbMin = transformedbox.m_min; 139 aabbMax = transformedbox.m_max; 140 } 141 142 //! Tells to this object that is needed to refit the box set 143 virtual void postUpdate() 144 { 145 m_needs_update = true; 146 } 147 148 //! Obtains the local box, which is the global calculated box of the total of subshapes 149 SIMD_FORCE_INLINE const btAABB & getLocalBox() 150 { 151 return m_localAABB; 152 } 153 154 155 virtual int getShapeType() const 156 { 157 return GIMPACT_SHAPE_PROXYTYPE; 158 } 159 160 /*! 161 \post You must call updateBound() for update the box set. 162 */ 163 virtual void setLocalScaling(const btVector3& scaling) 164 { 165 localScaling = scaling; 166 postUpdate(); 167 } 168 169 virtual const btVector3& getLocalScaling() const 170 { 171 return localScaling; 172 } 173 174 175 virtual void setMargin(btScalar margin) 176 { 177 m_collisionMargin = margin; 178 int i = getNumChildShapes(); 179 while(i--) 180 { 181 btCollisionShape* child = getChildShape(i); 182 child->setMargin(margin); 183 } 184 185 m_needs_update = true; 186 } 187 188 189 //! Subshape member functions 190 //!@{ 191 192 //! Base method for determinig which kind of GIMPACT shape we get 193 virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const = 0 ; 194 195 //! gets boxset 196 SIMD_FORCE_INLINE const btGImpactBoxSet * getBoxSet() const 197 { 198 return &m_box_set; 199 } 200 201 //! Determines if this class has a hierarchy structure for sorting its primitives 202 SIMD_FORCE_INLINE bool hasBoxSet() const 203 { 204 if(m_box_set.getNodeCount() == 0) return false; 205 return true; 206 } 207 208 //! Obtains the primitive manager 209 virtual const btPrimitiveManagerBase * getPrimitiveManager() const = 0; 210 211 212 //! Gets the number of children 213 virtual int getNumChildShapes() const = 0; 214 215 //! if true, then its children must get transforms. 216 virtual bool childrenHasTransform() const = 0; 217 218 //! Determines if this shape has triangles 219 virtual bool needsRetrieveTriangles() const = 0; 220 221 //! Determines if this shape has tetrahedrons 222 virtual bool needsRetrieveTetrahedrons() const = 0; 223 224 virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const = 0; 225 226 virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const = 0; 227 228 229 230 //! call when reading child shapes 231 virtual void lockChildShapes() const 232 { 233 } 234 235 virtual void unlockChildShapes() const 236 { 237 } 238 239 //! if this trimesh 240 SIMD_FORCE_INLINE void getPrimitiveTriangle(int index,btPrimitiveTriangle & triangle) const 241 { 242 getPrimitiveManager()->get_primitive_triangle(index,triangle); 243 } 244 245 246 //! Retrieves the bound from a child 247 /*! 248 */ 249 virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const 250 { 251 btAABB child_aabb; 252 getPrimitiveManager()->get_primitive_box(child_index,child_aabb); 253 child_aabb.appy_transform(t); 254 aabbMin = child_aabb.m_min; 255 aabbMax = child_aabb.m_max; 256 } 257 258 //! Gets the children 259 virtual btCollisionShape* getChildShape(int index) = 0; 260 261 262 //! Gets the child 263 virtual const btCollisionShape* getChildShape(int index) const = 0; 264 265 //! Gets the children transform 266 virtual btTransform getChildTransform(int index) const = 0; 267 268 //! Sets the children transform 269 /*! 270 \post You must call updateBound() for update the box set. 271 */ 272 virtual void setChildTransform(int index, const btTransform & transform) = 0; 273 274 //!@} 275 276 277 //! virtual method for ray collision 278 virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const 279 { 280 (void) rayFrom; (void) rayTo; (void) resultCallback; 281 } 282 283 //! Function for retrieve triangles. 284 /*! 285 It gives the triangles in local space 286 */ 287 virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const 288 { 289 (void) callback; (void) aabbMin; (void) aabbMax; 290 } 291 292 //! Function for retrieve triangles. 293 /*! 294 It gives the triangles in local space 295 */ 296 virtual void processAllTrianglesRay(btTriangleCallback* /*callback*/,const btVector3& /*rayFrom*/, const btVector3& /*rayTo*/) const 297 { 298 299 } 300 301 //!@} 302 303 }; 304 305 306 //! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once 307 /*! 308 This class only can manage Convex subshapes 309 */ 310 class btGImpactCompoundShape : public btGImpactShapeInterface 311 { 312 public: 313 //! compound primitive manager 314 class CompoundPrimitiveManager:public btPrimitiveManagerBase 315 { 316 public: 317 virtual ~CompoundPrimitiveManager() {} 318 btGImpactCompoundShape * m_compoundShape; 319 320 321 CompoundPrimitiveManager(const CompoundPrimitiveManager& compound) 322 : btPrimitiveManagerBase() 323 { 324 m_compoundShape = compound.m_compoundShape; 325 } 326 327 CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape) 328 { 329 m_compoundShape = compoundShape; 330 } 331 332 CompoundPrimitiveManager() 333 { 334 m_compoundShape = NULL; 335 } 336 337 virtual bool is_trimesh() const 338 { 339 return false; 340 } 341 342 virtual int get_primitive_count() const 343 { 344 return (int )m_compoundShape->getNumChildShapes(); 345 } 346 347 virtual void get_primitive_box(int prim_index ,btAABB & primbox) const 348 { 349 btTransform prim_trans; 350 if(m_compoundShape->childrenHasTransform()) 351 { 352 prim_trans = m_compoundShape->getChildTransform(prim_index); 353 } 354 else 355 { 356 prim_trans.setIdentity(); 357 } 358 const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index); 359 shape->getAabb(prim_trans,primbox.m_min,primbox.m_max); 360 } 361 362 virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const 363 { 364 btAssert(0); 365 (void) prim_index; (void) triangle; 366 } 367 368 }; 369 370 371 372 protected: 373 CompoundPrimitiveManager m_primitive_manager; 374 btAlignedObjectArray<btTransform> m_childTransforms; 375 btAlignedObjectArray<btCollisionShape*> m_childShapes; 376 377 378 public: 379 380 btGImpactCompoundShape(bool children_has_transform = true) 381 { 382 (void) children_has_transform; 383 m_primitive_manager.m_compoundShape = this; 384 m_box_set.setPrimitiveManager(&m_primitive_manager); 385 } 386 387 virtual ~btGImpactCompoundShape() 388 { 389 } 390 391 392 //! if true, then its children must get transforms. 393 virtual bool childrenHasTransform() const 394 { 395 if(m_childTransforms.size()==0) return false; 396 return true; 397 } 398 399 400 //! Obtains the primitive manager 401 virtual const btPrimitiveManagerBase * getPrimitiveManager() const 402 { 403 return &m_primitive_manager; 404 } 405 406 //! Obtains the compopund primitive manager 407 SIMD_FORCE_INLINE CompoundPrimitiveManager * getCompoundPrimitiveManager() 408 { 409 return &m_primitive_manager; 410 } 411 412 //! Gets the number of children 413 virtual int getNumChildShapes() const 414 { 415 return m_childShapes.size(); 416 } 417 418 419 //! Use this method for adding children. Only Convex shapes are allowed. 420 void addChildShape(const btTransform& localTransform,btCollisionShape* shape) 421 { 422 btAssert(shape->isConvex()); 423 m_childTransforms.push_back(localTransform); 424 m_childShapes.push_back(shape); 425 } 426 427 //! Use this method for adding children. Only Convex shapes are allowed. 428 void addChildShape(btCollisionShape* shape) 429 { 430 btAssert(shape->isConvex()); 431 m_childShapes.push_back(shape); 432 } 433 434 //! Gets the children 435 virtual btCollisionShape* getChildShape(int index) 436 { 437 return m_childShapes[index]; 438 } 439 440 //! Gets the children 441 virtual const btCollisionShape* getChildShape(int index) const 442 { 443 return m_childShapes[index]; 444 } 445 446 //! Retrieves the bound from a child 447 /*! 448 */ 449 virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const 450 { 451 452 if(childrenHasTransform()) 453 { 454 m_childShapes[child_index]->getAabb(t*m_childTransforms[child_index],aabbMin,aabbMax); 455 } 456 else 457 { 458 m_childShapes[child_index]->getAabb(t,aabbMin,aabbMax); 459 } 460 } 461 462 463 //! Gets the children transform 464 virtual btTransform getChildTransform(int index) const 465 { 466 btAssert(m_childTransforms.size() == m_childShapes.size()); 467 return m_childTransforms[index]; 468 } 469 470 //! Sets the children transform 471 /*! 472 \post You must call updateBound() for update the box set. 473 */ 474 virtual void setChildTransform(int index, const btTransform & transform) 475 { 476 btAssert(m_childTransforms.size() == m_childShapes.size()); 477 m_childTransforms[index] = transform; 478 postUpdate(); 479 } 480 481 //! Determines if this shape has triangles 482 virtual bool needsRetrieveTriangles() const 483 { 484 return false; 485 } 486 487 //! Determines if this shape has tetrahedrons 488 virtual bool needsRetrieveTetrahedrons() const 489 { 490 return false; 491 } 492 493 494 virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const 495 { 496 (void) prim_index; (void) triangle; 497 btAssert(0); 498 } 499 500 virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const 501 { 502 (void) prim_index; (void) tetrahedron; 503 btAssert(0); 504 } 505 506 507 //! Calculates the exact inertia tensor for this shape 508 virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; 509 510 virtual const char* getName()const 511 { 512 return "GImpactCompound"; 513 } 514 515 virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const 516 { 517 return CONST_GIMPACT_COMPOUND_SHAPE; 518 } 519 520 }; 521 522 523 524 //! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface. 525 /*! 526 - Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh 527 - When making operations with this shape, you must call <b>lock</b> before accessing to the trimesh primitives, and then call <b>unlock</b> 528 - You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices. 529 530 */ 531 class btGImpactMeshShapePart : public btGImpactShapeInterface 532 { 533 public: 534 //! Trimesh primitive manager 535 /*! 536 Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism 537 */ 538 class TrimeshPrimitiveManager:public btPrimitiveManagerBase 539 { 540 public: 541 btScalar m_margin; 542 btStridingMeshInterface * m_meshInterface; 543 btVector3 m_scale; 544 int m_part; 545 int m_lock_count; 546 const unsigned char *vertexbase; 547 int numverts; 548 PHY_ScalarType type; 549 int stride; 550 const unsigned char *indexbase; 551 int indexstride; 552 int numfaces; 553 PHY_ScalarType indicestype; 554 555 TrimeshPrimitiveManager() 556 { 557 m_meshInterface = NULL; 558 m_part = 0; 559 m_margin = 0.01f; 560 m_scale = btVector3(1.f,1.f,1.f); 561 m_lock_count = 0; 562 vertexbase = 0; 563 numverts = 0; 564 stride = 0; 565 indexbase = 0; 566 indexstride = 0; 567 numfaces = 0; 568 } 569 570 TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager) 571 : btPrimitiveManagerBase() 572 { 573 m_meshInterface = manager.m_meshInterface; 574 m_part = manager.m_part; 575 m_margin = manager.m_margin; 576 m_scale = manager.m_scale; 577 m_lock_count = 0; 578 vertexbase = 0; 579 numverts = 0; 580 stride = 0; 581 indexbase = 0; 582 indexstride = 0; 583 numfaces = 0; 584 585 } 586 587 TrimeshPrimitiveManager( 588 btStridingMeshInterface * meshInterface, int part) 589 { 590 m_meshInterface = meshInterface; 591 m_part = part; 592 m_scale = m_meshInterface->getScaling(); 593 m_margin = 0.1f; 594 m_lock_count = 0; 595 vertexbase = 0; 596 numverts = 0; 597 stride = 0; 598 indexbase = 0; 599 indexstride = 0; 600 numfaces = 0; 601 602 } 603 604 virtual ~TrimeshPrimitiveManager() {} 605 606 void lock() 607 { 608 if(m_lock_count>0) 609 { 610 m_lock_count++; 611 return; 612 } 613 m_meshInterface->getLockedReadOnlyVertexIndexBase( 614 &vertexbase,numverts, 615 type, stride,&indexbase, indexstride, numfaces,indicestype,m_part); 616 617 m_lock_count = 1; 618 } 619 620 void unlock() 621 { 622 if(m_lock_count == 0) return; 623 if(m_lock_count>1) 624 { 625 --m_lock_count; 626 return; 627 } 628 m_meshInterface->unLockReadOnlyVertexBase(m_part); 629 vertexbase = NULL; 630 m_lock_count = 0; 631 } 632 633 virtual bool is_trimesh() const 634 { 635 return true; 636 } 637 638 virtual int get_primitive_count() const 639 { 640 return (int )numfaces; 641 } 642 643 SIMD_FORCE_INLINE int get_vertex_count() const 644 { 645 return (int )numverts; 646 } 647 648 SIMD_FORCE_INLINE void get_indices(int face_index,unsigned int &i0,unsigned int &i1,unsigned int &i2) const 649 { 650 if(indicestype == PHY_SHORT) 651 { 652 unsigned short* s_indices = (unsigned short *)(indexbase + face_index * indexstride); 653 i0 = s_indices[0]; 654 i1 = s_indices[1]; 655 i2 = s_indices[2]; 656 } 657 else 658 { 659 unsigned int * i_indices = (unsigned int *)(indexbase + face_index*indexstride); 660 i0 = i_indices[0]; 661 i1 = i_indices[1]; 662 i2 = i_indices[2]; 663 } 664 } 665 666 SIMD_FORCE_INLINE void get_vertex(unsigned int vertex_index, btVector3 & vertex) const 667 { 668 if(type == PHY_DOUBLE) 669 { 670 double * dvertices = (double *)(vertexbase + vertex_index*stride); 671 vertex[0] = btScalar(dvertices[0]*m_scale[0]); 672 vertex[1] = btScalar(dvertices[1]*m_scale[1]); 673 vertex[2] = btScalar(dvertices[2]*m_scale[2]); 674 } 675 else 676 { 677 float * svertices = (float *)(vertexbase + vertex_index*stride); 678 vertex[0] = svertices[0]*m_scale[0]; 679 vertex[1] = svertices[1]*m_scale[1]; 680 vertex[2] = svertices[2]*m_scale[2]; 681 } 682 } 683 684 virtual void get_primitive_box(int prim_index ,btAABB & primbox) const 685 { 686 btPrimitiveTriangle triangle; 687 get_primitive_triangle(prim_index,triangle); 688 primbox.calc_from_triangle_margin( 689 triangle.m_vertices[0], 690 triangle.m_vertices[1],triangle.m_vertices[2],triangle.m_margin); 691 } 692 693 virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const 694 { 695 unsigned int indices[3]; 696 get_indices(prim_index,indices[0],indices[1],indices[2]); 697 get_vertex(indices[0],triangle.m_vertices[0]); 698 get_vertex(indices[1],triangle.m_vertices[1]); 699 get_vertex(indices[2],triangle.m_vertices[2]); 700 triangle.m_margin = m_margin; 701 } 702 703 SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle) const 704 { 705 unsigned int indices[3]; 706 get_indices(prim_index,indices[0],indices[1],indices[2]); 707 get_vertex(indices[0],triangle.m_vertices1[0]); 708 get_vertex(indices[1],triangle.m_vertices1[1]); 709 get_vertex(indices[2],triangle.m_vertices1[2]); 710 triangle.setMargin(m_margin); 711 } 712 713 }; 714 715 716 protected: 717 TrimeshPrimitiveManager m_primitive_manager; 718 public: 719 720 btGImpactMeshShapePart() 721 { 722 m_box_set.setPrimitiveManager(&m_primitive_manager); 723 } 724 725 726 btGImpactMeshShapePart(btStridingMeshInterface * meshInterface, int part) 727 { 728 m_primitive_manager.m_meshInterface = meshInterface; 729 m_primitive_manager.m_part = part; 730 m_box_set.setPrimitiveManager(&m_primitive_manager); 731 } 732 733 virtual ~btGImpactMeshShapePart() 734 { 735 } 736 737 //! if true, then its children must get transforms. 738 virtual bool childrenHasTransform() const 739 { 740 return false; 741 } 742 743 744 //! call when reading child shapes 745 virtual void lockChildShapes() const 746 { 747 void * dummy = (void*)(m_box_set.getPrimitiveManager()); 748 TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>(dummy); 749 dummymanager->lock(); 750 } 751 752 virtual void unlockChildShapes() const 753 { 754 void * dummy = (void*)(m_box_set.getPrimitiveManager()); 755 TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>(dummy); 756 dummymanager->unlock(); 757 } 758 759 //! Gets the number of children 760 virtual int getNumChildShapes() const 761 { 762 return m_primitive_manager.get_primitive_count(); 763 } 764 765 766 //! Gets the children 767 virtual btCollisionShape* getChildShape(int index) 768 { 769 (void) index; 770 btAssert(0); 771 return NULL; 772 } 773 774 775 776 //! Gets the child 777 virtual const btCollisionShape* getChildShape(int index) const 778 { 779 (void) index; 780 btAssert(0); 781 return NULL; 782 } 783 784 //! Gets the children transform 785 virtual btTransform getChildTransform(int index) const 786 { 787 (void) index; 788 btAssert(0); 789 return btTransform(); 790 } 791 792 //! Sets the children transform 793 /*! 794 \post You must call updateBound() for update the box set. 795 */ 796 virtual void setChildTransform(int index, const btTransform & transform) 797 { 798 (void) index; 799 (void) transform; 800 btAssert(0); 801 } 802 803 804 //! Obtains the primitive manager 805 virtual const btPrimitiveManagerBase * getPrimitiveManager() const 806 { 807 return &m_primitive_manager; 808 } 809 810 SIMD_FORCE_INLINE TrimeshPrimitiveManager * getTrimeshPrimitiveManager() 811 { 812 return &m_primitive_manager; 813 } 814 815 816 817 818 819 virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; 820 821 822 823 824 virtual const char* getName()const 825 { 826 return "GImpactMeshShapePart"; 827 } 828 829 virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const 830 { 831 return CONST_GIMPACT_TRIMESH_SHAPE_PART; 832 } 833 834 //! Determines if this shape has triangles 835 virtual bool needsRetrieveTriangles() const 836 { 837 return true; 838 } 839 840 //! Determines if this shape has tetrahedrons 841 virtual bool needsRetrieveTetrahedrons() const 842 { 843 return false; 844 } 845 846 virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const 847 { 848 m_primitive_manager.get_bullet_triangle(prim_index,triangle); 849 } 850 851 virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const 852 { 853 (void) prim_index; 854 (void) tetrahedron; 855 btAssert(0); 856 } 857 858 859 860 SIMD_FORCE_INLINE int getVertexCount() const 861 { 862 return m_primitive_manager.get_vertex_count(); 863 } 864 865 SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3 & vertex) const 866 { 867 m_primitive_manager.get_vertex(vertex_index,vertex); 868 } 869 870 SIMD_FORCE_INLINE void setMargin(btScalar margin) 871 { 872 m_primitive_manager.m_margin = margin; 873 postUpdate(); 874 } 875 876 SIMD_FORCE_INLINE btScalar getMargin() const 877 { 878 return m_primitive_manager.m_margin; 879 } 880 881 virtual void setLocalScaling(const btVector3& scaling) 882 { 883 m_primitive_manager.m_scale = scaling; 884 postUpdate(); 885 } 886 887 virtual const btVector3& getLocalScaling() const 888 { 889 return m_primitive_manager.m_scale; 890 } 891 892 SIMD_FORCE_INLINE int getPart() const 893 { 894 return (int)m_primitive_manager.m_part; 895 } 896 897 virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; 898 virtual void processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const; 899 }; 900 901 902 //! This class manages a mesh supplied by the btStridingMeshInterface interface. 903 /*! 904 Set of btGImpactMeshShapePart parts 905 - Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh 906 907 - You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices. 908 909 */ 910 class btGImpactMeshShape : public btGImpactShapeInterface 911 { 912 btStridingMeshInterface* m_meshInterface; 913 914 protected: 915 btAlignedObjectArray<btGImpactMeshShapePart*> m_mesh_parts; 916 void buildMeshParts(btStridingMeshInterface * meshInterface) 917 { 918 for (int i=0;i<meshInterface->getNumSubParts() ;++i ) 919 { 920 btGImpactMeshShapePart * newpart = new btGImpactMeshShapePart(meshInterface,i); 921 m_mesh_parts.push_back(newpart); 922 } 923 } 924 925 //! use this function for perfofm refit in bounding boxes 926 virtual void calcLocalAABB() 927 { 928 m_localAABB.invalidate(); 929 int i = m_mesh_parts.size(); 930 while(i--) 931 { 932 m_mesh_parts[i]->updateBound(); 933 m_localAABB.merge(m_mesh_parts[i]->getLocalBox()); 934 } 935 } 936 937 public: 938 btGImpactMeshShape(btStridingMeshInterface * meshInterface) 939 { 940 m_meshInterface = meshInterface; 941 buildMeshParts(meshInterface); 942 } 943 944 virtual ~btGImpactMeshShape() 945 { 946 int i = m_mesh_parts.size(); 947 while(i--) 948 { 949 btGImpactMeshShapePart * part = m_mesh_parts[i]; 950 delete part; 951 } 952 m_mesh_parts.clear(); 953 } 954 955 956 btStridingMeshInterface* getMeshInterface() 957 { 958 return m_meshInterface; 959 } 960 961 const btStridingMeshInterface* getMeshInterface() const 962 { 963 return m_meshInterface; 964 } 965 966 int getMeshPartCount() const 967 { 968 return m_mesh_parts.size(); 969 } 970 971 btGImpactMeshShapePart * getMeshPart(int index) 972 { 973 return m_mesh_parts[index]; 974 } 975 976 977 978 const btGImpactMeshShapePart * getMeshPart(int index) const 979 { 980 return m_mesh_parts[index]; 981 } 982 983 984 virtual void setLocalScaling(const btVector3& scaling) 985 { 986 localScaling = scaling; 987 988 int i = m_mesh_parts.size(); 989 while(i--) 990 { 991 btGImpactMeshShapePart * part = m_mesh_parts[i]; 992 part->setLocalScaling(scaling); 993 } 994 995 m_needs_update = true; 996 } 997 998 virtual void setMargin(btScalar margin) 999 { 1000 m_collisionMargin = margin; 1001 1002 int i = m_mesh_parts.size(); 1003 while(i--) 1004 { 1005 btGImpactMeshShapePart * part = m_mesh_parts[i]; 1006 part->setMargin(margin); 1007 } 1008 1009 m_needs_update = true; 1010 } 1011 1012 //! Tells to this object that is needed to refit all the meshes 1013 virtual void postUpdate() 1014 { 1015 int i = m_mesh_parts.size(); 1016 while(i--) 1017 { 1018 btGImpactMeshShapePart * part = m_mesh_parts[i]; 1019 part->postUpdate(); 1020 } 1021 1022 m_needs_update = true; 1023 } 1024 1025 virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; 1026 1027 1028 //! Obtains the primitive manager 1029 virtual const btPrimitiveManagerBase * getPrimitiveManager() const 1030 { 1031 btAssert(0); 1032 return NULL; 1033 } 1034 1035 1036 //! Gets the number of children 1037 virtual int getNumChildShapes() const 1038 { 1039 btAssert(0); 1040 return 0; 1041 } 1042 1043 1044 //! if true, then its children must get transforms. 1045 virtual bool childrenHasTransform() const 1046 { 1047 btAssert(0); 1048 return false; 1049 } 1050 1051 //! Determines if this shape has triangles 1052 virtual bool needsRetrieveTriangles() const 1053 { 1054 btAssert(0); 1055 return false; 1056 } 1057 1058 //! Determines if this shape has tetrahedrons 1059 virtual bool needsRetrieveTetrahedrons() const 1060 { 1061 btAssert(0); 1062 return false; 1063 } 1064 1065 virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const 1066 { 1067 (void) prim_index; (void) triangle; 1068 btAssert(0); 1069 } 1070 1071 virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const 1072 { 1073 (void) prim_index; (void) tetrahedron; 1074 btAssert(0); 1075 } 1076 1077 //! call when reading child shapes 1078 virtual void lockChildShapes() const 1079 { 1080 btAssert(0); 1081 } 1082 1083 virtual void unlockChildShapes() const 1084 { 1085 btAssert(0); 1086 } 1087 1088 1089 1090 1091 //! Retrieves the bound from a child 1092 /*! 1093 */ 1094 virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const 1095 { 1096 (void) child_index; (void) t; (void) aabbMin; (void) aabbMax; 1097 btAssert(0); 1098 } 1099 1100 //! Gets the children 1101 virtual btCollisionShape* getChildShape(int index) 1102 { 1103 (void) index; 1104 btAssert(0); 1105 return NULL; 1106 } 1107 1108 1109 //! Gets the child 1110 virtual const btCollisionShape* getChildShape(int index) const 1111 { 1112 (void) index; 1113 btAssert(0); 1114 return NULL; 1115 } 1116 1117 //! Gets the children transform 1118 virtual btTransform getChildTransform(int index) const 1119 { 1120 (void) index; 1121 btAssert(0); 1122 return btTransform(); 1123 } 1124 1125 //! Sets the children transform 1126 /*! 1127 \post You must call updateBound() for update the box set. 1128 */ 1129 virtual void setChildTransform(int index, const btTransform & transform) 1130 { 1131 (void) index; (void) transform; 1132 btAssert(0); 1133 } 1134 1135 1136 virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const 1137 { 1138 return CONST_GIMPACT_TRIMESH_SHAPE; 1139 } 1140 1141 1142 virtual const char* getName()const 1143 { 1144 return "GImpactMesh"; 1145 } 1146 1147 virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const; 1148 1149 //! Function for retrieve triangles. 1150 /*! 1151 It gives the triangles in local space 1152 */ 1153 virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; 1154 1155 virtual void processAllTrianglesRay (btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const; 1156 1157 virtual int calculateSerializeBufferSize() const; 1158 1159 ///fills the dataBuffer and returns the struct name (and 0 on failure) 1160 virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; 1161 1162 }; 1163 1164 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 1165 struct btGImpactMeshShapeData 1166 { 1167 btCollisionShapeData m_collisionShapeData; 1168 1169 btStridingMeshInterfaceData m_meshInterface; 1170 1171 btVector3FloatData m_localScaling; 1172 1173 float m_collisionMargin; 1174 1175 int m_gimpactSubType; 1176 }; 1177 1178 SIMD_FORCE_INLINE int btGImpactMeshShape::calculateSerializeBufferSize() const 1179 { 1180 return sizeof(btGImpactMeshShapeData); 1181 } 1182 1183 1184 #endif //GIMPACT_MESH_SHAPE_H 1185