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