Bullet 2.85 update
[Torque-3d.git] / Engine / lib / bullet / src / BulletCollision / CollisionDispatch / btConvexConcaveCollisionAlgorithm.cpp
blobc774383dc11af4c8349e7404e1241f41bf75aa1f
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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:
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.
17 #include "btConvexConcaveCollisionAlgorithm.h"
18 #include "LinearMath/btQuickprof.h"
19 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
20 #include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
21 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
22 #include "BulletCollision/CollisionShapes/btConcaveShape.h"
23 #include "BulletCollision/CollisionDispatch/btManifoldResult.h"
24 #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
25 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
26 #include "BulletCollision/CollisionShapes/btSphereShape.h"
27 #include "LinearMath/btIDebugDraw.h"
28 #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
29 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
31 btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
32 : btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
33 m_isSwapped(isSwapped),
34 m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped)
38 btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
42 void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
44 if (m_btConvexTriangleCallback.m_manifoldPtr)
46 manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr);
51 btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped):
52 m_dispatcher(dispatcher),
53 m_dispatchInfoPtr(0)
55 m_convexBodyWrap = isSwapped? body1Wrap:body0Wrap;
56 m_triBodyWrap = isSwapped? body0Wrap:body1Wrap;
59 // create the manifold from the dispatcher 'manifold pool'
61 m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(),m_triBodyWrap->getCollisionObject());
63 clearCache();
66 btConvexTriangleCallback::~btConvexTriangleCallback()
68 clearCache();
69 m_dispatcher->releaseManifold( m_manifoldPtr );
74 void btConvexTriangleCallback::clearCache()
76 m_dispatcher->clearManifold(m_manifoldPtr);
80 void btConvexTriangleCallback::processTriangle(btVector3* triangle,int
81 partId, int triangleIndex)
83 BT_PROFILE("btConvexTriangleCallback::processTriangle");
85 if (!TestTriangleAgainstAabb2(triangle, m_aabbMin, m_aabbMax))
87 return;
90 //just for debugging purposes
91 //printf("triangle %d",m_triangleCount++);
95 btCollisionAlgorithmConstructionInfo ci;
96 ci.m_dispatcher1 = m_dispatcher;
100 #if 0
102 ///debug drawing of the overlapping triangles
103 if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe ))
105 const btCollisionObject* ob = const_cast<btCollisionObject*>(m_triBodyWrap->getCollisionObject());
106 btVector3 color(1,1,0);
107 btTransform& tr = ob->getWorldTransform();
108 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
109 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
110 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
112 #endif
114 if (m_convexBodyWrap->getCollisionShape()->isConvex())
116 btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
117 tm.setMargin(m_collisionMarginTriangle);
120 btCollisionObjectWrapper triObWrap(m_triBodyWrap,&tm,m_triBodyWrap->getCollisionObject(),m_triBodyWrap->getWorldTransform(),partId,triangleIndex);//correct transform?
121 btCollisionAlgorithm* colAlgo = 0;
123 if (m_resultOut->m_closestPointDistanceThreshold > 0)
125 colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
127 else
129 colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, m_manifoldPtr, BT_CONTACT_POINT_ALGORITHMS);
131 const btCollisionObjectWrapper* tmpWrap = 0;
133 if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
135 tmpWrap = m_resultOut->getBody0Wrap();
136 m_resultOut->setBody0Wrap(&triObWrap);
137 m_resultOut->setShapeIdentifiersA(partId,triangleIndex);
139 else
141 tmpWrap = m_resultOut->getBody1Wrap();
142 m_resultOut->setBody1Wrap(&triObWrap);
143 m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
146 colAlgo->processCollision(m_convexBodyWrap,&triObWrap,*m_dispatchInfoPtr,m_resultOut);
148 if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
150 m_resultOut->setBody0Wrap(tmpWrap);
151 } else
153 m_resultOut->setBody1Wrap(tmpWrap);
158 colAlgo->~btCollisionAlgorithm();
159 ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
166 void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
168 m_convexBodyWrap = convexBodyWrap;
169 m_triBodyWrap = triBodyWrap;
171 m_dispatchInfoPtr = &dispatchInfo;
172 m_collisionMarginTriangle = collisionMarginTriangle;
173 m_resultOut = resultOut;
175 //recalc aabbs
176 btTransform convexInTriangleSpace;
177 convexInTriangleSpace = m_triBodyWrap->getWorldTransform().inverse() * m_convexBodyWrap->getWorldTransform();
178 const btCollisionShape* convexShape = static_cast<const btCollisionShape*>(m_convexBodyWrap->getCollisionShape());
179 //CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
180 convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
181 btScalar extraMargin = collisionMarginTriangle+ resultOut->m_closestPointDistanceThreshold;
183 btVector3 extra(extraMargin,extraMargin,extraMargin);
185 m_aabbMax += extra;
186 m_aabbMin -= extra;
190 void btConvexConcaveCollisionAlgorithm::clearCache()
192 m_btConvexTriangleCallback.clearCache();
196 void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
198 BT_PROFILE("btConvexConcaveCollisionAlgorithm::processCollision");
200 const btCollisionObjectWrapper* convexBodyWrap = m_isSwapped ? body1Wrap : body0Wrap;
201 const btCollisionObjectWrapper* triBodyWrap = m_isSwapped ? body0Wrap : body1Wrap;
203 if (triBodyWrap->getCollisionShape()->isConcave())
208 const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triBodyWrap->getCollisionShape());
210 if (convexBodyWrap->getCollisionShape()->isConvex())
212 btScalar collisionMarginTriangle = concaveShape->getMargin();
214 resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
215 m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,convexBodyWrap,triBodyWrap,resultOut);
217 m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(),triBodyWrap->getCollisionObject());
219 concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
221 resultOut->refreshContactPoints();
223 m_btConvexTriangleCallback.clearWrapperData();
232 btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
234 (void)resultOut;
235 (void)dispatchInfo;
236 btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
237 btCollisionObject* triBody = m_isSwapped ? body0 : body1;
240 //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
242 //only perform CCD above a certain threshold, this prevents blocking on the long run
243 //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
244 btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
245 if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
247 return btScalar(1.);
250 //const btVector3& from = convexbody->m_worldTransform.getOrigin();
251 //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
252 //todo: only do if the motion exceeds the 'radius'
254 btTransform triInv = triBody->getWorldTransform().inverse();
255 btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
256 btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
258 struct LocalTriangleSphereCastCallback : public btTriangleCallback
260 btTransform m_ccdSphereFromTrans;
261 btTransform m_ccdSphereToTrans;
262 btTransform m_meshTransform;
264 btScalar m_ccdSphereRadius;
265 btScalar m_hitFraction;
268 LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
269 :m_ccdSphereFromTrans(from),
270 m_ccdSphereToTrans(to),
271 m_ccdSphereRadius(ccdSphereRadius),
272 m_hitFraction(hitFraction)
277 virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
279 BT_PROFILE("processTriangle");
280 (void)partId;
281 (void)triangleIndex;
282 //do a swept sphere for now
283 btTransform ident;
284 ident.setIdentity();
285 btConvexCast::CastResult castResult;
286 castResult.m_fraction = m_hitFraction;
287 btSphereShape pointShape(m_ccdSphereRadius);
288 btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
289 btVoronoiSimplexSolver simplexSolver;
290 btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
291 //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
292 //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
293 //local space?
295 if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
296 ident,ident,castResult))
298 if (m_hitFraction > castResult.m_fraction)
299 m_hitFraction = castResult.m_fraction;
310 if (triBody->getCollisionShape()->isConcave())
312 btVector3 rayAabbMin = convexFromLocal.getOrigin();
313 rayAabbMin.setMin(convexToLocal.getOrigin());
314 btVector3 rayAabbMax = convexFromLocal.getOrigin();
315 rayAabbMax.setMax(convexToLocal.getOrigin());
316 btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
317 rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
318 rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
320 btScalar curHitFraction = btScalar(1.); //is this available?
321 LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
322 convexbody->getCcdSweptSphereRadius(),curHitFraction);
324 raycastCallback.m_hitFraction = convexbody->getHitFraction();
326 btCollisionObject* concavebody = triBody;
328 btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
330 if (triangleMesh)
332 triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
337 if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
339 convexbody->setHitFraction( raycastCallback.m_hitFraction);
340 return raycastCallback.m_hitFraction;
344 return btScalar(1.);