Bullet Collision Detection & Physics Library
btCompoundCollisionAlgorithm.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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 
22 #include "LinearMath/btAabbUtil2.h"
23 #include "btManifoldResult.h"
25 
27 
29 :btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
30 m_isSwapped(isSwapped),
31 m_sharedManifold(ci.m_manifold)
32 {
33  m_ownsManifold = false;
34 
35  const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
36  btAssert (colObjWrap->getCollisionShape()->isCompound());
37 
38  const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
39  m_compoundShapeRevision = compoundShape->getUpdateRevision();
40 
41 
42  preallocateChildAlgorithms(body0Wrap,body1Wrap);
43 }
44 
46 {
47  const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
48  const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
49  btAssert (colObjWrap->getCollisionShape()->isCompound());
50 
51  const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
52 
53  int numChildren = compoundShape->getNumChildShapes();
54  int i;
55 
57  for (i=0;i<numChildren;i++)
58  {
59  if (compoundShape->getDynamicAabbTree())
60  {
62  } else
63  {
64 
65  const btCollisionShape* childShape = compoundShape->getChildShape(i);
66 
67  btCollisionObjectWrapper childWrap(colObjWrap,childShape,colObjWrap->getCollisionObject(),colObjWrap->getWorldTransform(),-1,i);//wrong child trans, but unused (hopefully)
69 
70 
71  btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsContact;
72  btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsClosestPoints;
73 
74 
75  }
76  }
77 }
78 
80 {
81  int numChildren = m_childCollisionAlgorithms.size();
82  int i;
83  for (i=0;i<numChildren;i++)
84  {
86  {
87  m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
89  }
90  }
91 }
92 
94 {
96 }
97 
98 
99 
100 
102 {
103 
104 public:
105 
113 
114  btCompoundLeafCallback (const btCollisionObjectWrapper* compoundObjWrap,const btCollisionObjectWrapper* otherObjWrap,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold)
115  :m_compoundColObjWrap(compoundObjWrap),m_otherObjWrap(otherObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
116  m_childCollisionAlgorithms(childCollisionAlgorithms),
117  m_sharedManifold(sharedManifold)
118  {
119 
120  }
121 
122 
123  void ProcessChildShape(const btCollisionShape* childShape,int index)
124  {
125  btAssert(index>=0);
126  const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
127  btAssert(index<compoundShape->getNumChildShapes());
128 
129 
130  //backup
131  btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
132 
133  const btTransform& childTrans = compoundShape->getChildTransform(index);
134  btTransform newChildWorldTrans = orgTrans*childTrans ;
135 
136  //perform an AABB check first
137  btVector3 aabbMin0,aabbMax0;
138  childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
139 
141  aabbMin0 -= extendAabb;
142  aabbMax0 += extendAabb;
143 
144  btVector3 aabbMin1, aabbMax1;
145  m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
146 
148  {
149  if (!gCompoundChildShapePairCallback(m_otherObjWrap->getCollisionShape(), childShape))
150  return;
151  }
152 
153  if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
154  {
155 
156  btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap,childShape,m_compoundColObjWrap->getCollisionObject(),newChildWorldTrans,-1,index);
157 
158  btCollisionAlgorithm* algo = 0;
159  bool allocatedAlgorithm = false;
160 
161  if (m_resultOut->m_closestPointDistanceThreshold > 0)
162  {
163  algo = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
164  allocatedAlgorithm = true;
165  }
166  else
167  {
168  //the contactpoint is still projected back using the original inverted worldtrans
169  if (!m_childCollisionAlgorithms[index])
170  {
171  m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
172  }
173  algo = m_childCollisionAlgorithms[index];
174  }
175 
176  const btCollisionObjectWrapper* tmpWrap = 0;
177 
179  if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
180  {
181  tmpWrap = m_resultOut->getBody0Wrap();
182  m_resultOut->setBody0Wrap(&compoundWrap);
183  m_resultOut->setShapeIdentifiersA(-1,index);
184  } else
185  {
186  tmpWrap = m_resultOut->getBody1Wrap();
187  m_resultOut->setBody1Wrap(&compoundWrap);
188  m_resultOut->setShapeIdentifiersB(-1,index);
189  }
190 
191  algo->processCollision(&compoundWrap,m_otherObjWrap,m_dispatchInfo,m_resultOut);
192 
193 #if 0
194  if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
195  {
196  btVector3 worldAabbMin,worldAabbMax;
197  m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
198  m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
199  }
200 #endif
201 
202  if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
203  {
204  m_resultOut->setBody0Wrap(tmpWrap);
205  } else
206  {
207  m_resultOut->setBody1Wrap(tmpWrap);
208  }
209  if(allocatedAlgorithm)
210  {
211  algo->~btCollisionAlgorithm();
212  m_dispatcher->freeCollisionAlgorithm(algo);
213  }
214  }
215  }
216  void Process(const btDbvtNode* leaf)
217  {
218  int index = leaf->dataAsInt;
219 
220  const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
221  const btCollisionShape* childShape = compoundShape->getChildShape(index);
222 
223 #if 0
224  if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
225  {
226  btVector3 worldAabbMin,worldAabbMax;
227  btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
228  btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
229  m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
230  }
231 #endif
232 
233  ProcessChildShape(childShape,index);
234 
235  }
236 };
237 
238 
239 
240 
241 
242 
244 {
245  const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
246  const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
247 
248  btAssert (colObjWrap->getCollisionShape()->isCompound());
249  const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
250 
253  if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
254  {
257 
258  preallocateChildAlgorithms(body0Wrap,body1Wrap);
259  m_compoundShapeRevision = compoundShape->getUpdateRevision();
260  }
261 
263  return;
264 
265  const btDbvt* tree = compoundShape->getDynamicAabbTree();
266  //use a dynamic aabb tree to cull potential child-overlaps
267  btCompoundLeafCallback callback(colObjWrap,otherObjWrap,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
268 
272  {
273  int i;
275  for (i=0;i<m_childCollisionAlgorithms.size();i++)
276  {
278  {
279  m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
280  for (int m=0;m<manifoldArray.size();m++)
281  {
282  if (manifoldArray[m]->getNumContacts())
283  {
284  resultOut->setPersistentManifold(manifoldArray[m]);
285  resultOut->refreshContactPoints();
286  resultOut->setPersistentManifold(0);//??necessary?
287  }
288  }
290  }
291  }
292  }
293 
294  if (tree)
295  {
296 
297  btVector3 localAabbMin,localAabbMax;
298  btTransform otherInCompoundSpace;
299  otherInCompoundSpace = colObjWrap->getWorldTransform().inverse() * otherObjWrap->getWorldTransform();
300  otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
302  localAabbMin -= extraExtends;
303  localAabbMax += extraExtends;
304 
305  const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
306  //process all children, that overlap with the given AABB bounds
307  tree->collideTVNoStackAlloc(tree->m_root,bounds,stack2,callback);
308 
309  } else
310  {
311  //iterate over all children, perform an AABB check inside ProcessChildShape
312  int numChildren = m_childCollisionAlgorithms.size();
313  int i;
314  for (i=0;i<numChildren;i++)
315  {
316  callback.ProcessChildShape(compoundShape->getChildShape(i),i);
317  }
318  }
319 
320  {
321  //iterate over all children, perform an AABB check inside ProcessChildShape
322  int numChildren = m_childCollisionAlgorithms.size();
323  int i;
325  const btCollisionShape* childShape = 0;
326  btTransform orgTrans;
327 
328  btTransform newChildWorldTrans;
329  btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
330 
331  for (i=0;i<numChildren;i++)
332  {
334  {
335  childShape = compoundShape->getChildShape(i);
336  //if not longer overlapping, remove the algorithm
337  orgTrans = colObjWrap->getWorldTransform();
338 
339  const btTransform& childTrans = compoundShape->getChildTransform(i);
340  newChildWorldTrans = orgTrans*childTrans ;
341 
342  //perform an AABB check first
343  childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
344  otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
345 
346  if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
347  {
348  m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
351  }
352  }
353  }
354  }
355 }
356 
358 {
359  btAssert(0);
360  //needs to be fixed, using btCollisionObjectWrapper and NOT modifying internal data structures
361  btCollisionObject* colObj = m_isSwapped? body1 : body0;
362  btCollisionObject* otherObj = m_isSwapped? body0 : body1;
363 
364  btAssert (colObj->getCollisionShape()->isCompound());
365 
366  btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
367 
368  //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
369  //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
370  //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
371  //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
372  //then use each overlapping node AABB against Tree0
373  //and vise versa.
374 
375  btScalar hitFraction = btScalar(1.);
376 
377  int numChildren = m_childCollisionAlgorithms.size();
378  int i;
379  btTransform orgTrans;
380  btScalar frac;
381  for (i=0;i<numChildren;i++)
382  {
383  //btCollisionShape* childShape = compoundShape->getChildShape(i);
384 
385  //backup
386  orgTrans = colObj->getWorldTransform();
387 
388  const btTransform& childTrans = compoundShape->getChildTransform(i);
389  //btTransform newChildWorldTrans = orgTrans*childTrans ;
390  colObj->setWorldTransform( orgTrans*childTrans );
391 
392  //btCollisionShape* tmpShape = colObj->getCollisionShape();
393  //colObj->internalSetTemporaryCollisionShape( childShape );
394  frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
395  if (frac<hitFraction)
396  {
397  hitFraction = frac;
398  }
399  //revert back
400  //colObj->internalSetTemporaryCollisionShape( tmpShape);
401  colObj->setWorldTransform( orgTrans);
402  }
403  return hitFraction;
404 
405 }
406 
407 
408 
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
class btPersistentManifold * m_sharedManifold
virtual btCollisionAlgorithm * findAlgorithm(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, btPersistentManifold *sharedManifold, ebtDispatcherQueryType queryType)=0
void setPersistentManifold(btPersistentManifold *manifoldPtr)
btCompoundLeafCallback(const btCollisionObjectWrapper *compoundObjWrap, const btCollisionObjectWrapper *otherObjWrap, btDispatcher *dispatcher, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut, btCollisionAlgorithm **childCollisionAlgorithms, btPersistentManifold *sharedManifold)
#define btAssert(x)
Definition: btScalar.h:131
This class is not enabled yet (work-in-progress) to more aggressively activate objects.
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...
btCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo &ci, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, bool isSwapped)
btDbvtNode * m_root
Definition: btDbvt.h:262
btManifoldResult is a helper class to manage contact results.
class btIDebugDraw * m_debugDraw
Definition: btDispatcher.h:59
const btCollisionObjectWrapper * getBody1Wrap() const
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
const btDispatcherInfo & m_dispatchInfo
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...
virtual void setShapeIdentifiersA(int partId0, int index0)
setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material comb...
btAlignedObjectArray< btCollisionAlgorithm * > m_childCollisionAlgorithms
virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)
btPersistentManifold * m_sharedManifold
btTransform & getWorldTransform()
btScalar m_closestPointDistanceThreshold
int size() const
return the number of elements in the array
const btCollisionObjectWrapper * m_compoundColObjWrap
const btCollisionObjectWrapper * getBody0Wrap() const
btTransform & getChildTransform(int index)
static btDbvtAabbMm FromMM(const btVector3 &mi, const btVector3 &mx)
Definition: btDbvt.h:425
const btTransform & getWorldTransform() const
btCollisionObject can be used to manage collision detection objects.
bool(* btShapePairCallback)(const btCollisionShape *pShape0, const btCollisionShape *pShape1)
DBVT_PREFIX void collideTVNoStackAlloc(const btDbvtNode *root, const btDbvtVolume &volume, btNodeStack &stack, DBVT_IPOLICY) const
Definition: btDbvt.h:974
virtual void drawAabb(const btVector3 &from, const btVector3 &to, const btVector3 &color)
Definition: btIDebugDraw.h:137
const btCollisionObject * getBody0Internal() const
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)
void setWorldTransform(const btTransform &worldTrans)
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
DBVT_INLINE const btVector3 & Maxs() const
Definition: btDbvt.h:137
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
void Process(const btDbvtNode *leaf)
bool isCompound() const
void resize(int newsize, const T &fillData=T())
btDbvtVolume volume
Definition: btDbvt.h:180
virtual int getDebugMode() const =0
void setBody1Wrap(const btCollisionObjectWrapper *obj1Wrap)
int dataAsInt
Definition: btDbvt.h:188
void preallocateChildAlgorithms(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:284
btShapePairCallback gCompoundChildShapePairCallback
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...
btCollisionAlgorithm ** m_childCollisionAlgorithms
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...
const btCollisionShape * getCollisionShape() const
btScalar calculateTimeOfImpact(btCollisionObject *body0, btCollisionObject *body1, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)
void ProcessChildShape(const btCollisionShape *childShape, int index)
const btCollisionObjectWrapper * m_otherObjWrap
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
const btCollisionObject * getCollisionObject() const
int getNumChildShapes() const