Bullet Collision Detection & Physics Library
btCompoundCompoundCollisionAlgorithm.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 
15 */
16 
18 #include "LinearMath/btQuickprof.h"
23 #include "LinearMath/btAabbUtil2.h"
26 
27 //USE_LOCAL_STACK will avoid most (often all) dynamic memory allocations due to resizing in processCollision and MycollideTT
28 #define USE_LOCAL_STACK 1
29 
31 
33 :btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,isSwapped)
34 {
35 
36  void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache),16);
38 
39  const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
40  btAssert (col0ObjWrap->getCollisionShape()->isCompound());
41 
42  const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
43  btAssert (col1ObjWrap->getCollisionShape()->isCompound());
44 
45  const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
46  m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
47 
48  const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
49  m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
50 
51 
52 }
53 
54 
56 {
60 }
61 
63 {
64  int i;
66  for (i=0;i<pairs.size();i++)
67  {
68  if (pairs[i].m_userPointer)
69  {
70 
71  ((btCollisionAlgorithm*)pairs[i].m_userPointer)->getAllContactManifolds(manifoldArray);
72  }
73  }
74 }
75 
76 
78 {
80 
81  int numChildren = pairs.size();
82  int i;
83  for (i=0;i<numChildren;i++)
84  {
85  if (pairs[i].m_userPointer)
86  {
87  btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer;
88  algo->~btCollisionAlgorithm();
90  }
91  }
93 }
94 
96 {
98 
99 
105 
106 
108 
110 
112  const btCollisionObjectWrapper* compound0ObjWrap,
113  btDispatcher* dispatcher,
114  const btDispatcherInfo& dispatchInfo,
115  btManifoldResult* resultOut,
116  btHashedSimplePairCache* childAlgorithmsCache,
117  btPersistentManifold* sharedManifold)
118  :m_numOverlapPairs(0),m_compound0ColObjWrap(compound1ObjWrap),m_compound1ColObjWrap(compound0ObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
119  m_childCollisionAlgorithmCache(childAlgorithmsCache),
120  m_sharedManifold(sharedManifold)
121  {
122 
123  }
124 
125 
126 
127 
128  void Process(const btDbvtNode* leaf0,const btDbvtNode* leaf1)
129  {
130  BT_PROFILE("btCompoundCompoundLeafCallback::Process");
131  m_numOverlapPairs++;
132 
133 
134  int childIndex0 = leaf0->dataAsInt;
135  int childIndex1 = leaf1->dataAsInt;
136 
137 
138  btAssert(childIndex0>=0);
139  btAssert(childIndex1>=0);
140 
141 
142  const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(m_compound0ColObjWrap->getCollisionShape());
143  btAssert(childIndex0<compoundShape0->getNumChildShapes());
144 
145  const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(m_compound1ColObjWrap->getCollisionShape());
146  btAssert(childIndex1<compoundShape1->getNumChildShapes());
147 
148  const btCollisionShape* childShape0 = compoundShape0->getChildShape(childIndex0);
149  const btCollisionShape* childShape1 = compoundShape1->getChildShape(childIndex1);
150 
151  //backup
152  btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform();
153  const btTransform& childTrans0 = compoundShape0->getChildTransform(childIndex0);
154  btTransform newChildWorldTrans0 = orgTrans0*childTrans0 ;
155 
156  btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform();
157  const btTransform& childTrans1 = compoundShape1->getChildTransform(childIndex1);
158  btTransform newChildWorldTrans1 = orgTrans1*childTrans1 ;
159 
160 
161  //perform an AABB check first
162  btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
163  childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0);
164  childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1);
165 
167 
168  aabbMin0 -= thresholdVec;
169  aabbMax0 += thresholdVec;
170 
172  {
173  if (!gCompoundCompoundChildShapePairCallback(childShape0,childShape1))
174  return;
175  }
176 
177  if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
178  {
179  btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap,childShape0, m_compound0ColObjWrap->getCollisionObject(),newChildWorldTrans0,-1,childIndex0);
180  btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap,childShape1,m_compound1ColObjWrap->getCollisionObject(),newChildWorldTrans1,-1,childIndex1);
181 
182 
183  btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0,childIndex1);
184  bool removePair = false;
185  btCollisionAlgorithm* colAlgo = 0;
186  if (m_resultOut->m_closestPointDistanceThreshold > 0)
187  {
188  colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, 0, BT_CLOSEST_POINT_ALGORITHMS);
189  removePair = true;
190  }
191  else
192  {
193  if (pair)
194  {
195  colAlgo = (btCollisionAlgorithm*)pair->m_userPointer;
196 
197  }
198  else
199  {
200  colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
201  pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0, childIndex1);
202  btAssert(pair);
203  pair->m_userPointer = colAlgo;
204  }
205  }
206 
207  btAssert(colAlgo);
208 
209  const btCollisionObjectWrapper* tmpWrap0 = 0;
210  const btCollisionObjectWrapper* tmpWrap1 = 0;
211 
212  tmpWrap0 = m_resultOut->getBody0Wrap();
213  tmpWrap1 = m_resultOut->getBody1Wrap();
214 
215  m_resultOut->setBody0Wrap(&compoundWrap0);
216  m_resultOut->setBody1Wrap(&compoundWrap1);
217 
218  m_resultOut->setShapeIdentifiersA(-1,childIndex0);
219  m_resultOut->setShapeIdentifiersB(-1,childIndex1);
220 
221 
222  colAlgo->processCollision(&compoundWrap0,&compoundWrap1,m_dispatchInfo,m_resultOut);
223 
224  m_resultOut->setBody0Wrap(tmpWrap0);
225  m_resultOut->setBody1Wrap(tmpWrap1);
226 
227  if (removePair)
228  {
229  colAlgo->~btCollisionAlgorithm();
230  m_dispatcher->freeCollisionAlgorithm(colAlgo);
231  }
232 
233  }
234  }
235 };
236 
237 
238 static DBVT_INLINE bool MyIntersect( const btDbvtAabbMm& a,
239  const btDbvtAabbMm& b, const btTransform& xform, btScalar distanceThreshold)
240 {
241  btVector3 newmin,newmax;
242  btTransformAabb(b.Mins(),b.Maxs(),0.f,xform,newmin,newmax);
243  newmin -= btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
244  newmax += btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
245  btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin,newmax);
246  return Intersect(a,newb);
247 }
248 
249 
250 static inline void MycollideTT( const btDbvtNode* root0,
251  const btDbvtNode* root1,
252  const btTransform& xform,
253  btCompoundCompoundLeafCallback* callback, btScalar distanceThreshold)
254 {
255 
256  if(root0&&root1)
257  {
258  int depth=1;
259  int treshold=btDbvt::DOUBLE_STACKSIZE-4;
261 #ifdef USE_LOCAL_STACK
263  stkStack.initializeFromBuffer(&localStack,btDbvt::DOUBLE_STACKSIZE,btDbvt::DOUBLE_STACKSIZE);
264 #else
265  stkStack.resize(btDbvt::DOUBLE_STACKSIZE);
266 #endif
267  stkStack[0]=btDbvt::sStkNN(root0,root1);
268  do {
269  btDbvt::sStkNN p=stkStack[--depth];
270  if(MyIntersect(p.a->volume,p.b->volume,xform, distanceThreshold))
271  {
272  if(depth>treshold)
273  {
274  stkStack.resize(stkStack.size()*2);
275  treshold=stkStack.size()-4;
276  }
277  if(p.a->isinternal())
278  {
279  if(p.b->isinternal())
280  {
281  stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[0]);
282  stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[0]);
283  stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[1]);
284  stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[1]);
285  }
286  else
287  {
288  stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b);
289  stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b);
290  }
291  }
292  else
293  {
294  if(p.b->isinternal())
295  {
296  stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[0]);
297  stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[1]);
298  }
299  else
300  {
301  callback->Process(p.a,p.b);
302  }
303  }
304  }
305  } while(depth);
306  }
307 }
308 
310 {
311 
312  const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
313  const btCollisionObjectWrapper* col1ObjWrap= body1Wrap;
314 
315  btAssert (col0ObjWrap->getCollisionShape()->isCompound());
316  btAssert (col1ObjWrap->getCollisionShape()->isCompound());
317  const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
318  const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
319 
320  const btDbvt* tree0 = compoundShape0->getDynamicAabbTree();
321  const btDbvt* tree1 = compoundShape1->getDynamicAabbTree();
322  if (!tree0 || !tree1)
323  {
324  return btCompoundCollisionAlgorithm::processCollision(body0Wrap,body1Wrap,dispatchInfo,resultOut);
325  }
328  if ((compoundShape0->getUpdateRevision() != m_compoundShapeRevision0) || (compoundShape1->getUpdateRevision() != m_compoundShapeRevision1))
329  {
332  m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
333  m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
334 
335  }
336 
337 
341  {
342  int i;
344 #ifdef USE_LOCAL_STACK
345  btPersistentManifold localManifolds[4];
346  manifoldArray.initializeFromBuffer(&localManifolds,0,4);
347 #endif
349  for (i=0;i<pairs.size();i++)
350  {
351  if (pairs[i].m_userPointer)
352  {
353  btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer;
354  algo->getAllContactManifolds(manifoldArray);
355  for (int m=0;m<manifoldArray.size();m++)
356  {
357  if (manifoldArray[m]->getNumContacts())
358  {
359  resultOut->setPersistentManifold(manifoldArray[m]);
360  resultOut->refreshContactPoints();
361  resultOut->setPersistentManifold(0);
362  }
363  }
364  manifoldArray.resize(0);
365  }
366  }
367  }
368 
369 
370 
371 
372  btCompoundCompoundLeafCallback callback(col0ObjWrap,col1ObjWrap,this->m_dispatcher,dispatchInfo,resultOut,this->m_childCollisionAlgorithmCache,m_sharedManifold);
373 
374 
375  const btTransform xform=col0ObjWrap->getWorldTransform().inverse()*col1ObjWrap->getWorldTransform();
376  MycollideTT(tree0->m_root,tree1->m_root,xform,&callback, resultOut->m_closestPointDistanceThreshold);
377 
378  //printf("#compound-compound child/leaf overlap =%d \r",callback.m_numOverlapPairs);
379 
380  //remove non-overlapping child pairs
381 
382  {
384 
385  //iterate over all children, perform an AABB check inside ProcessChildShape
387 
388  int i;
390 
391 
392 
393 
394 
395  btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
396 
397  for (i=0;i<pairs.size();i++)
398  {
399  if (pairs[i].m_userPointer)
400  {
401  btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
402 
403  {
404  const btCollisionShape* childShape0 = 0;
405 
406  btTransform newChildWorldTrans0;
407  childShape0 = compoundShape0->getChildShape(pairs[i].m_indexA);
408  const btTransform& childTrans0 = compoundShape0->getChildTransform(pairs[i].m_indexA);
409  newChildWorldTrans0 = col0ObjWrap->getWorldTransform()*childTrans0 ;
410  childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0);
411  }
413  aabbMin0 -= thresholdVec;
414  aabbMax0 += thresholdVec;
415  {
416  const btCollisionShape* childShape1 = 0;
417  btTransform newChildWorldTrans1;
418 
419  childShape1 = compoundShape1->getChildShape(pairs[i].m_indexB);
420  const btTransform& childTrans1 = compoundShape1->getChildTransform(pairs[i].m_indexB);
421  newChildWorldTrans1 = col1ObjWrap->getWorldTransform()*childTrans1 ;
422  childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1);
423  }
424 
425  aabbMin1 -= thresholdVec;
426  aabbMax1 += thresholdVec;
427 
428  if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
429  {
430  algo->~btCollisionAlgorithm();
432  m_removePairs.push_back(btSimplePair(pairs[i].m_indexA,pairs[i].m_indexB));
433  }
434  }
435  }
436  for (int i=0;i<m_removePairs.size();i++)
437  {
439  }
441  }
442 
443 }
444 
446 {
447  btAssert(0);
448  return 0.f;
449 
450 }
451 
452 
453 
void Process(const btDbvtNode *leaf0, const btDbvtNode *leaf1)
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
void push_back(const T &_Val)
btScalar calculateTimeOfImpact(btCollisionObject *body0, btCollisionObject *body1, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)
virtual void getAllContactManifolds(btManifoldArray &manifoldArray)
virtual btSimplePair * addOverlappingPair(int indexA, int indexB)
virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)=0
class btPersistentManifold * m_sharedManifold
int getUpdateRevision() const
virtual btCollisionAlgorithm * findAlgorithm(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, btPersistentManifold *sharedManifold, ebtDispatcherQueryType queryType)=0
btCompoundCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo &ci, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, bool isSwapped)
void setPersistentManifold(btPersistentManifold *manifoldPtr)
const btCollisionObjectWrapper * m_compound0ColObjWrap
#define btAssert(x)
Definition: btScalar.h:131
The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes ...
Definition: btDbvt.h:198
The btCollisionShape class provides an interface for collision shapes that can be shared among btColl...
const btDbvtNode * b
Definition: btDbvt.h:204
btDbvtNode * m_root
Definition: btDbvt.h:262
btManifoldResult is a helper class to manage contact results.
const btCollisionObjectWrapper * getBody1Wrap() const
const btDbvt * getDynamicAabbTree() const
btCompoundCompoundLeafCallback(const btCollisionObjectWrapper *compound1ObjWrap, const btCollisionObjectWrapper *compound0ObjWrap, btDispatcher *dispatcher, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut, btHashedSimplePairCache *childAlgorithmsCache, btPersistentManifold *sharedManifold)
bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1, const btVector3 &aabbMin2, const btVector3 &aabbMax2)
conservative test for overlap between two aabbs
Definition: btAabbUtil2.h:48
btSimplePairArray & getOverlappingPairArray()
DBVT_INLINE bool isinternal() const
Definition: btDbvt.h:183
virtual void getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const =0
getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t...
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
virtual void setShapeIdentifiersA(int partId0, int index0)
setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material comb...
virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)
virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)
btScalar m_closestPointDistanceThreshold
int size() const
return the number of elements in the array
btDbvtNode * childs[2]
Definition: btDbvt.h:186
const btCollisionObjectWrapper * getBody0Wrap() const
btTransform & getChildTransform(int index)
static btDbvtAabbMm FromMM(const btVector3 &mi, const btVector3 &mx)
Definition: btDbvt.h:425
const btDbvtNode * a
Definition: btDbvt.h:203
class btHashedSimplePairCache * m_childCollisionAlgorithmCache
const btTransform & getWorldTransform() const
#define btAlignedFree(ptr)
btCollisionObject can be used to manage collision detection objects.
void initializeFromBuffer(void *buffer, int size, int capacity)
bool(* btShapePairCallback)(const btCollisionShape *pShape0, const btCollisionShape *pShape1)
static DBVT_INLINE bool MyIntersect(const btDbvtAabbMm &a, const btDbvtAabbMm &b, const btTransform &xform, btScalar distanceThreshold)
virtual void freeCollisionAlgorithm(void *ptr)=0
btTransform inverse() const
Return the inverse of this transform.
Definition: btTransform.h:188
virtual void setShapeIdentifiersB(int partId1, int index1)
const btCollisionShape * getCollisionShape() const
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
#define ATTRIBUTE_ALIGNED16(a)
Definition: btScalar.h:82
virtual void getAllContactManifolds(btManifoldArray &manifoldArray)=0
DBVT_INLINE const btVector3 & Maxs() const
Definition: btDbvt.h:137
#define BT_PROFILE(name)
Definition: btQuickprof.h:216
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
static void MycollideTT(const btDbvtNode *root0, const btDbvtNode *root1, const btTransform &xform, btCompoundCompoundLeafCallback *callback, btScalar distanceThreshold)
bool isCompound() const
void resize(int newsize, const T &fillData=T())
btDbvtVolume volume
Definition: btDbvt.h:180
void setBody1Wrap(const btCollisionObjectWrapper *obj1Wrap)
btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision s...
btSimplePair * findPair(int indexA, int indexB)
const btCollisionObjectWrapper * m_compound1ColObjWrap
int dataAsInt
Definition: btDbvt.h:188
#define DBVT_INLINE
Definition: btDbvt.h:55
DBVT_INLINE bool Intersect(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
Definition: btDbvt.h:534
#define btAlignedAlloc(size, alignment)
void btTransformAabb(const btVector3 &halfExtents, btScalar margin, const btTransform &t, btVector3 &aabbMinOut, btVector3 &aabbMaxOut)
Definition: btAabbUtil2.h:182
The btCompoundShape allows to store multiple other btCollisionShapes This allows for moving concave c...
void setBody0Wrap(const btCollisionObjectWrapper *obj0Wrap)
DBVT_INLINE const btVector3 & Mins() const
Definition: btDbvt.h:136
btCollisionShape * getChildShape(int index)
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:77
btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatche...
virtual void * removeOverlappingPair(int indexA, int indexB)
class btHashedSimplePairCache * m_childCollisionAlgorithmCache
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
btShapePairCallback gCompoundCompoundChildShapePairCallback
const btCollisionObject * getCollisionObject() const