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
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;
146 
148  {
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 
161  {
163  }
164  else
165  {
166  //the contactpoint is still projected back using the original inverted worldtrans
167  if (!m_childCollisionAlgorithms[index])
168  {
170  }
171  algo = m_childCollisionAlgorithms[index];
172  }
173 
174  const btCollisionObjectWrapper* tmpWrap = 0;
175 
178  {
179  tmpWrap = m_resultOut->getBody0Wrap();
180  m_resultOut->setBody0Wrap(&compoundWrap);
182  } else
183  {
184  tmpWrap = m_resultOut->getBody1Wrap();
185  m_resultOut->setBody1Wrap(&compoundWrap);
187  }
188 
189  algo->processCollision(&compoundWrap,m_otherObjWrap,m_dispatchInfo,m_resultOut);
190 
191 #if 0
193  {
194  btVector3 worldAabbMin,worldAabbMax;
195  m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
196  m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
197  }
198 #endif
199 
201  {
202  m_resultOut->setBody0Wrap(tmpWrap);
203  } else
204  {
205  m_resultOut->setBody1Wrap(tmpWrap);
206  }
207 
208  }
209  }
210  void Process(const btDbvtNode* leaf)
211  {
212  int index = leaf->dataAsInt;
213 
214  const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
215  const btCollisionShape* childShape = compoundShape->getChildShape(index);
216 
217 #if 0
219  {
220  btVector3 worldAabbMin,worldAabbMax;
222  btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
223  m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
224  }
225 #endif
226 
227  ProcessChildShape(childShape,index);
228 
229  }
230 };
231 
232 
233 
234 
235 
236 
238 {
239  const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
240  const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
241 
242  btAssert (colObjWrap->getCollisionShape()->isCompound());
243  const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
244 
247  if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
248  {
251 
252  preallocateChildAlgorithms(body0Wrap,body1Wrap);
253  m_compoundShapeRevision = compoundShape->getUpdateRevision();
254  }
255 
257  return;
258 
259  const btDbvt* tree = compoundShape->getDynamicAabbTree();
260  //use a dynamic aabb tree to cull potential child-overlaps
261  btCompoundLeafCallback callback(colObjWrap,otherObjWrap,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
262 
266  {
267  int i;
269  for (i=0;i<m_childCollisionAlgorithms.size();i++)
270  {
272  {
273  m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
274  for (int m=0;m<manifoldArray.size();m++)
275  {
276  if (manifoldArray[m]->getNumContacts())
277  {
278  resultOut->setPersistentManifold(manifoldArray[m]);
279  resultOut->refreshContactPoints();
280  resultOut->setPersistentManifold(0);//??necessary?
281  }
282  }
284  }
285  }
286  }
287 
288  if (tree)
289  {
290 
291  btVector3 localAabbMin,localAabbMax;
292  btTransform otherInCompoundSpace;
293  otherInCompoundSpace = colObjWrap->getWorldTransform().inverse() * otherObjWrap->getWorldTransform();
294  otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
296  localAabbMin -= extraExtends;
297  localAabbMax += extraExtends;
298 
299  const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
300  //process all children, that overlap with the given AABB bounds
301  tree->collideTVNoStackAlloc(tree->m_root,bounds,stack2,callback);
302 
303  } else
304  {
305  //iterate over all children, perform an AABB check inside ProcessChildShape
306  int numChildren = m_childCollisionAlgorithms.size();
307  int i;
308  for (i=0;i<numChildren;i++)
309  {
310  callback.ProcessChildShape(compoundShape->getChildShape(i),i);
311  }
312  }
313 
314  {
315  //iterate over all children, perform an AABB check inside ProcessChildShape
316  int numChildren = m_childCollisionAlgorithms.size();
317  int i;
319  const btCollisionShape* childShape = 0;
320  btTransform orgTrans;
321 
322  btTransform newChildWorldTrans;
323  btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
324 
325  for (i=0;i<numChildren;i++)
326  {
328  {
329  childShape = compoundShape->getChildShape(i);
330  //if not longer overlapping, remove the algorithm
331  orgTrans = colObjWrap->getWorldTransform();
332 
333  const btTransform& childTrans = compoundShape->getChildTransform(i);
334  newChildWorldTrans = orgTrans*childTrans ;
335 
336  //perform an AABB check first
337  childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
338  otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
339 
340  if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
341  {
342  m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
345  }
346  }
347  }
348  }
349 }
350 
352 {
353  btAssert(0);
354  //needs to be fixed, using btCollisionObjectWrapper and NOT modifying internal data structures
355  btCollisionObject* colObj = m_isSwapped? body1 : body0;
356  btCollisionObject* otherObj = m_isSwapped? body0 : body1;
357 
358  btAssert (colObj->getCollisionShape()->isCompound());
359 
360  btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
361 
362  //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
363  //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
364  //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
365  //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
366  //then use each overlapping node AABB against Tree0
367  //and vise versa.
368 
369  btScalar hitFraction = btScalar(1.);
370 
371  int numChildren = m_childCollisionAlgorithms.size();
372  int i;
373  btTransform orgTrans;
374  btScalar frac;
375  for (i=0;i<numChildren;i++)
376  {
377  //btCollisionShape* childShape = compoundShape->getChildShape(i);
378 
379  //backup
380  orgTrans = colObj->getWorldTransform();
381 
382  const btTransform& childTrans = compoundShape->getChildTransform(i);
383  //btTransform newChildWorldTrans = orgTrans*childTrans ;
384  colObj->setWorldTransform( orgTrans*childTrans );
385 
386  //btCollisionShape* tmpShape = colObj->getCollisionShape();
387  //colObj->internalSetTemporaryCollisionShape( childShape );
388  frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
389  if (frac<hitFraction)
390  {
391  hitFraction = frac;
392  }
393  //revert back
394  //colObj->internalSetTemporaryCollisionShape( tmpShape);
395  colObj->setWorldTransform( orgTrans);
396  }
397  return hitFraction;
398 
399 }
400 
401 
402 
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
DBVT_INLINE const btVector3 & Mins() const
Definition: btDbvt.h:136
const btCollisionObjectWrapper * getBody0Wrap() const
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:58
const btCollisionShape * getCollisionShape() 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
int getNumChildShapes() const
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...
DBVT_INLINE const btVector3 & Maxs() const
Definition: btDbvt.h:137
btAlignedObjectArray< btCollisionAlgorithm * > m_childCollisionAlgorithms
virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)
bool isCompound() const
btPersistentManifold * m_sharedManifold
btTransform & getWorldTransform()
btScalar m_closestPointDistanceThreshold
const btCollisionObjectWrapper * m_compoundColObjWrap
btTransform & getChildTransform(int index)
static btDbvtAabbMm FromMM(const btVector3 &mi, const btVector3 &mx)
Definition: btDbvt.h:425
const btCollisionObject * getCollisionObject() const
btCollisionObject can be used to manage collision detection objects.
bool(* btShapePairCallback)(const btCollisionShape *pShape0, const btCollisionShape *pShape1)
virtual void drawAabb(const btVector3 &from, const btVector3 &to, const btVector3 &color)
Definition: btIDebugDraw.h:137
virtual void freeCollisionAlgorithm(void *ptr)=0
virtual void setShapeIdentifiersB(int partId1, int index1)
void setWorldTransform(const btTransform &worldTrans)
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
#define ATTRIBUTE_ALIGNED16(a)
Definition: btScalar.h:82
int size() const
return the number of elements in the array
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
void Process(const btDbvtNode *leaf)
const btCollisionObject * getBody0Internal() 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)
const btTransform & getWorldTransform() const
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
const btCollisionObjectWrapper * getBody1Wrap() const
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_PREFIX void collideTVNoStackAlloc(const btDbvtNode *root, const btDbvtVolume &volume, btNodeStack &stack, DBVT_IPOLICY) const
Definition: btDbvt.h:974
btCollisionShape * getChildShape(int index)
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:75
btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatche...
btTransform inverse() const
Return the inverse of this transform.
Definition: btTransform.h:188
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 btCollisionShape * getCollisionShape() const