00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "btConvexConcaveCollisionAlgorithm.h"
00018 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
00019 #include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
00020 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
00021 #include "BulletCollision/CollisionShapes/btConcaveShape.h"
00022 #include "BulletCollision/CollisionDispatch/btManifoldResult.h"
00023 #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
00024 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
00025 #include "BulletCollision/CollisionShapes/btSphereShape.h"
00026 #include "LinearMath/btIDebugDraw.h"
00027 #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
00028
00029 btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
00030 : btActivatingCollisionAlgorithm(ci,body0,body1),
00031 m_isSwapped(isSwapped),
00032 m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
00033 {
00034 }
00035
00036 btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
00037 {
00038 }
00039
00040 void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
00041 {
00042 if (m_btConvexTriangleCallback.m_manifoldPtr)
00043 {
00044 manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr);
00045 }
00046 }
00047
00048
00049 btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
00050 m_dispatcher(dispatcher),
00051 m_dispatchInfoPtr(0)
00052 {
00053 m_convexBody = isSwapped? body1:body0;
00054 m_triBody = isSwapped? body0:body1;
00055
00056
00057
00058
00059 m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody);
00060
00061 clearCache();
00062 }
00063
00064 btConvexTriangleCallback::~btConvexTriangleCallback()
00065 {
00066 clearCache();
00067 m_dispatcher->releaseManifold( m_manifoldPtr );
00068
00069 }
00070
00071
00072 void btConvexTriangleCallback::clearCache()
00073 {
00074 m_dispatcher->clearManifold(m_manifoldPtr);
00075 }
00076
00077
00078
00079 void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
00080 {
00081
00082
00083
00084
00085
00086
00087
00088 btCollisionAlgorithmConstructionInfo ci;
00089 ci.m_dispatcher1 = m_dispatcher;
00090
00091 btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
00092
00093
00094
00096 if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe ))
00097 {
00098 btVector3 color(1,1,0);
00099 btTransform& tr = ob->getWorldTransform();
00100 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
00101 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
00102 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
00103
00104
00105
00106
00107
00108
00109
00110 }
00111
00112
00113
00114
00115 if (m_convexBody->getCollisionShape()->isConvex())
00116 {
00117 btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
00118 tm.setMargin(m_collisionMarginTriangle);
00119
00120 btCollisionShape* tmpShape = ob->getCollisionShape();
00121 ob->internalSetTemporaryCollisionShape( &tm );
00122
00123 btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr);
00124
00125 if (m_resultOut->getBody0Internal() == m_triBody)
00126 {
00127 m_resultOut->setShapeIdentifiersA(partId,triangleIndex);
00128 }
00129 else
00130 {
00131 m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
00132 }
00133
00134 colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
00135 colAlgo->~btCollisionAlgorithm();
00136 ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
00137 ob->internalSetTemporaryCollisionShape( tmpShape);
00138 }
00139
00140
00141 }
00142
00143
00144
00145 void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00146 {
00147 m_dispatchInfoPtr = &dispatchInfo;
00148 m_collisionMarginTriangle = collisionMarginTriangle;
00149 m_resultOut = resultOut;
00150
00151
00152 btTransform convexInTriangleSpace;
00153 convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_convexBody->getWorldTransform();
00154 btCollisionShape* convexShape = static_cast<btCollisionShape*>(m_convexBody->getCollisionShape());
00155
00156 convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
00157 btScalar extraMargin = collisionMarginTriangle;
00158 btVector3 extra(extraMargin,extraMargin,extraMargin);
00159
00160 m_aabbMax += extra;
00161 m_aabbMin -= extra;
00162
00163 }
00164
00165 void btConvexConcaveCollisionAlgorithm::clearCache()
00166 {
00167 m_btConvexTriangleCallback.clearCache();
00168
00169 }
00170
00171 void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00172 {
00173
00174
00175 btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
00176 btCollisionObject* triBody = m_isSwapped ? body0 : body1;
00177
00178 if (triBody->getCollisionShape()->isConcave())
00179 {
00180
00181
00182 btCollisionObject* triOb = triBody;
00183 btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape());
00184
00185 if (convexBody->getCollisionShape()->isConvex())
00186 {
00187 btScalar collisionMarginTriangle = concaveShape->getMargin();
00188
00189 resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
00190 m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut);
00191
00192
00193
00194
00195 m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody);
00196
00197 concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
00198
00199 resultOut->refreshContactPoints();
00200
00201 }
00202
00203 }
00204
00205 }
00206
00207
00208 btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00209 {
00210 (void)resultOut;
00211 (void)dispatchInfo;
00212 btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
00213 btCollisionObject* triBody = m_isSwapped ? body0 : body1;
00214
00215
00216
00217
00218
00219
00220 btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
00221 if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
00222 {
00223 return btScalar(1.);
00224 }
00225
00226
00227
00228
00229
00230 btTransform triInv = triBody->getWorldTransform().inverse();
00231 btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
00232 btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
00233
00234 struct LocalTriangleSphereCastCallback : public btTriangleCallback
00235 {
00236 btTransform m_ccdSphereFromTrans;
00237 btTransform m_ccdSphereToTrans;
00238 btTransform m_meshTransform;
00239
00240 btScalar m_ccdSphereRadius;
00241 btScalar m_hitFraction;
00242
00243
00244 LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
00245 :m_ccdSphereFromTrans(from),
00246 m_ccdSphereToTrans(to),
00247 m_ccdSphereRadius(ccdSphereRadius),
00248 m_hitFraction(hitFraction)
00249 {
00250 }
00251
00252
00253 virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
00254 {
00255 (void)partId;
00256 (void)triangleIndex;
00257
00258 btTransform ident;
00259 ident.setIdentity();
00260 btConvexCast::CastResult castResult;
00261 castResult.m_fraction = m_hitFraction;
00262 btSphereShape pointShape(m_ccdSphereRadius);
00263 btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
00264 btVoronoiSimplexSolver simplexSolver;
00265 btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
00266
00267
00268
00269
00270 if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
00271 ident,ident,castResult))
00272 {
00273 if (m_hitFraction > castResult.m_fraction)
00274 m_hitFraction = castResult.m_fraction;
00275 }
00276
00277 }
00278
00279 };
00280
00281
00282
00283
00284
00285 if (triBody->getCollisionShape()->isConcave())
00286 {
00287 btVector3 rayAabbMin = convexFromLocal.getOrigin();
00288 rayAabbMin.setMin(convexToLocal.getOrigin());
00289 btVector3 rayAabbMax = convexFromLocal.getOrigin();
00290 rayAabbMax.setMax(convexToLocal.getOrigin());
00291 btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
00292 rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
00293 rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
00294
00295 btScalar curHitFraction = btScalar(1.);
00296 LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
00297 convexbody->getCcdSweptSphereRadius(),curHitFraction);
00298
00299 raycastCallback.m_hitFraction = convexbody->getHitFraction();
00300
00301 btCollisionObject* concavebody = triBody;
00302
00303 btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
00304
00305 if (triangleMesh)
00306 {
00307 triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
00308 }
00309
00310
00311
00312 if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
00313 {
00314 convexbody->setHitFraction( raycastCallback.m_hitFraction);
00315 return raycastCallback.m_hitFraction;
00316 }
00317 }
00318
00319 return btScalar(1.);
00320
00321 }