Bullet Collision Detection & Physics Library
btConvexConcaveCollisionAlgorithm.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 
29 
31 : btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
32 m_isSwapped(isSwapped),
33 m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped)
34 {
35 }
36 
38 {
39 }
40 
42 {
44  {
46  }
47 }
48 
49 
51  m_dispatcher(dispatcher),
52  m_dispatchInfoPtr(0)
53 {
54  m_convexBodyWrap = isSwapped? body1Wrap:body0Wrap;
55  m_triBodyWrap = isSwapped? body0Wrap:body1Wrap;
56 
57  //
58  // create the manifold from the dispatcher 'manifold pool'
59  //
61 
62  clearCache();
63 }
64 
66 {
67  clearCache();
69 
70 }
71 
72 
74 {
76 }
77 
78 
80 partId, int triangleIndex)
81 {
82 
84  {
85  return;
86  }
87 
88  //just for debugging purposes
89  //printf("triangle %d",m_triangleCount++);
90 
92 
95 
96  //const btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBodyWrap->getCollisionObject());
97 
98 
99 
100 
101 #if 0
102 
104  {
105  btVector3 color(1,1,0);
106  btTransform& tr = ob->getWorldTransform();
107  m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
108  m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
109  m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
110  }
111 #endif
112 
114  {
115  btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
117 
118 
119  btCollisionObjectWrapper triObWrap(m_triBodyWrap,&tm,m_triBodyWrap->getCollisionObject(),m_triBodyWrap->getWorldTransform(),partId,triangleIndex);//correct transform?
121 
122  const btCollisionObjectWrapper* tmpWrap = 0;
123 
125  {
126  tmpWrap = m_resultOut->getBody0Wrap();
127  m_resultOut->setBody0Wrap(&triObWrap);
128  m_resultOut->setShapeIdentifiersA(partId,triangleIndex);
129  }
130  else
131  {
132  tmpWrap = m_resultOut->getBody1Wrap();
133  m_resultOut->setBody1Wrap(&triObWrap);
134  m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
135  }
136 
137  colAlgo->processCollision(m_convexBodyWrap,&triObWrap,*m_dispatchInfoPtr,m_resultOut);
138 
140  {
141  m_resultOut->setBody0Wrap(tmpWrap);
142  } else
143  {
144  m_resultOut->setBody1Wrap(tmpWrap);
145  }
146 
147 
148 
149  colAlgo->~btCollisionAlgorithm();
151  }
152 
153 }
154 
155 
156 
157 void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
158 {
159  m_convexBodyWrap = convexBodyWrap;
160  m_triBodyWrap = triBodyWrap;
161 
162  m_dispatchInfoPtr = &dispatchInfo;
163  m_collisionMarginTriangle = collisionMarginTriangle;
164  m_resultOut = resultOut;
165 
166  //recalc aabbs
167  btTransform convexInTriangleSpace;
169  const btCollisionShape* convexShape = static_cast<const btCollisionShape*>(m_convexBodyWrap->getCollisionShape());
170  //CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
171  convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
172  btScalar extraMargin = collisionMarginTriangle;
173  btVector3 extra(extraMargin,extraMargin,extraMargin);
174 
175  m_aabbMax += extra;
176  m_aabbMin -= extra;
177 
178 }
179 
181 {
183 
184 }
185 
187 {
188 
189 
190  const btCollisionObjectWrapper* convexBodyWrap = m_isSwapped ? body1Wrap : body0Wrap;
191  const btCollisionObjectWrapper* triBodyWrap = m_isSwapped ? body0Wrap : body1Wrap;
192 
193  if (triBodyWrap->getCollisionShape()->isConcave())
194  {
195 
196 
197 
198  const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triBodyWrap->getCollisionShape());
199 
200  if (convexBodyWrap->getCollisionShape()->isConvex())
201  {
202  btScalar collisionMarginTriangle = concaveShape->getMargin();
203 
205  m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,convexBodyWrap,triBodyWrap,resultOut);
206 
208 
210 
211  resultOut->refreshContactPoints();
212 
214 
215  }
216 
217  }
218 
219 }
220 
221 
223 {
224  (void)resultOut;
225  (void)dispatchInfo;
226  btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
227  btCollisionObject* triBody = m_isSwapped ? body0 : body1;
228 
229 
230  //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
231 
232  //only perform CCD above a certain threshold, this prevents blocking on the long run
233  //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
234  btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
235  if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
236  {
237  return btScalar(1.);
238  }
239 
240  //const btVector3& from = convexbody->m_worldTransform.getOrigin();
241  //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
242  //todo: only do if the motion exceeds the 'radius'
243 
244  btTransform triInv = triBody->getWorldTransform().inverse();
245  btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
246  btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
247 
248  struct LocalTriangleSphereCastCallback : public btTriangleCallback
249  {
250  btTransform m_ccdSphereFromTrans;
251  btTransform m_ccdSphereToTrans;
252  btTransform m_meshTransform;
253 
254  btScalar m_ccdSphereRadius;
255  btScalar m_hitFraction;
256 
257 
258  LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
259  :m_ccdSphereFromTrans(from),
260  m_ccdSphereToTrans(to),
261  m_ccdSphereRadius(ccdSphereRadius),
262  m_hitFraction(hitFraction)
263  {
264  }
265 
266 
267  virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
268  {
269  (void)partId;
270  (void)triangleIndex;
271  //do a swept sphere for now
272  btTransform ident;
273  ident.setIdentity();
274  btConvexCast::CastResult castResult;
275  castResult.m_fraction = m_hitFraction;
276  btSphereShape pointShape(m_ccdSphereRadius);
277  btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
278  btVoronoiSimplexSolver simplexSolver;
279  btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
280  //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
281  //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
282  //local space?
283 
284  if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
285  ident,ident,castResult))
286  {
287  if (m_hitFraction > castResult.m_fraction)
288  m_hitFraction = castResult.m_fraction;
289  }
290 
291  }
292 
293  };
294 
295 
296 
297 
298 
299  if (triBody->getCollisionShape()->isConcave())
300  {
301  btVector3 rayAabbMin = convexFromLocal.getOrigin();
302  rayAabbMin.setMin(convexToLocal.getOrigin());
303  btVector3 rayAabbMax = convexFromLocal.getOrigin();
304  rayAabbMax.setMax(convexToLocal.getOrigin());
305  btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
306  rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
307  rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
308 
309  btScalar curHitFraction = btScalar(1.); //is this available?
310  LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
311  convexbody->getCcdSweptSphereRadius(),curHitFraction);
312 
313  raycastCallback.m_hitFraction = convexbody->getHitFraction();
314 
315  btCollisionObject* concavebody = triBody;
316 
317  btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
318 
319  if (triangleMesh)
320  {
321  triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
322  }
323 
324 
325 
326  if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
327  {
328  convexbody->setHitFraction( raycastCallback.m_hitFraction);
329  return raycastCallback.m_hitFraction;
330  }
331  }
332 
333  return btScalar(1.);
334 
335 }