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