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 }
72 
74 {
75  int numChildren = m_childCollisionAlgorithms.size();
76  int i;
77  for (i=0;i<numChildren;i++)
78  {
80  {
81  m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
83  }
84  }
85 }
86 
88 {
90 }
91 
92 
93 
94 
96 {
97 
98 public:
99 
107 
108  btCompoundLeafCallback (const btCollisionObjectWrapper* compoundObjWrap,const btCollisionObjectWrapper* otherObjWrap,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold)
109  :m_compoundColObjWrap(compoundObjWrap),m_otherObjWrap(otherObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
110  m_childCollisionAlgorithms(childCollisionAlgorithms),
111  m_sharedManifold(sharedManifold)
112  {
113 
114  }
115 
116 
117  void ProcessChildShape(const btCollisionShape* childShape,int index)
118  {
119  btAssert(index>=0);
120  const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
121  btAssert(index<compoundShape->getNumChildShapes());
122 
123 
124  //backup
125  btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
126 
127  const btTransform& childTrans = compoundShape->getChildTransform(index);
128  btTransform newChildWorldTrans = orgTrans*childTrans ;
129 
130  //perform an AABB check first
131  btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
132  childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
133  m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
134 
136  {
137  if (!gCompoundChildShapePairCallback(m_otherObjWrap->getCollisionShape(), childShape))
138  return;
139  }
140 
141  if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
142  {
143 
144  btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap,childShape,m_compoundColObjWrap->getCollisionObject(),newChildWorldTrans,-1,index);
145 
146 
147  //the contactpoint is still projected back using the original inverted worldtrans
148  if (!m_childCollisionAlgorithms[index])
149  m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap,m_otherObjWrap,m_sharedManifold);
150 
151 
152  const btCollisionObjectWrapper* tmpWrap = 0;
153 
155  if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
156  {
157  tmpWrap = m_resultOut->getBody0Wrap();
158  m_resultOut->setBody0Wrap(&compoundWrap);
159  m_resultOut->setShapeIdentifiersA(-1,index);
160  } else
161  {
162  tmpWrap = m_resultOut->getBody1Wrap();
163  m_resultOut->setBody1Wrap(&compoundWrap);
164  m_resultOut->setShapeIdentifiersB(-1,index);
165  }
166 
167 
168  m_childCollisionAlgorithms[index]->processCollision(&compoundWrap,m_otherObjWrap,m_dispatchInfo,m_resultOut);
169 
170 #if 0
171  if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
172  {
173  btVector3 worldAabbMin,worldAabbMax;
174  m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
175  m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
176  }
177 #endif
178 
179  if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
180  {
181  m_resultOut->setBody0Wrap(tmpWrap);
182  } else
183  {
184  m_resultOut->setBody1Wrap(tmpWrap);
185  }
186 
187  }
188  }
189  void Process(const btDbvtNode* leaf)
190  {
191  int index = leaf->dataAsInt;
192 
193  const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
194  const btCollisionShape* childShape = compoundShape->getChildShape(index);
195 
196 #if 0
197  if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
198  {
199  btVector3 worldAabbMin,worldAabbMax;
200  btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
201  btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
202  m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
203  }
204 #endif
205 
206  ProcessChildShape(childShape,index);
207 
208  }
209 };
210 
211 
212 
213 
214 
215 
217 {
218  const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
219  const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
220 
221  btAssert (colObjWrap->getCollisionShape()->isCompound());
222  const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
223 
226  if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
227  {
230 
231  preallocateChildAlgorithms(body0Wrap,body1Wrap);
232  m_compoundShapeRevision = compoundShape->getUpdateRevision();
233  }
234 
236  return;
237 
238  const btDbvt* tree = compoundShape->getDynamicAabbTree();
239  //use a dynamic aabb tree to cull potential child-overlaps
240  btCompoundLeafCallback callback(colObjWrap,otherObjWrap,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
241 
245  {
246  int i;
247  btManifoldArray manifoldArray;
248  for (i=0;i<m_childCollisionAlgorithms.size();i++)
249  {
251  {
252  m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
253  for (int m=0;m<manifoldArray.size();m++)
254  {
255  if (manifoldArray[m]->getNumContacts())
256  {
257  resultOut->setPersistentManifold(manifoldArray[m]);
258  resultOut->refreshContactPoints();
259  resultOut->setPersistentManifold(0);//??necessary?
260  }
261  }
262  manifoldArray.resize(0);
263  }
264  }
265  }
266 
267  if (tree)
268  {
269 
270  btVector3 localAabbMin,localAabbMax;
271  btTransform otherInCompoundSpace;
272  otherInCompoundSpace = colObjWrap->getWorldTransform().inverse() * otherObjWrap->getWorldTransform();
273  otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
274 
275  const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
276  //process all children, that overlap with the given AABB bounds
277  tree->collideTV(tree->m_root,bounds,callback);
278 
279  } else
280  {
281  //iterate over all children, perform an AABB check inside ProcessChildShape
282  int numChildren = m_childCollisionAlgorithms.size();
283  int i;
284  for (i=0;i<numChildren;i++)
285  {
286  callback.ProcessChildShape(compoundShape->getChildShape(i),i);
287  }
288  }
289 
290  {
291  //iterate over all children, perform an AABB check inside ProcessChildShape
292  int numChildren = m_childCollisionAlgorithms.size();
293  int i;
294  btManifoldArray manifoldArray;
295  const btCollisionShape* childShape = 0;
296  btTransform orgTrans;
297 
298  btTransform newChildWorldTrans;
299  btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
300 
301  for (i=0;i<numChildren;i++)
302  {
304  {
305  childShape = compoundShape->getChildShape(i);
306  //if not longer overlapping, remove the algorithm
307  orgTrans = colObjWrap->getWorldTransform();
308 
309  const btTransform& childTrans = compoundShape->getChildTransform(i);
310  newChildWorldTrans = orgTrans*childTrans ;
311 
312  //perform an AABB check first
313  childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
314  otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
315 
316  if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
317  {
318  m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
321  }
322  }
323  }
324  }
325 }
326 
328 {
329  btAssert(0);
330  //needs to be fixed, using btCollisionObjectWrapper and NOT modifying internal data structures
331  btCollisionObject* colObj = m_isSwapped? body1 : body0;
332  btCollisionObject* otherObj = m_isSwapped? body0 : body1;
333 
334  btAssert (colObj->getCollisionShape()->isCompound());
335 
336  btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
337 
338  //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
339  //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
340  //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
341  //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
342  //then use each overlapping node AABB against Tree0
343  //and vise versa.
344 
345  btScalar hitFraction = btScalar(1.);
346 
347  int numChildren = m_childCollisionAlgorithms.size();
348  int i;
349  btTransform orgTrans;
350  btScalar frac;
351  for (i=0;i<numChildren;i++)
352  {
353  //btCollisionShape* childShape = compoundShape->getChildShape(i);
354 
355  //backup
356  orgTrans = colObj->getWorldTransform();
357 
358  const btTransform& childTrans = compoundShape->getChildTransform(i);
359  //btTransform newChildWorldTrans = orgTrans*childTrans ;
360  colObj->setWorldTransform( orgTrans*childTrans );
361 
362  //btCollisionShape* tmpShape = colObj->getCollisionShape();
363  //colObj->internalSetTemporaryCollisionShape( childShape );
364  frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
365  if (frac<hitFraction)
366  {
367  hitFraction = frac;
368  }
369  //revert back
370  //colObj->internalSetTemporaryCollisionShape( tmpShape);
371  colObj->setWorldTransform( orgTrans);
372  }
373  return hitFraction;
374 
375 }
376 
377 
378 
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
virtual btCollisionAlgorithm * findAlgorithm(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, btPersistentManifold *sharedManifold=0)=0
virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)=0
class btPersistentManifold * m_sharedManifold
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:113
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:194
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:258
btManifoldResult is a helper class to manage contact results.
class btIDebugDraw * m_debugDraw
Definition: btDispatcher.h:58
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()
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:411
const btTransform & getWorldTransform() 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
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:64
DBVT_INLINE const btVector3 & Maxs() const
Definition: btDbvt.h:136
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:179
virtual int getDebugMode() const =0
void setBody1Wrap(const btCollisionObjectWrapper *obj1Wrap)
int dataAsInt
Definition: btDbvt.h:187
void preallocateChildAlgorithms(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap)
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:135
btCollisionShape * getChildShape(int index)
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:69
btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatche...
const btCollisionShape * getCollisionShape() const
DBVT_PREFIX void collideTV(const btDbvtNode *root, const btDbvtVolume &volume, DBVT_IPOLICY) const
Definition: btDbvt.h:922
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:278
static btDbvtVolume bounds(const tNodeArray &leaves)
Definition: btDbvt.cpp:250
const btCollisionObject * getCollisionObject() const
int getNumChildShapes() const