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
55 //! Helper class for tetrahedrons
56 class btTetrahedronShapeEx:public btBU_Simplex1to4
57 {
58 public:
btTetrahedronShapeEx()59 btTetrahedronShapeEx()
60 {
61 m_numVertices = 4;
62 }
63
64
setVertices(const btVector3 & v0,const btVector3 & v1,const btVector3 & v2,const btVector3 & v3)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
calcLocalAABB()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:
btGImpactShapeInterface()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 */
updateBound()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 */
getAabb(const btTransform & t,btVector3 & aabbMin,btVector3 & aabbMax)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
postUpdate()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
getLocalBox()149 SIMD_FORCE_INLINE const btAABB & getLocalBox()
150 {
151 return m_localAABB;
152 }
153
154
getShapeType()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 */
setLocalScaling(const btVector3 & scaling)163 virtual void setLocalScaling(const btVector3& scaling)
164 {
165 localScaling = scaling;
166 postUpdate();
167 }
168
getLocalScaling()169 virtual const btVector3& getLocalScaling() const
170 {
171 return localScaling;
172 }
173
174
setMargin(btScalar margin)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
getBoxSet()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
hasBoxSet()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
lockChildShapes()231 virtual void lockChildShapes() const
232 {
233 }
234
unlockChildShapes()235 virtual void unlockChildShapes() const
236 {
237 }
238
239 //! if this trimesh
getPrimitiveTriangle(int index,btPrimitiveTriangle & triangle)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 */
getChildAabb(int child_index,const btTransform & t,btVector3 & aabbMin,btVector3 & aabbMax)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
rayTest(const btVector3 & rayFrom,const btVector3 & rayTo,btCollisionWorld::RayResultCallback & resultCallback)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 */
processAllTriangles(btTriangleCallback * callback,const btVector3 & aabbMin,const btVector3 & aabbMax)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 */
processAllTrianglesRay(btTriangleCallback *,const btVector3 &,const btVector3 &)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:
~CompoundPrimitiveManager()317 virtual ~CompoundPrimitiveManager() {}
318 btGImpactCompoundShape * m_compoundShape;
319
320
CompoundPrimitiveManager(const CompoundPrimitiveManager & compound)321 CompoundPrimitiveManager(const CompoundPrimitiveManager& compound)
322 : btPrimitiveManagerBase()
323 {
324 m_compoundShape = compound.m_compoundShape;
325 }
326
CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape)327 CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape)
328 {
329 m_compoundShape = compoundShape;
330 }
331
CompoundPrimitiveManager()332 CompoundPrimitiveManager()
333 {
334 m_compoundShape = NULL;
335 }
336
is_trimesh()337 virtual bool is_trimesh() const
338 {
339 return false;
340 }
341
get_primitive_count()342 virtual int get_primitive_count() const
343 {
344 return (int )m_compoundShape->getNumChildShapes();
345 }
346
get_primitive_box(int prim_index,btAABB & primbox)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
get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle)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
~btGImpactCompoundShape()387 virtual ~btGImpactCompoundShape()
388 {
389 }
390
391
392 //! if true, then its children must get transforms.
childrenHasTransform()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
getPrimitiveManager()401 virtual const btPrimitiveManagerBase * getPrimitiveManager() const
402 {
403 return &m_primitive_manager;
404 }
405
406 //! Obtains the compopund primitive manager
getCompoundPrimitiveManager()407 SIMD_FORCE_INLINE CompoundPrimitiveManager * getCompoundPrimitiveManager()
408 {
409 return &m_primitive_manager;
410 }
411
412 //! Gets the number of children
getNumChildShapes()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.
addChildShape(const btTransform & localTransform,btCollisionShape * shape)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.
addChildShape(btCollisionShape * shape)428 void addChildShape(btCollisionShape* shape)
429 {
430 btAssert(shape->isConvex());
431 m_childShapes.push_back(shape);
432 }
433
434 //! Gets the children
getChildShape(int index)435 virtual btCollisionShape* getChildShape(int index)
436 {
437 return m_childShapes[index];
438 }
439
440 //! Gets the children
getChildShape(int index)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 */
getChildAabb(int child_index,const btTransform & t,btVector3 & aabbMin,btVector3 & aabbMax)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
getChildTransform(int index)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 */
setChildTransform(int index,const btTransform & transform)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
needsRetrieveTriangles()482 virtual bool needsRetrieveTriangles() const
483 {
484 return false;
485 }
486
487 //! Determines if this shape has tetrahedrons
needsRetrieveTetrahedrons()488 virtual bool needsRetrieveTetrahedrons() const
489 {
490 return false;
491 }
492
493
getBulletTriangle(int prim_index,btTriangleShapeEx & triangle)494 virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
495 {
496 (void) prim_index; (void) triangle;
497 btAssert(0);
498 }
499
getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron)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
getName()510 virtual const char* getName()const
511 {
512 return "GImpactCompound";
513 }
514
getGImpactShapeType()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
TrimeshPrimitiveManager()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
TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager)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
TrimeshPrimitiveManager(btStridingMeshInterface * meshInterface,int part)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
~TrimeshPrimitiveManager()604 virtual ~TrimeshPrimitiveManager() {}
605
lock()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
unlock()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
is_trimesh()633 virtual bool is_trimesh() const
634 {
635 return true;
636 }
637
get_primitive_count()638 virtual int get_primitive_count() const
639 {
640 return (int )numfaces;
641 }
642
get_vertex_count()643 SIMD_FORCE_INLINE int get_vertex_count() const
644 {
645 return (int )numverts;
646 }
647
get_indices(int face_index,unsigned int & i0,unsigned int & i1,unsigned int & i2)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
get_vertex(unsigned int vertex_index,btVector3 & vertex)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
get_primitive_box(int prim_index,btAABB & primbox)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
get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle)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
get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle)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
btGImpactMeshShapePart()720 btGImpactMeshShapePart()
721 {
722 m_box_set.setPrimitiveManager(&m_primitive_manager);
723 }
724
725
btGImpactMeshShapePart(btStridingMeshInterface * meshInterface,int part)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
~btGImpactMeshShapePart()733 virtual ~btGImpactMeshShapePart()
734 {
735 }
736
737 //! if true, then its children must get transforms.
childrenHasTransform()738 virtual bool childrenHasTransform() const
739 {
740 return false;
741 }
742
743
744 //! call when reading child shapes
lockChildShapes()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
unlockChildShapes()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
getNumChildShapes()760 virtual int getNumChildShapes() const
761 {
762 return m_primitive_manager.get_primitive_count();
763 }
764
765
766 //! Gets the children
getChildShape(int index)767 virtual btCollisionShape* getChildShape(int index)
768 {
769 (void) index;
770 btAssert(0);
771 return NULL;
772 }
773
774
775
776 //! Gets the child
getChildShape(int index)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
getChildTransform(int index)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 */
setChildTransform(int index,const btTransform & transform)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
getPrimitiveManager()805 virtual const btPrimitiveManagerBase * getPrimitiveManager() const
806 {
807 return &m_primitive_manager;
808 }
809
getTrimeshPrimitiveManager()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
getName()824 virtual const char* getName()const
825 {
826 return "GImpactMeshShapePart";
827 }
828
getGImpactShapeType()829 virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
830 {
831 return CONST_GIMPACT_TRIMESH_SHAPE_PART;
832 }
833
834 //! Determines if this shape has triangles
needsRetrieveTriangles()835 virtual bool needsRetrieveTriangles() const
836 {
837 return true;
838 }
839
840 //! Determines if this shape has tetrahedrons
needsRetrieveTetrahedrons()841 virtual bool needsRetrieveTetrahedrons() const
842 {
843 return false;
844 }
845
getBulletTriangle(int prim_index,btTriangleShapeEx & triangle)846 virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
847 {
848 m_primitive_manager.get_bullet_triangle(prim_index,triangle);
849 }
850
getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron)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
getVertexCount()860 SIMD_FORCE_INLINE int getVertexCount() const
861 {
862 return m_primitive_manager.get_vertex_count();
863 }
864
getVertex(int vertex_index,btVector3 & vertex)865 SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3 & vertex) const
866 {
867 m_primitive_manager.get_vertex(vertex_index,vertex);
868 }
869
setMargin(btScalar margin)870 SIMD_FORCE_INLINE void setMargin(btScalar margin)
871 {
872 m_primitive_manager.m_margin = margin;
873 postUpdate();
874 }
875
getMargin()876 SIMD_FORCE_INLINE btScalar getMargin() const
877 {
878 return m_primitive_manager.m_margin;
879 }
880
setLocalScaling(const btVector3 & scaling)881 virtual void setLocalScaling(const btVector3& scaling)
882 {
883 m_primitive_manager.m_scale = scaling;
884 postUpdate();
885 }
886
getLocalScaling()887 virtual const btVector3& getLocalScaling() const
888 {
889 return m_primitive_manager.m_scale;
890 }
891
getPart()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;
buildMeshParts(btStridingMeshInterface * meshInterface)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
calcLocalAABB()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:
btGImpactMeshShape(btStridingMeshInterface * meshInterface)938 btGImpactMeshShape(btStridingMeshInterface * meshInterface)
939 {
940 m_meshInterface = meshInterface;
941 buildMeshParts(meshInterface);
942 }
943
~btGImpactMeshShape()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
getMeshInterface()956 btStridingMeshInterface* getMeshInterface()
957 {
958 return m_meshInterface;
959 }
960
getMeshInterface()961 const btStridingMeshInterface* getMeshInterface() const
962 {
963 return m_meshInterface;
964 }
965
getMeshPartCount()966 int getMeshPartCount() const
967 {
968 return m_mesh_parts.size();
969 }
970
getMeshPart(int index)971 btGImpactMeshShapePart * getMeshPart(int index)
972 {
973 return m_mesh_parts[index];
974 }
975
976
977
getMeshPart(int index)978 const btGImpactMeshShapePart * getMeshPart(int index) const
979 {
980 return m_mesh_parts[index];
981 }
982
983
setLocalScaling(const btVector3 & scaling)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
setMargin(btScalar margin)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
postUpdate()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
getPrimitiveManager()1029 virtual const btPrimitiveManagerBase * getPrimitiveManager() const
1030 {
1031 btAssert(0);
1032 return NULL;
1033 }
1034
1035
1036 //! Gets the number of children
getNumChildShapes()1037 virtual int getNumChildShapes() const
1038 {
1039 btAssert(0);
1040 return 0;
1041 }
1042
1043
1044 //! if true, then its children must get transforms.
childrenHasTransform()1045 virtual bool childrenHasTransform() const
1046 {
1047 btAssert(0);
1048 return false;
1049 }
1050
1051 //! Determines if this shape has triangles
needsRetrieveTriangles()1052 virtual bool needsRetrieveTriangles() const
1053 {
1054 btAssert(0);
1055 return false;
1056 }
1057
1058 //! Determines if this shape has tetrahedrons
needsRetrieveTetrahedrons()1059 virtual bool needsRetrieveTetrahedrons() const
1060 {
1061 btAssert(0);
1062 return false;
1063 }
1064
getBulletTriangle(int prim_index,btTriangleShapeEx & triangle)1065 virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
1066 {
1067 (void) prim_index; (void) triangle;
1068 btAssert(0);
1069 }
1070
getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron)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
lockChildShapes()1078 virtual void lockChildShapes() const
1079 {
1080 btAssert(0);
1081 }
1082
unlockChildShapes()1083 virtual void unlockChildShapes() const
1084 {
1085 btAssert(0);
1086 }
1087
1088
1089
1090
1091 //! Retrieves the bound from a child
1092 /*!
1093 */
getChildAabb(int child_index,const btTransform & t,btVector3 & aabbMin,btVector3 & aabbMax)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
getChildShape(int index)1101 virtual btCollisionShape* getChildShape(int index)
1102 {
1103 (void) index;
1104 btAssert(0);
1105 return NULL;
1106 }
1107
1108
1109 //! Gets the child
getChildShape(int index)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
getChildTransform(int index)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 */
setChildTransform(int index,const btTransform & transform)1129 virtual void setChildTransform(int index, const btTransform & transform)
1130 {
1131 (void) index; (void) transform;
1132 btAssert(0);
1133 }
1134
1135
getGImpactShapeType()1136 virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
1137 {
1138 return CONST_GIMPACT_TRIMESH_SHAPE;
1139 }
1140
1141
getName()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
calculateSerializeBufferSize()1178 SIMD_FORCE_INLINE int btGImpactMeshShape::calculateSerializeBufferSize() const
1179 {
1180 return sizeof(btGImpactMeshShapeData);
1181 }
1182
1183
1184 #endif //GIMPACT_MESH_SHAPE_H
1185