Blender V2.61 - r43446

btConvexConcaveCollisionAlgorithm.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
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       // create the manifold from the dispatcher 'manifold pool'
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     //just for debugging purposes
00083     //printf("triangle %d",m_triangleCount++);
00084 
00085 
00086     //aabb filter is already applied!   
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         //btVector3 center = triangle[0] + triangle[1]+triangle[2];
00105         //center *= btScalar(0.333333);
00106         //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(center),color);
00107         //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(center),color);
00108         //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(center),color);
00109 
00110     }
00111 
00112 
00113     //btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);
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     //recalc aabbs
00152     btTransform convexInTriangleSpace;
00153     convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_convexBody->getWorldTransform();
00154     btCollisionShape* convexShape = static_cast<btCollisionShape*>(m_convexBody->getCollisionShape());
00155     //CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
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             //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here.
00193             //m_dispatcher->clearManifold(m_btConvexTriangleCallback.m_manifoldPtr);
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     //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
00217 
00218     //only perform CCD above a certain threshold, this prevents blocking on the long run
00219     //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
00220     btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
00221     if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
00222     {
00223         return btScalar(1.);
00224     }
00225 
00226     //const btVector3& from = convexbody->m_worldTransform.getOrigin();
00227     //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
00228     //todo: only do if the motion exceeds the 'radius'
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             //do a swept sphere for now
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             //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
00267             //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
00268             //local space?
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.); //is this available?
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 }