2
This source file is part of GIMPACT Library.
4
For the latest info, see http://gimpact.sourceforge.net/
6
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
7
email: projectileman@yahoo.com
10
This software is provided 'as-is', without any express or implied warranty.
11
In no event will the authors be held liable for any damages arising from the use of this software.
12
Permission is granted to anyone to use this software for any purpose,
13
including commercial applications, and to alter it and redistribute it freely,
14
subject to the following restrictions:
16
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.
17
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
18
3. This notice may not be removed or altered from any source distribution.
21
Author: Francisco Len Nļæ½jera
22
Concave-Concave Collision
26
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
27
#include "LinearMath/btIDebugDraw.h"
28
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
29
#include "BulletCollision/CollisionShapes/btBoxShape.h"
30
#include "btGImpactCollisionAlgorithm.h"
31
#include "btContactProcessing.h"
32
#include "LinearMath/btQuickprof.h"
35
//! Class for accessing the plane equation
36
class btPlaneShape : public btStaticPlaneShape
40
btPlaneShape(const btVector3& v, float f)
41
:btStaticPlaneShape(v,f)
45
void get_plane_equation(btVector4 &equation)
47
equation[0] = m_planeNormal[0];
48
equation[1] = m_planeNormal[1];
49
equation[2] = m_planeNormal[2];
50
equation[3] = m_planeConstant;
54
void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation)
56
equation[0] = trans.getBasis().getRow(0).dot(m_planeNormal);
57
equation[1] = trans.getBasis().getRow(1).dot(m_planeNormal);
58
equation[2] = trans.getBasis().getRow(2).dot(m_planeNormal);
59
equation[3] = trans.getOrigin().dot(m_planeNormal) + m_planeConstant;
65
//////////////////////////////////////////////////////////////////////////////////////////////
66
#ifdef TRI_COLLISION_PROFILING
68
btClock g_triangle_clock;
70
float g_accum_triangle_collision_time = 0;
71
int g_count_triangle_collision = 0;
73
void bt_begin_gim02_tri_time()
75
g_triangle_clock.reset();
78
void bt_end_gim02_tri_time()
80
g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds();
81
g_count_triangle_collision++;
83
#endif //TRI_COLLISION_PROFILING
84
//! Retrieving shapes shapes
86
Declared here due of insuficent space on Pool allocators
89
class GIM_ShapeRetriever
92
btGImpactShapeInterface * m_gim_shape;
93
btTriangleShapeEx m_trishape;
94
btTetrahedronShapeEx m_tetrashape;
97
class ChildShapeRetriever
100
GIM_ShapeRetriever * m_parent;
101
virtual btCollisionShape * getChildShape(int index)
103
return m_parent->m_gim_shape->getChildShape(index);
105
virtual ~ChildShapeRetriever() {}
108
class TriangleShapeRetriever:public ChildShapeRetriever
112
virtual btCollisionShape * getChildShape(int index)
114
m_parent->m_gim_shape->getBulletTriangle(index,m_parent->m_trishape);
115
return &m_parent->m_trishape;
117
virtual ~TriangleShapeRetriever() {}
120
class TetraShapeRetriever:public ChildShapeRetriever
124
virtual btCollisionShape * getChildShape(int index)
126
m_parent->m_gim_shape->getBulletTetrahedron(index,m_parent->m_tetrashape);
127
return &m_parent->m_tetrashape;
131
ChildShapeRetriever m_child_retriever;
132
TriangleShapeRetriever m_tri_retriever;
133
TetraShapeRetriever m_tetra_retriever;
134
ChildShapeRetriever * m_current_retriever;
136
GIM_ShapeRetriever(btGImpactShapeInterface * gim_shape)
138
m_gim_shape = gim_shape;
140
if(m_gim_shape->needsRetrieveTriangles())
142
m_current_retriever = &m_tri_retriever;
144
else if(m_gim_shape->needsRetrieveTetrahedrons())
146
m_current_retriever = &m_tetra_retriever;
150
m_current_retriever = &m_child_retriever;
153
m_current_retriever->m_parent = this;
156
btCollisionShape * getChildShape(int index)
158
return m_current_retriever->getChildShape(index);
169
#ifdef TRI_COLLISION_PROFILING
171
//! Gets the average time in miliseconds of tree collisions
172
float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()
174
return btGImpactBoxSet::getAverageTreeCollisionTime();
178
//! Gets the average time in miliseconds of triangle collisions
179
float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
181
if(g_count_triangle_collision == 0) return 0;
183
float avgtime = g_accum_triangle_collision_time;
184
avgtime /= (float)g_count_triangle_collision;
186
g_accum_triangle_collision_time = 0;
187
g_count_triangle_collision = 0;
192
#endif //TRI_COLLISION_PROFILING
196
btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
197
: btActivatingCollisionAlgorithm(ci,body0,body1)
199
m_manifoldPtr = NULL;
200
m_convex_algorithm = NULL;
203
btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
212
void btGImpactCollisionAlgorithm::addContactPoint(btCollisionObject * body0,
213
btCollisionObject * body1,
214
const btVector3 & point,
215
const btVector3 & normal,
218
m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
219
m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
220
checkManifold(body0,body1);
221
m_resultOut->addContactPoint(normal,point,distance);
225
void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
226
btCollisionObject * body0,
227
btCollisionObject * body1,
228
btCollisionShape * shape0,
229
btCollisionShape * shape1)
232
btCollisionShape* tmpShape0 = body0->getCollisionShape();
233
btCollisionShape* tmpShape1 = body1->getCollisionShape();
235
body0->internalSetTemporaryCollisionShape(shape0);
236
body1->internalSetTemporaryCollisionShape(shape1);
239
btCollisionAlgorithm* algor = newAlgorithm(body0,body1);
240
// post : checkManifold is called
242
m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
243
m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
245
algor->processCollision(body0,body1,*m_dispatchInfo,m_resultOut);
247
algor->~btCollisionAlgorithm();
248
m_dispatcher->freeCollisionAlgorithm(algor);
251
body0->internalSetTemporaryCollisionShape(tmpShape0);
252
body1->internalSetTemporaryCollisionShape(tmpShape1);
255
void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
256
btCollisionObject * body0,
257
btCollisionObject * body1,
258
btCollisionShape * shape0,
259
btCollisionShape * shape1)
262
btCollisionShape* tmpShape0 = body0->getCollisionShape();
263
btCollisionShape* tmpShape1 = body1->getCollisionShape();
265
body0->internalSetTemporaryCollisionShape(shape0);
266
body1->internalSetTemporaryCollisionShape(shape1);
269
m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
270
m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
272
checkConvexAlgorithm(body0,body1);
273
m_convex_algorithm->processCollision(body0,body1,*m_dispatchInfo,m_resultOut);
275
body0->internalSetTemporaryCollisionShape(tmpShape0);
276
body1->internalSetTemporaryCollisionShape(tmpShape1);
283
void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
284
const btTransform & trans0,
285
const btTransform & trans1,
286
btGImpactShapeInterface * shape0,
287
btGImpactShapeInterface * shape1,btPairSet & pairset)
289
if(shape0->hasBoxSet() && shape1->hasBoxSet())
291
btGImpactBoxSet::find_collision(shape0->getBoxSet(),trans0,shape1->getBoxSet(),trans1,pairset);
297
int i = shape0->getNumChildShapes();
301
shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
303
int j = shape1->getNumChildShapes();
306
shape1->getChildAabb(i,trans1,boxshape1.m_min,boxshape1.m_max);
308
if(boxshape1.has_collision(boxshape0))
310
pairset.push_pair(i,j);
320
void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
321
const btTransform & trans0,
322
const btTransform & trans1,
323
btGImpactShapeInterface * shape0,
324
btCollisionShape * shape1,
325
btAlignedObjectArray<int> & collided_primitives)
331
if(shape0->hasBoxSet())
333
btTransform trans1to0 = trans0.inverse();
336
shape1->getAabb(trans1to0,boxshape.m_min,boxshape.m_max);
338
shape0->getBoxSet()->boxQuery(boxshape, collided_primitives);
342
shape1->getAabb(trans1,boxshape.m_min,boxshape.m_max);
345
int i = shape0->getNumChildShapes();
349
shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
351
if(boxshape.has_collision(boxshape0))
353
collided_primitives.push_back(i);
362
void btGImpactCollisionAlgorithm::collide_gjk_triangles(btCollisionObject * body0,
363
btCollisionObject * body1,
364
btGImpactMeshShapePart * shape0,
365
btGImpactMeshShapePart * shape1,
366
const int * pairs, int pair_count)
368
btTriangleShapeEx tri0;
369
btTriangleShapeEx tri1;
371
shape0->lockChildShapes();
372
shape1->lockChildShapes();
374
const int * pair_pointer = pairs;
379
m_triface0 = *(pair_pointer);
380
m_triface1 = *(pair_pointer+1);
385
shape0->getBulletTriangle(m_triface0,tri0);
386
shape1->getBulletTriangle(m_triface1,tri1);
389
//collide two convex shapes
390
if(tri0.overlap_test_conservative(tri1))
392
convex_vs_convex_collision(body0,body1,&tri0,&tri1);
397
shape0->unlockChildShapes();
398
shape1->unlockChildShapes();
401
void btGImpactCollisionAlgorithm::collide_sat_triangles(btCollisionObject * body0,
402
btCollisionObject * body1,
403
btGImpactMeshShapePart * shape0,
404
btGImpactMeshShapePart * shape1,
405
const int * pairs, int pair_count)
407
btTransform orgtrans0 = body0->getWorldTransform();
408
btTransform orgtrans1 = body1->getWorldTransform();
410
btPrimitiveTriangle ptri0;
411
btPrimitiveTriangle ptri1;
412
GIM_TRIANGLE_CONTACT contact_data;
414
shape0->lockChildShapes();
415
shape1->lockChildShapes();
417
const int * pair_pointer = pairs;
422
m_triface0 = *(pair_pointer);
423
m_triface1 = *(pair_pointer+1);
427
shape0->getPrimitiveTriangle(m_triface0,ptri0);
428
shape1->getPrimitiveTriangle(m_triface1,ptri1);
430
#ifdef TRI_COLLISION_PROFILING
431
bt_begin_gim02_tri_time();
434
ptri0.applyTransform(orgtrans0);
435
ptri1.applyTransform(orgtrans1);
439
ptri0.buildTriPlane();
440
ptri1.buildTriPlane();
445
if(ptri0.overlap_test_conservative(ptri1))
447
if(ptri0.find_triangle_collision_clip_method(ptri1,contact_data))
450
int j = contact_data.m_point_count;
454
addContactPoint(body0, body1,
455
contact_data.m_points[j],
456
contact_data.m_separating_normal,
457
-contact_data.m_penetration_depth);
462
#ifdef TRI_COLLISION_PROFILING
463
bt_end_gim02_tri_time();
468
shape0->unlockChildShapes();
469
shape1->unlockChildShapes();
474
void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
475
btCollisionObject * body0,
476
btCollisionObject * body1,
477
btGImpactShapeInterface * shape0,
478
btGImpactShapeInterface * shape1)
481
if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
483
btGImpactMeshShape * meshshape0 = static_cast<btGImpactMeshShape *>(shape0);
484
m_part0 = meshshape0->getMeshPartCount();
488
gimpact_vs_gimpact(body0,body1,meshshape0->getMeshPart(m_part0),shape1);
494
if(shape1->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
496
btGImpactMeshShape * meshshape1 = static_cast<btGImpactMeshShape *>(shape1);
497
m_part1 = meshshape1->getMeshPartCount();
502
gimpact_vs_gimpact(body0,body1,shape0,meshshape1->getMeshPart(m_part1));
510
btTransform orgtrans0 = body0->getWorldTransform();
511
btTransform orgtrans1 = body1->getWorldTransform();
515
gimpact_vs_gimpact_find_pairs(orgtrans0,orgtrans1,shape0,shape1,pairset);
517
if(pairset.size()== 0) return;
519
if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
520
shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART)
522
btGImpactMeshShapePart * shapepart0 = static_cast<btGImpactMeshShapePart * >(shape0);
523
btGImpactMeshShapePart * shapepart1 = static_cast<btGImpactMeshShapePart * >(shape1);
524
//specialized function
525
#ifdef BULLET_TRIANGLE_COLLISION
526
collide_gjk_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
528
collide_sat_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
536
shape0->lockChildShapes();
537
shape1->lockChildShapes();
539
GIM_ShapeRetriever retriever0(shape0);
540
GIM_ShapeRetriever retriever1(shape1);
542
bool child_has_transform0 = shape0->childrenHasTransform();
543
bool child_has_transform1 = shape1->childrenHasTransform();
545
int i = pairset.size();
548
GIM_PAIR * pair = &pairset[i];
549
m_triface0 = pair->m_index1;
550
m_triface1 = pair->m_index2;
551
btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0);
552
btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1);
554
if(child_has_transform0)
556
body0->setWorldTransform(orgtrans0*shape0->getChildTransform(m_triface0));
559
if(child_has_transform1)
561
body1->setWorldTransform(orgtrans1*shape1->getChildTransform(m_triface1));
564
//collide two convex shapes
565
convex_vs_convex_collision(body0,body1,colshape0,colshape1);
568
if(child_has_transform0)
570
body0->setWorldTransform(orgtrans0);
573
if(child_has_transform1)
575
body1->setWorldTransform(orgtrans1);
580
shape0->unlockChildShapes();
581
shape1->unlockChildShapes();
584
void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0,
585
btCollisionObject * body1,
586
btGImpactShapeInterface * shape0,
587
btCollisionShape * shape1,bool swapped)
589
if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
591
btGImpactMeshShape * meshshape0 = static_cast<btGImpactMeshShape *>(shape0);
592
int& part = swapped ? m_part1 : m_part0;
593
part = meshshape0->getMeshPartCount();
598
gimpact_vs_shape(body0,
600
meshshape0->getMeshPart(part),
608
#ifdef GIMPACT_VS_PLANE_COLLISION
609
if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
610
shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
612
btGImpactMeshShapePart * shapepart = static_cast<btGImpactMeshShapePart *>(shape0);
613
btStaticPlaneShape * planeshape = static_cast<btStaticPlaneShape * >(shape1);
614
gimpacttrimeshpart_vs_plane_collision(body0,body1,shapepart,planeshape,swapped);
622
if(shape1->isCompound())
624
btCompoundShape * compoundshape = static_cast<btCompoundShape *>(shape1);
625
gimpact_vs_compoundshape(body0,body1,shape0,compoundshape,swapped);
628
else if(shape1->isConcave())
630
btConcaveShape * concaveshape = static_cast<btConcaveShape *>(shape1);
631
gimpact_vs_concave(body0,body1,shape0,concaveshape,swapped);
636
btTransform orgtrans0 = body0->getWorldTransform();
638
btTransform orgtrans1 = body1->getWorldTransform();
640
btAlignedObjectArray<int> collided_results;
642
gimpact_vs_shape_find_pairs(orgtrans0,orgtrans1,shape0,shape1,collided_results);
644
if(collided_results.size() == 0) return;
647
shape0->lockChildShapes();
649
GIM_ShapeRetriever retriever0(shape0);
652
bool child_has_transform0 = shape0->childrenHasTransform();
655
int i = collided_results.size();
659
int child_index = collided_results[i];
661
m_triface1 = child_index;
663
m_triface0 = child_index;
665
btCollisionShape * colshape0 = retriever0.getChildShape(child_index);
667
if(child_has_transform0)
669
body0->setWorldTransform(orgtrans0*shape0->getChildTransform(child_index));
675
shape_vs_shape_collision(body1,body0,shape1,colshape0);
679
shape_vs_shape_collision(body0,body1,colshape0,shape1);
683
if(child_has_transform0)
685
body0->setWorldTransform(orgtrans0);
690
shape0->unlockChildShapes();
694
void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(btCollisionObject * body0,
695
btCollisionObject * body1,
696
btGImpactShapeInterface * shape0,
697
btCompoundShape * shape1,bool swapped)
699
btTransform orgtrans1 = body1->getWorldTransform();
701
int i = shape1->getNumChildShapes();
705
btCollisionShape * colshape1 = shape1->getChildShape(i);
706
btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i);
708
body1->setWorldTransform(childtrans1);
710
//collide child shape
711
gimpact_vs_shape(body0, body1,
712
shape0,colshape1,swapped);
716
body1->setWorldTransform(orgtrans1);
720
void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
721
btCollisionObject * body0,
722
btCollisionObject * body1,
723
btGImpactMeshShapePart * shape0,
724
btStaticPlaneShape * shape1,bool swapped)
728
btTransform orgtrans0 = body0->getWorldTransform();
729
btTransform orgtrans1 = body1->getWorldTransform();
731
btPlaneShape * planeshape = static_cast<btPlaneShape *>(shape1);
733
planeshape->get_plane_equation_transformed(orgtrans1,plane);
735
//test box against plane
738
shape0->getAabb(orgtrans0,tribox.m_min,tribox.m_max);
739
tribox.increment_margin(planeshape->getMargin());
741
if( tribox.plane_classify(plane)!= BT_CONST_COLLIDE_PLANE) return;
743
shape0->lockChildShapes();
745
btScalar margin = shape0->getMargin() + planeshape->getMargin();
748
int vi = shape0->getVertexCount();
751
shape0->getVertex(vi,vertex);
752
vertex = orgtrans0(vertex);
754
btScalar distance = vertex.dot(plane) - plane[3] - margin;
756
if(distance<0.0)//add contact
760
addContactPoint(body1, body0,
767
addContactPoint(body0, body1,
775
shape0->unlockChildShapes();
781
class btGImpactTriangleCallback: public btTriangleCallback
784
btGImpactCollisionAlgorithm * algorithm;
785
btCollisionObject * body0;
786
btCollisionObject * body1;
787
btGImpactShapeInterface * gimpactshape0;
791
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
793
btTriangleShapeEx tri1(triangle[0],triangle[1],triangle[2]);
794
tri1.setMargin(margin);
797
algorithm->setPart0(partId);
798
algorithm->setFace0(triangleIndex);
802
algorithm->setPart1(partId);
803
algorithm->setFace1(triangleIndex);
805
algorithm->gimpact_vs_shape(
806
body0,body1,gimpactshape0,&tri1,swapped);
813
void btGImpactCollisionAlgorithm::gimpact_vs_concave(
814
btCollisionObject * body0,
815
btCollisionObject * body1,
816
btGImpactShapeInterface * shape0,
817
btConcaveShape * shape1,bool swapped)
819
//create the callback
820
btGImpactTriangleCallback tricallback;
821
tricallback.algorithm = this;
822
tricallback.body0 = body0;
823
tricallback.body1 = body1;
824
tricallback.gimpactshape0 = shape0;
825
tricallback.swapped = swapped;
826
tricallback.margin = shape1->getMargin();
828
//getting the trimesh AABB
829
btTransform gimpactInConcaveSpace;
831
gimpactInConcaveSpace = body1->getWorldTransform().inverse() * body0->getWorldTransform();
833
btVector3 minAABB,maxAABB;
834
shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB);
836
shape1->processAllTriangles(&tricallback,minAABB,maxAABB);
842
void btGImpactCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
846
m_resultOut = resultOut;
847
m_dispatchInfo = &dispatchInfo;
848
btGImpactShapeInterface * gimpactshape0;
849
btGImpactShapeInterface * gimpactshape1;
851
if (body0->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE)
853
gimpactshape0 = static_cast<btGImpactShapeInterface *>(body0->getCollisionShape());
855
if( body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
857
gimpactshape1 = static_cast<btGImpactShapeInterface *>(body1->getCollisionShape());
859
gimpact_vs_gimpact(body0,body1,gimpactshape0,gimpactshape1);
863
gimpact_vs_shape(body0,body1,gimpactshape0,body1->getCollisionShape(),false);
867
else if (body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
869
gimpactshape1 = static_cast<btGImpactShapeInterface *>(body1->getCollisionShape());
871
gimpact_vs_shape(body1,body0,gimpactshape1,body0->getCollisionShape(),true);
876
btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
882
///////////////////////////////////// REGISTERING ALGORITHM //////////////////////////////////////////////
886
//! Use this function for register the algorithm externally
887
void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher * dispatcher)
890
static btGImpactCollisionAlgorithm::CreateFunc s_gimpact_cf;
894
for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
896
dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,i ,&s_gimpact_cf);
899
for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
901
dispatcher->registerCollisionCreateFunc(i,GIMPACT_SHAPE_PROXYTYPE ,&s_gimpact_cf);