1
/*! \file btGImpactShape.h
2
\author Francisco Len N�jera
5
This source file is part of GIMPACT Library.
7
For the latest info, see http://gimpact.sourceforge.net/
9
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
10
email: projectileman@yahoo.com
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:
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.
25
#ifndef GIMPACT_SHAPE_H
26
#define GIMPACT_SHAPE_H
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"
40
#include "btGImpactQuantizedBvh.h" // box tree class
43
//! declare Quantized trees, (you can change to float based trees)
44
typedef btGImpactQuantizedBvh btGImpactBoxSet;
46
enum eGIMPACT_SHAPE_TYPE
48
CONST_GIMPACT_COMPOUND_SHAPE = 0,
49
CONST_GIMPACT_TRIMESH_SHAPE_PART,
50
CONST_GIMPACT_TRIMESH_SHAPE
54
//! Helper class for tetrahedrons
55
class btTetrahedronShapeEx:public btBU_Simplex1to4
58
btTetrahedronShapeEx()
64
SIMD_FORCE_INLINE void setVertices(
65
const btVector3 & v0,const btVector3 & v1,
66
const btVector3 & v2,const btVector3 & v3)
77
//! Base class for gimpact shapes
78
class btGImpactShapeInterface : public btConcaveShape
83
btVector3 localScaling;
84
btGImpactBoxSet m_box_set;// optionally boxset
86
//! use this function for perfofm refit in bounding boxes
87
//! use this function for perfofm refit in bounding boxes
88
virtual void calcLocalAABB()
91
if(m_box_set.getNodeCount() == 0)
101
m_localAABB = m_box_set.getGlobalBox();
106
btGImpactShapeInterface()
108
m_localAABB.invalidate();
109
m_needs_update = true;
110
localScaling.setValue(1.f,1.f,1.f);
114
//! performs refit operation
116
Updates the entire Box set of this shape.
117
\pre postUpdate() must be called for attemps to calculating the box set, else this function
119
\post if m_needs_update == true, then it calls calcLocalAABB();
121
SIMD_FORCE_INLINE void updateBound()
123
if(!m_needs_update) return;
125
m_needs_update = false;
128
//! If the Bounding box is not updated, then this class attemps to calculate it.
130
\post Calls updateBound() for update the box set.
132
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
134
btAABB transformedbox = m_localAABB;
135
transformedbox.appy_transform(t);
136
aabbMin = transformedbox.m_min;
137
aabbMax = transformedbox.m_max;
140
//! Tells to this object that is needed to refit the box set
141
virtual void postUpdate()
143
m_needs_update = true;
146
//! Obtains the local box, which is the global calculated box of the total of subshapes
147
SIMD_FORCE_INLINE const btAABB & getLocalBox()
153
virtual int getShapeType() const
155
return GIMPACT_SHAPE_PROXYTYPE;
159
\post You must call updateBound() for update the box set.
161
virtual void setLocalScaling(const btVector3& scaling)
163
localScaling = scaling;
167
virtual const btVector3& getLocalScaling() const
173
virtual void setMargin(btScalar margin)
175
m_collisionMargin = margin;
176
int i = getNumChildShapes();
179
btCollisionShape* child = getChildShape(i);
180
child->setMargin(margin);
183
m_needs_update = true;
187
//! Subshape member functions
190
//! Base method for determinig which kind of GIMPACT shape we get
191
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() = 0;
194
SIMD_FORCE_INLINE btGImpactBoxSet * getBoxSet()
199
//! Determines if this class has a hierarchy structure for sorting its primitives
200
SIMD_FORCE_INLINE bool hasBoxSet() const
202
if(m_box_set.getNodeCount() == 0) return false;
206
//! Obtains the primitive manager
207
virtual const btPrimitiveManagerBase * getPrimitiveManager() const = 0;
210
//! Gets the number of children
211
virtual int getNumChildShapes() const = 0;
213
//! if true, then its children must get transforms.
214
virtual bool childrenHasTransform() const = 0;
216
//! Determines if this shape has triangles
217
virtual bool needsRetrieveTriangles() const = 0;
219
//! Determines if this shape has tetrahedrons
220
virtual bool needsRetrieveTetrahedrons() const = 0;
222
virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const = 0;
224
virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const = 0;
228
//! call when reading child shapes
229
virtual void lockChildShapes() const
233
virtual void unlockChildShapes() const
238
SIMD_FORCE_INLINE void getPrimitiveTriangle(int index,btPrimitiveTriangle & triangle) const
240
getPrimitiveManager()->get_primitive_triangle(index,triangle);
244
//! Retrieves the bound from a child
247
virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
250
getPrimitiveManager()->get_primitive_box(child_index,child_aabb);
251
child_aabb.appy_transform(t);
252
aabbMin = child_aabb.m_min;
253
aabbMax = child_aabb.m_max;
256
//! Gets the children
257
virtual btCollisionShape* getChildShape(int index) = 0;
261
virtual const btCollisionShape* getChildShape(int index) const = 0;
263
//! Gets the children transform
264
virtual btTransform getChildTransform(int index) const = 0;
266
//! Sets the children transform
268
\post You must call updateBound() for update the box set.
270
virtual void setChildTransform(int index, const btTransform & transform) = 0;
275
//! virtual method for ray collision
276
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
280
//! Function for retrieve triangles.
282
It gives the triangles in local space
284
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
293
//! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once
295
This class only can manage Convex subshapes
297
class btGImpactCompoundShape : public btGImpactShapeInterface
300
//! compound primitive manager
301
class CompoundPrimitiveManager:public btPrimitiveManagerBase
304
btGImpactCompoundShape * m_compoundShape;
307
CompoundPrimitiveManager(const CompoundPrimitiveManager& compound)
309
m_compoundShape = compound.m_compoundShape;
312
CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape)
314
m_compoundShape = compoundShape;
317
CompoundPrimitiveManager()
319
m_compoundShape = NULL;
322
virtual bool is_trimesh() const
327
virtual int get_primitive_count() const
329
return (int )m_compoundShape->getNumChildShapes();
332
virtual void get_primitive_box(int prim_index ,btAABB & primbox) const
334
btTransform prim_trans;
335
if(m_compoundShape->childrenHasTransform())
337
prim_trans = m_compoundShape->getChildTransform(prim_index);
341
prim_trans.setIdentity();
343
const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index);
344
shape->getAabb(prim_trans,primbox.m_min,primbox.m_max);
347
virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const
357
CompoundPrimitiveManager m_primitive_manager;
358
btAlignedObjectArray<btTransform> m_childTransforms;
359
btAlignedObjectArray<btCollisionShape*> m_childShapes;
364
btGImpactCompoundShape(bool children_has_transform = true)
366
m_primitive_manager.m_compoundShape = this;
367
m_box_set.setPrimitiveManager(&m_primitive_manager);
370
virtual ~btGImpactCompoundShape()
375
//! if true, then its children must get transforms.
376
virtual bool childrenHasTransform() const
378
if(m_childTransforms.size()==0) return false;
383
//! Obtains the primitive manager
384
virtual const btPrimitiveManagerBase * getPrimitiveManager() const
386
return &m_primitive_manager;
389
//! Obtains the compopund primitive manager
390
SIMD_FORCE_INLINE CompoundPrimitiveManager * getCompoundPrimitiveManager()
392
return &m_primitive_manager;
395
//! Gets the number of children
396
virtual int getNumChildShapes() const
398
return m_childShapes.size();
402
//! Use this method for adding children. Only Convex shapes are allowed.
403
void addChildShape(const btTransform& localTransform,btCollisionShape* shape)
405
btAssert(shape->isConvex());
406
m_childTransforms.push_back(localTransform);
407
m_childShapes.push_back(shape);
410
//! Use this method for adding children. Only Convex shapes are allowed.
411
void addChildShape(btCollisionShape* shape)
413
btAssert(shape->isConvex());
414
m_childShapes.push_back(shape);
417
//! Gets the children
418
virtual btCollisionShape* getChildShape(int index)
420
return m_childShapes[index];
423
//! Gets the children
424
virtual const btCollisionShape* getChildShape(int index) const
426
return m_childShapes[index];
429
//! Retrieves the bound from a child
432
virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
435
if(childrenHasTransform())
437
m_childShapes[child_index]->getAabb(t*m_childTransforms[child_index],aabbMin,aabbMax);
441
m_childShapes[child_index]->getAabb(t,aabbMin,aabbMax);
446
//! Gets the children transform
447
virtual btTransform getChildTransform(int index) const
449
btAssert(m_childTransforms.size() == m_childShapes.size());
450
return m_childTransforms[index];
453
//! Sets the children transform
455
\post You must call updateBound() for update the box set.
457
virtual void setChildTransform(int index, const btTransform & transform)
459
btAssert(m_childTransforms.size() == m_childShapes.size());
460
m_childTransforms[index] = transform;
464
//! Determines if this shape has triangles
465
virtual bool needsRetrieveTriangles() const
470
//! Determines if this shape has tetrahedrons
471
virtual bool needsRetrieveTetrahedrons() const
477
virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
482
virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
488
//! Calculates the exact inertia tensor for this shape
489
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
491
virtual const char* getName()const
493
return "GImpactCompound";
496
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType()
498
return CONST_GIMPACT_COMPOUND_SHAPE;
505
//! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface.
507
- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh
508
- When making operations with this shape, you must call <b>lock</b> before accessing to the trimesh primitives, and then call <b>unlock</b>
509
- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
512
class btGImpactMeshShapePart : public btGImpactShapeInterface
515
//! Trimesh primitive manager
517
Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism
519
class TrimeshPrimitiveManager:public btPrimitiveManagerBase
523
btStridingMeshInterface * m_meshInterface;
527
const unsigned char *vertexbase;
531
const unsigned char *indexbase;
534
PHY_ScalarType indicestype;
536
TrimeshPrimitiveManager()
538
m_meshInterface = NULL;
541
m_scale = btVector3(1.f,1.f,1.f);
551
TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager)
553
m_meshInterface = manager.m_meshInterface;
554
m_part = manager.m_part;
555
m_margin = manager.m_margin;
556
m_scale = manager.m_scale;
567
TrimeshPrimitiveManager(
568
btStridingMeshInterface * meshInterface, int part)
570
m_meshInterface = meshInterface;
572
m_scale = m_meshInterface->getScaling();
592
m_meshInterface->getLockedReadOnlyVertexIndexBase(
593
&vertexbase,numverts,
594
type, stride,&indexbase, indexstride, numfaces,indicestype,m_part);
601
if(m_lock_count == 0) return;
607
m_meshInterface->unLockReadOnlyVertexBase(m_part);
612
virtual bool is_trimesh() const
617
virtual int get_primitive_count() const
619
return (int )numfaces;
622
SIMD_FORCE_INLINE int get_vertex_count() const
624
return (int )numverts;
627
SIMD_FORCE_INLINE void get_indices(int face_index,int &i0,int &i1,int &i2) const
629
if(indicestype == PHY_SHORT)
631
short * s_indices = (short *)(indexbase + face_index*indexstride);
638
int * i_indices = (int *)(indexbase + face_index*indexstride);
645
SIMD_FORCE_INLINE void get_vertex(int vertex_index, btVector3 & vertex) const
647
if(type == PHY_DOUBLE)
649
double * dvertices = (double *)(vertexbase + vertex_index*stride);
650
vertex[0] = btScalar(dvertices[0]*m_scale[0]);
651
vertex[1] = btScalar(dvertices[1]*m_scale[1]);
652
vertex[2] = btScalar(dvertices[2]*m_scale[2]);
656
float * svertices = (float *)(vertexbase + vertex_index*stride);
657
vertex[0] = svertices[0]*m_scale[0];
658
vertex[1] = svertices[1]*m_scale[1];
659
vertex[2] = svertices[2]*m_scale[2];
663
virtual void get_primitive_box(int prim_index ,btAABB & primbox) const
665
btPrimitiveTriangle triangle;
666
get_primitive_triangle(prim_index,triangle);
667
primbox.calc_from_triangle_margin(
668
triangle.m_vertices[0],
669
triangle.m_vertices[1],triangle.m_vertices[2],triangle.m_margin);
672
virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const
675
get_indices(prim_index,indices[0],indices[1],indices[2]);
676
get_vertex(indices[0],triangle.m_vertices[0]);
677
get_vertex(indices[1],triangle.m_vertices[1]);
678
get_vertex(indices[2],triangle.m_vertices[2]);
679
triangle.m_margin = m_margin;
682
SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle) const
685
get_indices(prim_index,indices[0],indices[1],indices[2]);
686
get_vertex(indices[0],triangle.m_vertices1[0]);
687
get_vertex(indices[1],triangle.m_vertices1[1]);
688
get_vertex(indices[2],triangle.m_vertices1[2]);
689
triangle.setMargin(m_margin);
696
TrimeshPrimitiveManager m_primitive_manager;
699
btGImpactMeshShapePart()
701
m_box_set.setPrimitiveManager(&m_primitive_manager);
705
btGImpactMeshShapePart(btStridingMeshInterface * meshInterface, int part)
707
m_primitive_manager.m_meshInterface = meshInterface;
708
m_primitive_manager.m_part = part;
709
m_box_set.setPrimitiveManager(&m_primitive_manager);
712
virtual ~btGImpactMeshShapePart()
716
//! if true, then its children must get transforms.
717
virtual bool childrenHasTransform() const
723
//! call when reading child shapes
724
virtual void lockChildShapes() const
726
void * dummy = (void*)(m_box_set.getPrimitiveManager());
727
TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>(dummy);
728
dummymanager->lock();
731
virtual void unlockChildShapes() const
733
void * dummy = (void*)(m_box_set.getPrimitiveManager());
734
TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>(dummy);
735
dummymanager->unlock();
738
//! Gets the number of children
739
virtual int getNumChildShapes() const
741
return m_primitive_manager.get_primitive_count();
745
//! Gets the children
746
virtual btCollisionShape* getChildShape(int index)
755
virtual const btCollisionShape* getChildShape(int index) const
761
//! Gets the children transform
762
virtual btTransform getChildTransform(int index) const
765
return btTransform();
768
//! Sets the children transform
770
\post You must call updateBound() for update the box set.
772
virtual void setChildTransform(int index, const btTransform & transform)
778
//! Obtains the primitive manager
779
virtual const btPrimitiveManagerBase * getPrimitiveManager() const
781
return &m_primitive_manager;
784
SIMD_FORCE_INLINE TrimeshPrimitiveManager * getTrimeshPrimitiveManager()
786
return &m_primitive_manager;
793
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
798
virtual const char* getName()const
800
return "GImpactMeshShapePart";
803
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType()
805
return CONST_GIMPACT_TRIMESH_SHAPE_PART;
808
//! Determines if this shape has triangles
809
virtual bool needsRetrieveTriangles() const
814
//! Determines if this shape has tetrahedrons
815
virtual bool needsRetrieveTetrahedrons() const
820
virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
822
m_primitive_manager.get_bullet_triangle(prim_index,triangle);
825
virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
832
SIMD_FORCE_INLINE int getVertexCount() const
834
return m_primitive_manager.get_vertex_count();
837
SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3 & vertex) const
839
m_primitive_manager.get_vertex(vertex_index,vertex);
842
SIMD_FORCE_INLINE void setMargin(btScalar margin)
844
m_primitive_manager.m_margin = margin;
848
SIMD_FORCE_INLINE btScalar getMargin() const
850
return m_primitive_manager.m_margin;
853
virtual void setLocalScaling(const btVector3& scaling)
855
m_primitive_manager.m_scale = scaling;
859
virtual const btVector3& getLocalScaling() const
861
return m_primitive_manager.m_scale;
864
SIMD_FORCE_INLINE int getPart() const
866
return (int)m_primitive_manager.m_part;
869
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
873
//! This class manages a mesh supplied by the btStridingMeshInterface interface.
875
Set of btGImpactMeshShapePart parts
876
- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh
878
- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
881
class btGImpactMeshShape : public btGImpactShapeInterface
884
btAlignedObjectArray<btGImpactMeshShapePart*> m_mesh_parts;
885
void buildMeshParts(btStridingMeshInterface * meshInterface)
887
for (int i=0;i<meshInterface->getNumSubParts() ;++i )
889
btGImpactMeshShapePart * newpart = new btGImpactMeshShapePart(meshInterface,i);
890
m_mesh_parts.push_back(newpart);
894
//! use this function for perfofm refit in bounding boxes
895
virtual void calcLocalAABB()
897
m_localAABB.invalidate();
898
int i = m_mesh_parts.size();
901
m_mesh_parts[i]->updateBound();
902
m_localAABB.merge(m_mesh_parts[i]->getLocalBox());
907
btGImpactMeshShape(btStridingMeshInterface * meshInterface)
909
buildMeshParts(meshInterface);
912
virtual ~btGImpactMeshShape()
914
int i = m_mesh_parts.size();
917
btGImpactMeshShapePart * part = m_mesh_parts[i];
920
m_mesh_parts.clear();
925
int getMeshPartCount() const
927
return m_mesh_parts.size();
930
btGImpactMeshShapePart * getMeshPart(int index)
932
return m_mesh_parts[index];
937
const btGImpactMeshShapePart * getMeshPart(int index) const
939
return m_mesh_parts[index];
943
virtual void setLocalScaling(const btVector3& scaling)
945
localScaling = scaling;
947
int i = m_mesh_parts.size();
950
btGImpactMeshShapePart * part = m_mesh_parts[i];
951
part->setLocalScaling(scaling);
954
m_needs_update = true;
957
virtual void setMargin(btScalar margin)
959
m_collisionMargin = margin;
961
int i = m_mesh_parts.size();
964
btGImpactMeshShapePart * part = m_mesh_parts[i];
965
part->setMargin(margin);
968
m_needs_update = true;
971
//! Tells to this object that is needed to refit all the meshes
972
virtual void postUpdate()
974
int i = m_mesh_parts.size();
977
btGImpactMeshShapePart * part = m_mesh_parts[i];
981
m_needs_update = true;
984
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
987
//! Obtains the primitive manager
988
virtual const btPrimitiveManagerBase * getPrimitiveManager() const
995
//! Gets the number of children
996
virtual int getNumChildShapes() const
1003
//! if true, then its children must get transforms.
1004
virtual bool childrenHasTransform() const
1010
//! Determines if this shape has triangles
1011
virtual bool needsRetrieveTriangles() const
1017
//! Determines if this shape has tetrahedrons
1018
virtual bool needsRetrieveTetrahedrons() const
1024
virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
1029
virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const
1034
//! call when reading child shapes
1035
virtual void lockChildShapes()
1040
virtual void unlockChildShapes()
1048
//! Retrieves the bound from a child
1051
virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
1056
//! Gets the children
1057
virtual btCollisionShape* getChildShape(int index)
1065
virtual const btCollisionShape* getChildShape(int index) const
1071
//! Gets the children transform
1072
virtual btTransform getChildTransform(int index) const
1075
return btTransform();
1078
//! Sets the children transform
1080
\post You must call updateBound() for update the box set.
1082
virtual void setChildTransform(int index, const btTransform & transform)
1088
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType()
1090
return CONST_GIMPACT_TRIMESH_SHAPE;
1094
virtual const char* getName()const
1096
return "GImpactMesh";
1099
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const;
1101
//! Function for retrieve triangles.
1103
It gives the triangles in local space
1105
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
1109
#endif //GIMPACT_MESH_SHAPE_H