Bullet Collision Detection & Physics Library
btGImpactCollisionAlgorithm.cpp
Go to the documentation of this file.
1 /*
2 This source file is part of GIMPACT Library.
3 
4 For the latest info, see http://gimpact.sourceforge.net/
5 
6 Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
7 email: projectileman@yahoo.com
8 
9 
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:
15 
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.
19 */
20 /*
21 Author: Francisco Len Nßjera
22 Concave-Concave Collision
23 
24 */
25 
31 #include "btContactProcessing.h"
32 #include "LinearMath/btQuickprof.h"
33 
34 
37 {
38 public:
39 
40  btPlaneShape(const btVector3& v, float f)
41  :btStaticPlaneShape(v,f)
42  {
43  }
44 
45  void get_plane_equation(btVector4 &equation)
46  {
47  equation[0] = m_planeNormal[0];
48  equation[1] = m_planeNormal[1];
49  equation[2] = m_planeNormal[2];
50  equation[3] = m_planeConstant;
51  }
52 
53 
54  void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation) const
55  {
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;
60  }
61 };
62 
63 
64 
66 #ifdef TRI_COLLISION_PROFILING
67 
68 btClock g_triangle_clock;
69 
70 float g_accum_triangle_collision_time = 0;
71 int g_count_triangle_collision = 0;
72 
73 void bt_begin_gim02_tri_time()
74 {
75  g_triangle_clock.reset();
76 }
77 
78 void bt_end_gim02_tri_time()
79 {
80  g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds();
81  g_count_triangle_collision++;
82 }
83 #endif //TRI_COLLISION_PROFILING
84 
90 {
91 public:
95 
96 public:
98  {
99  public:
101  virtual const btCollisionShape * getChildShape(int index)
102  {
103  return m_parent->m_gim_shape->getChildShape(index);
104  }
105  virtual ~ChildShapeRetriever() {}
106  };
107 
109  {
110  public:
111 
112  virtual btCollisionShape * getChildShape(int index)
113  {
115  return &m_parent->m_trishape;
116  }
118  };
119 
121  {
122  public:
123 
124  virtual btCollisionShape * getChildShape(int index)
125  {
127  return &m_parent->m_tetrashape;
128  }
129  };
130 public:
135 
137  {
138  m_gim_shape = gim_shape;
139  //select retriever
141  {
143  }
145  {
147  }
148  else
149  {
151  }
152 
154  }
155 
156  const btCollisionShape * getChildShape(int index)
157  {
158  return m_current_retriever->getChildShape(index);
159  }
160 
161 
162 };
163 
164 
165 
167 
168 
169 #ifdef TRI_COLLISION_PROFILING
170 
172 float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()
173 {
174  return btGImpactBoxSet::getAverageTreeCollisionTime();
175 
176 }
177 
179 float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
180 {
181  if(g_count_triangle_collision == 0) return 0;
182 
183  float avgtime = g_accum_triangle_collision_time;
184  avgtime /= (float)g_count_triangle_collision;
185 
186  g_accum_triangle_collision_time = 0;
187  g_count_triangle_collision = 0;
188 
189  return avgtime;
190 }
191 
192 #endif //TRI_COLLISION_PROFILING
193 
194 
195 
197 : btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap)
198 {
199  m_manifoldPtr = NULL;
200  m_convex_algorithm = NULL;
201 }
202 
204 {
205  clearCache();
206 }
207 
208 
209 
210 
211 
213  const btCollisionObjectWrapper * body1Wrap,
214  const btVector3 & point,
215  const btVector3 & normal,
216  btScalar distance)
217 {
220  checkManifold(body0Wrap,body1Wrap);
221  m_resultOut->addContactPoint(normal,point,distance);
222 }
223 
224 
226  const btCollisionObjectWrapper * body0Wrap,
227  const btCollisionObjectWrapper* body1Wrap,
228  const btCollisionShape * shape0,
229  const btCollisionShape * shape1)
230 {
231 
232 
233  {
234  btCollisionObjectWrapper ob0(body0Wrap,shape0,body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform());
235  btCollisionObjectWrapper ob1(body1Wrap,shape1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform());
236 
237  btCollisionAlgorithm* algor = newAlgorithm(&ob0,&ob1);
238  // post : checkManifold is called
239 
242 
243  algor->processCollision(&ob0,&ob1,*m_dispatchInfo,m_resultOut);
244 
245  algor->~btCollisionAlgorithm();
247  }
248 
249 }
250 
252  const btCollisionObjectWrapper* body0Wrap,
253  const btCollisionObjectWrapper* body1Wrap,
254  const btCollisionShape* shape0,
255  const btCollisionShape* shape1)
256 {
257 
260 
261  btCollisionObjectWrapper ob0(body0Wrap,shape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform());
262  btCollisionObjectWrapper ob1(body1Wrap,shape1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform());
263  checkConvexAlgorithm(&ob0,&ob1);
265 
266 
267 }
268 
269 
270 
271 
273  const btTransform & trans0,
274  const btTransform & trans1,
275  const btGImpactShapeInterface * shape0,
276  const btGImpactShapeInterface * shape1,btPairSet & pairset)
277 {
278  if(shape0->hasBoxSet() && shape1->hasBoxSet())
279  {
280  btGImpactBoxSet::find_collision(shape0->getBoxSet(),trans0,shape1->getBoxSet(),trans1,pairset);
281  }
282  else
283  {
284  btAABB boxshape0;
285  btAABB boxshape1;
286  int i = shape0->getNumChildShapes();
287 
288  while(i--)
289  {
290  shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
291 
292  int j = shape1->getNumChildShapes();
293  while(j--)
294  {
295  shape1->getChildAabb(i,trans1,boxshape1.m_min,boxshape1.m_max);
296 
297  if(boxshape1.has_collision(boxshape0))
298  {
299  pairset.push_pair(i,j);
300  }
301  }
302  }
303  }
304 
305 
306 }
307 
308 
310  const btTransform & trans0,
311  const btTransform & trans1,
312  const btGImpactShapeInterface * shape0,
313  const btCollisionShape * shape1,
314  btAlignedObjectArray<int> & collided_primitives)
315 {
316 
317  btAABB boxshape;
318 
319 
320  if(shape0->hasBoxSet())
321  {
322  btTransform trans1to0 = trans0.inverse();
323  trans1to0 *= trans1;
324 
325  shape1->getAabb(trans1to0,boxshape.m_min,boxshape.m_max);
326 
327  shape0->getBoxSet()->boxQuery(boxshape, collided_primitives);
328  }
329  else
330  {
331  shape1->getAabb(trans1,boxshape.m_min,boxshape.m_max);
332 
333  btAABB boxshape0;
334  int i = shape0->getNumChildShapes();
335 
336  while(i--)
337  {
338  shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
339 
340  if(boxshape.has_collision(boxshape0))
341  {
342  collided_primitives.push_back(i);
343  }
344  }
345 
346  }
347 
348 }
349 
350 
352  const btCollisionObjectWrapper * body1Wrap,
353  const btGImpactMeshShapePart * shape0,
354  const btGImpactMeshShapePart * shape1,
355  const int * pairs, int pair_count)
356 {
357  btTriangleShapeEx tri0;
358  btTriangleShapeEx tri1;
359 
360  shape0->lockChildShapes();
361  shape1->lockChildShapes();
362 
363  const int * pair_pointer = pairs;
364 
365  while(pair_count--)
366  {
367 
368  m_triface0 = *(pair_pointer);
369  m_triface1 = *(pair_pointer+1);
370  pair_pointer+=2;
371 
372 
373 
374  shape0->getBulletTriangle(m_triface0,tri0);
375  shape1->getBulletTriangle(m_triface1,tri1);
376 
377 
378  //collide two convex shapes
379  if(tri0.overlap_test_conservative(tri1))
380  {
381  convex_vs_convex_collision(body0Wrap,body1Wrap,&tri0,&tri1);
382  }
383 
384  }
385 
386  shape0->unlockChildShapes();
387  shape1->unlockChildShapes();
388 }
389 
391  const btCollisionObjectWrapper* body1Wrap,
392  const btGImpactMeshShapePart * shape0,
393  const btGImpactMeshShapePart * shape1,
394  const int * pairs, int pair_count)
395 {
396  btTransform orgtrans0 = body0Wrap->getWorldTransform();
397  btTransform orgtrans1 = body1Wrap->getWorldTransform();
398 
399  btPrimitiveTriangle ptri0;
400  btPrimitiveTriangle ptri1;
401  GIM_TRIANGLE_CONTACT contact_data;
402 
403  shape0->lockChildShapes();
404  shape1->lockChildShapes();
405 
406  const int * pair_pointer = pairs;
407 
408  while(pair_count--)
409  {
410 
411  m_triface0 = *(pair_pointer);
412  m_triface1 = *(pair_pointer+1);
413  pair_pointer+=2;
414 
415 
416  shape0->getPrimitiveTriangle(m_triface0,ptri0);
417  shape1->getPrimitiveTriangle(m_triface1,ptri1);
418 
419  #ifdef TRI_COLLISION_PROFILING
420  bt_begin_gim02_tri_time();
421  #endif
422 
423  ptri0.applyTransform(orgtrans0);
424  ptri1.applyTransform(orgtrans1);
425 
426 
427  //build planes
428  ptri0.buildTriPlane();
429  ptri1.buildTriPlane();
430  // test conservative
431 
432 
433 
434  if(ptri0.overlap_test_conservative(ptri1))
435  {
436  if(ptri0.find_triangle_collision_clip_method(ptri1,contact_data))
437  {
438 
439  int j = contact_data.m_point_count;
440  while(j--)
441  {
442 
443  addContactPoint(body0Wrap, body1Wrap,
444  contact_data.m_points[j],
445  contact_data.m_separating_normal,
446  -contact_data.m_penetration_depth);
447  }
448  }
449  }
450 
451  #ifdef TRI_COLLISION_PROFILING
452  bt_end_gim02_tri_time();
453  #endif
454 
455  }
456 
457  shape0->unlockChildShapes();
458  shape1->unlockChildShapes();
459 
460 }
461 
462 
464  const btCollisionObjectWrapper* body0Wrap,
465  const btCollisionObjectWrapper * body1Wrap,
466  const btGImpactShapeInterface * shape0,
467  const btGImpactShapeInterface * shape1)
468 {
469 
471  {
472  const btGImpactMeshShape * meshshape0 = static_cast<const btGImpactMeshShape *>(shape0);
473  m_part0 = meshshape0->getMeshPartCount();
474 
475  while(m_part0--)
476  {
477  gimpact_vs_gimpact(body0Wrap,body1Wrap,meshshape0->getMeshPart(m_part0),shape1);
478  }
479 
480  return;
481  }
482 
484  {
485  const btGImpactMeshShape * meshshape1 = static_cast<const btGImpactMeshShape *>(shape1);
486  m_part1 = meshshape1->getMeshPartCount();
487 
488  while(m_part1--)
489  {
490 
491  gimpact_vs_gimpact(body0Wrap,body1Wrap,shape0,meshshape1->getMeshPart(m_part1));
492 
493  }
494 
495  return;
496  }
497 
498 
499  btTransform orgtrans0 = body0Wrap->getWorldTransform();
500  btTransform orgtrans1 = body1Wrap->getWorldTransform();
501 
502  btPairSet pairset;
503 
504  gimpact_vs_gimpact_find_pairs(orgtrans0,orgtrans1,shape0,shape1,pairset);
505 
506  if(pairset.size()== 0) return;
507 
510  {
511  const btGImpactMeshShapePart * shapepart0 = static_cast<const btGImpactMeshShapePart * >(shape0);
512  const btGImpactMeshShapePart * shapepart1 = static_cast<const btGImpactMeshShapePart * >(shape1);
513  //specialized function
514  #ifdef BULLET_TRIANGLE_COLLISION
515  collide_gjk_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
516  #else
517  collide_sat_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
518  #endif
519 
520  return;
521  }
522 
523  //general function
524 
525  shape0->lockChildShapes();
526  shape1->lockChildShapes();
527 
528  GIM_ShapeRetriever retriever0(shape0);
529  GIM_ShapeRetriever retriever1(shape1);
530 
531  bool child_has_transform0 = shape0->childrenHasTransform();
532  bool child_has_transform1 = shape1->childrenHasTransform();
533 
534  int i = pairset.size();
535  while(i--)
536  {
537  GIM_PAIR * pair = &pairset[i];
538  m_triface0 = pair->m_index1;
539  m_triface1 = pair->m_index2;
540  const btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0);
541  const btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1);
542 
543  btTransform tr0 = body0Wrap->getWorldTransform();
544  btTransform tr1 = body1Wrap->getWorldTransform();
545 
546  if(child_has_transform0)
547  {
548  tr0 = orgtrans0*shape0->getChildTransform(m_triface0);
549  }
550 
551  if(child_has_transform1)
552  {
553  tr1 = orgtrans1*shape1->getChildTransform(m_triface1);
554  }
555 
556  btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),tr0);
557  btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),tr1);
558 
559  //collide two convex shapes
560  convex_vs_convex_collision(&ob0,&ob1,colshape0,colshape1);
561  }
562 
563  shape0->unlockChildShapes();
564  shape1->unlockChildShapes();
565 }
566 
568  const btCollisionObjectWrapper * body1Wrap,
569  const btGImpactShapeInterface * shape0,
570  const btCollisionShape * shape1,bool swapped)
571 {
573  {
574  const btGImpactMeshShape * meshshape0 = static_cast<const btGImpactMeshShape *>(shape0);
575  int& part = swapped ? m_part1 : m_part0;
576  part = meshshape0->getMeshPartCount();
577 
578  while(part--)
579  {
580 
581  gimpact_vs_shape(body0Wrap,
582  body1Wrap,
583  meshshape0->getMeshPart(part),
584  shape1,swapped);
585 
586  }
587 
588  return;
589  }
590 
591  #ifdef GIMPACT_VS_PLANE_COLLISION
594  {
595  const btGImpactMeshShapePart * shapepart = static_cast<const btGImpactMeshShapePart *>(shape0);
596  const btStaticPlaneShape * planeshape = static_cast<const btStaticPlaneShape * >(shape1);
597  gimpacttrimeshpart_vs_plane_collision(body0Wrap,body1Wrap,shapepart,planeshape,swapped);
598  return;
599  }
600 
601  #endif
602 
603 
604 
605  if(shape1->isCompound())
606  {
607  const btCompoundShape * compoundshape = static_cast<const btCompoundShape *>(shape1);
608  gimpact_vs_compoundshape(body0Wrap,body1Wrap,shape0,compoundshape,swapped);
609  return;
610  }
611  else if(shape1->isConcave())
612  {
613  const btConcaveShape * concaveshape = static_cast<const btConcaveShape *>(shape1);
614  gimpact_vs_concave(body0Wrap,body1Wrap,shape0,concaveshape,swapped);
615  return;
616  }
617 
618 
619  btTransform orgtrans0 = body0Wrap->getWorldTransform();
620 
621  btTransform orgtrans1 = body1Wrap->getWorldTransform();
622 
623  btAlignedObjectArray<int> collided_results;
624 
625  gimpact_vs_shape_find_pairs(orgtrans0,orgtrans1,shape0,shape1,collided_results);
626 
627  if(collided_results.size() == 0) return;
628 
629 
630  shape0->lockChildShapes();
631 
632  GIM_ShapeRetriever retriever0(shape0);
633 
634 
635  bool child_has_transform0 = shape0->childrenHasTransform();
636 
637 
638  int i = collided_results.size();
639 
640  while(i--)
641  {
642  int child_index = collided_results[i];
643  if(swapped)
644  m_triface1 = child_index;
645  else
646  m_triface0 = child_index;
647 
648  const btCollisionShape * colshape0 = retriever0.getChildShape(child_index);
649 
650  btTransform tr0 = body0Wrap->getWorldTransform();
651 
652  if(child_has_transform0)
653  {
654  tr0 = orgtrans0*shape0->getChildTransform(child_index);
655  }
656 
657  btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform());
658 
659  //collide two shapes
660  if(swapped)
661  {
662  shape_vs_shape_collision(body1Wrap,&ob0,shape1,colshape0);
663  }
664  else
665  {
666  shape_vs_shape_collision(&ob0,body1Wrap,colshape0,shape1);
667  }
668 
669  }
670 
671  shape0->unlockChildShapes();
672 
673 }
674 
676  const btCollisionObjectWrapper* body1Wrap,
677  const btGImpactShapeInterface * shape0,
678  const btCompoundShape * shape1,bool swapped)
679 {
680  btTransform orgtrans1 = body1Wrap->getWorldTransform();
681 
682  int i = shape1->getNumChildShapes();
683  while(i--)
684  {
685 
686  const btCollisionShape * colshape1 = shape1->getChildShape(i);
687  btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i);
688 
689  btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),childtrans1);
690  //collide child shape
691  gimpact_vs_shape(body0Wrap, &ob1,
692  shape0,colshape1,swapped);
693  }
694 }
695 
697  const btCollisionObjectWrapper * body0Wrap,
698  const btCollisionObjectWrapper * body1Wrap,
699  const btGImpactMeshShapePart * shape0,
700  const btStaticPlaneShape * shape1,bool swapped)
701 {
702 
703 
704  btTransform orgtrans0 = body0Wrap->getWorldTransform();
705  btTransform orgtrans1 = body1Wrap->getWorldTransform();
706 
707  const btPlaneShape * planeshape = static_cast<const btPlaneShape *>(shape1);
708  btVector4 plane;
709  planeshape->get_plane_equation_transformed(orgtrans1,plane);
710 
711  //test box against plane
712 
713  btAABB tribox;
714  shape0->getAabb(orgtrans0,tribox.m_min,tribox.m_max);
715  tribox.increment_margin(planeshape->getMargin());
716 
717  if( tribox.plane_classify(plane)!= BT_CONST_COLLIDE_PLANE) return;
718 
719  shape0->lockChildShapes();
720 
721  btScalar margin = shape0->getMargin() + planeshape->getMargin();
722 
723  btVector3 vertex;
724  int vi = shape0->getVertexCount();
725  while(vi--)
726  {
727  shape0->getVertex(vi,vertex);
728  vertex = orgtrans0(vertex);
729 
730  btScalar distance = vertex.dot(plane) - plane[3] - margin;
731 
732  if(distance<0.0)//add contact
733  {
734  if(swapped)
735  {
736  addContactPoint(body1Wrap, body0Wrap,
737  vertex,
738  -plane,
739  distance);
740  }
741  else
742  {
743  addContactPoint(body0Wrap, body1Wrap,
744  vertex,
745  plane,
746  distance);
747  }
748  }
749  }
750 
751  shape0->unlockChildShapes();
752 }
753 
754 
755 
756 
758 {
759 public:
764  bool swapped;
766 
767  virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
768  {
769  btTriangleShapeEx tri1(triangle[0],triangle[1],triangle[2]);
770  tri1.setMargin(margin);
771  if(swapped)
772  {
773  algorithm->setPart0(partId);
774  algorithm->setFace0(triangleIndex);
775  }
776  else
777  {
778  algorithm->setPart1(partId);
779  algorithm->setFace1(triangleIndex);
780  }
783  }
784 };
785 
786 
787 
788 
790  const btCollisionObjectWrapper* body0Wrap,
791  const btCollisionObjectWrapper * body1Wrap,
792  const btGImpactShapeInterface * shape0,
793  const btConcaveShape * shape1,bool swapped)
794 {
795  //create the callback
796  btGImpactTriangleCallback tricallback;
797  tricallback.algorithm = this;
798  tricallback.body0Wrap = body0Wrap;
799  tricallback.body1Wrap = body1Wrap;
800  tricallback.gimpactshape0 = shape0;
801  tricallback.swapped = swapped;
802  tricallback.margin = shape1->getMargin();
803 
804  //getting the trimesh AABB
805  btTransform gimpactInConcaveSpace;
806 
807  gimpactInConcaveSpace = body1Wrap->getWorldTransform().inverse() * body0Wrap->getWorldTransform();
808 
809  btVector3 minAABB,maxAABB;
810  shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB);
811 
812  shape1->processAllTriangles(&tricallback,minAABB,maxAABB);
813 
814 }
815 
816 
817 
819 {
820  clearCache();
821 
822  m_resultOut = resultOut;
823  m_dispatchInfo = &dispatchInfo;
824  const btGImpactShapeInterface * gimpactshape0;
825  const btGImpactShapeInterface * gimpactshape1;
826 
828  {
829  gimpactshape0 = static_cast<const btGImpactShapeInterface *>(body0Wrap->getCollisionShape());
830 
832  {
833  gimpactshape1 = static_cast<const btGImpactShapeInterface *>(body1Wrap->getCollisionShape());
834 
835  gimpact_vs_gimpact(body0Wrap,body1Wrap,gimpactshape0,gimpactshape1);
836  }
837  else
838  {
839  gimpact_vs_shape(body0Wrap,body1Wrap,gimpactshape0,body1Wrap->getCollisionShape(),false);
840  }
841 
842  }
843  else if (body1Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
844  {
845  gimpactshape1 = static_cast<const btGImpactShapeInterface *>(body1Wrap->getCollisionShape());
846 
847  gimpact_vs_shape(body1Wrap,body0Wrap,gimpactshape1,body0Wrap->getCollisionShape(),true);
848  }
849 }
850 
851 
853 {
854  return 1.f;
855 
856 }
857 
859 
860 
861 
864 {
865 
866  static btGImpactCollisionAlgorithm::CreateFunc s_gimpact_cf;
867 
868  int i;
869 
870  for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
871  {
872  dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,i ,&s_gimpact_cf);
873  }
874 
875  for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
876  {
877  dispatcher->registerCollisionCreateFunc(i,GIMPACT_SHAPE_PROXYTYPE ,&s_gimpact_cf);
878  }
879 
880 }