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 }

Generated on Mon Feb 15 22:17:03 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1