Blender V2.61 - r43446

btContinuousConvexCollision.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 "btContinuousConvexCollision.h"
00018 #include "BulletCollision/CollisionShapes/btConvexShape.h"
00019 #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
00020 #include "LinearMath/btTransformUtil.h"
00021 #include "BulletCollision/CollisionShapes/btSphereShape.h"
00022 
00023 #include "btGjkPairDetector.h"
00024 #include "btPointCollector.h"
00025 
00026 
00027 
00028 btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape*    convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
00029 :m_simplexSolver(simplexSolver),
00030 m_penetrationDepthSolver(penetrationDepthSolver),
00031 m_convexA(convexA),m_convexB(convexB)
00032 {
00033 }
00034 
00037 #define MAX_ITERATIONS 64
00038 
00039 bool    btContinuousConvexCollision::calcTimeOfImpact(
00040                 const btTransform& fromA,
00041                 const btTransform& toA,
00042                 const btTransform& fromB,
00043                 const btTransform& toB,
00044                 CastResult& result)
00045 {
00046 
00047     m_simplexSolver->reset();
00048 
00050     btVector3 linVelA,angVelA,linVelB,angVelB;
00051     btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA);
00052     btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB);
00053 
00054 
00055     btScalar boundingRadiusA = m_convexA->getAngularMotionDisc();
00056     btScalar boundingRadiusB = m_convexB->getAngularMotionDisc();
00057 
00058     btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB;
00059     btVector3 relLinVel = (linVelB-linVelA);
00060 
00061     btScalar relLinVelocLength = (linVelB-linVelA).length();
00062     
00063     if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f)
00064         return false;
00065 
00066 
00067     btScalar radius = btScalar(0.001);
00068 
00069     btScalar lambda = btScalar(0.);
00070     btVector3 v(1,0,0);
00071 
00072     int maxIter = MAX_ITERATIONS;
00073 
00074     btVector3 n;
00075     n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
00076     bool hasResult = false;
00077     btVector3 c;
00078 
00079     btScalar lastLambda = lambda;
00080     //btScalar epsilon = btScalar(0.001);
00081 
00082     int numIter = 0;
00083     //first solution, using GJK
00084 
00085 
00086     btTransform identityTrans;
00087     identityTrans.setIdentity();
00088 
00089     btSphereShape   raySphere(btScalar(0.0));
00090     raySphere.setMargin(btScalar(0.));
00091 
00092 
00093 //  result.drawCoordSystem(sphereTr);
00094 
00095     btPointCollector    pointCollector1;
00096 
00097     {
00098         
00099         btGjkPairDetector gjk(m_convexA,m_convexB,m_convexA->getShapeType(),m_convexB->getShapeType(),m_convexA->getMargin(),m_convexB->getMargin(),m_simplexSolver,m_penetrationDepthSolver);      
00100         btGjkPairDetector::ClosestPointInput input;
00101     
00102         //we don't use margins during CCD
00103     //  gjk.setIgnoreMargin(true);
00104 
00105         input.m_transformA = fromA;
00106         input.m_transformB = fromB;
00107         gjk.getClosestPoints(input,pointCollector1,0);
00108 
00109         hasResult = pointCollector1.m_hasResult;
00110         c = pointCollector1.m_pointInWorld;
00111     }
00112 
00113     if (hasResult)
00114     {
00115         btScalar dist;
00116         dist = pointCollector1.m_distance;
00117         n = pointCollector1.m_normalOnBInWorld;
00118 
00119         btScalar projectedLinearVelocity = relLinVel.dot(n);
00120         
00121         //not close enough
00122         while (dist > radius)
00123         {
00124             if (result.m_debugDrawer)
00125             {
00126                 result.m_debugDrawer->drawSphere(c,0.2f,btVector3(1,1,1));
00127             }
00128             numIter++;
00129             if (numIter > maxIter)
00130             {
00131                 return false; //todo: report a failure
00132             }
00133             btScalar dLambda = btScalar(0.);
00134 
00135             projectedLinearVelocity = relLinVel.dot(n);
00136 
00137             //calculate safe moving fraction from distance / (linear+rotational velocity)
00138             
00139             //btScalar clippedDist  = GEN_min(angularConservativeRadius,dist);
00140             //btScalar clippedDist  = dist;
00141             
00142             //don't report time of impact for motion away from the contact normal (or causes minor penetration)
00143             if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON)
00144                 return false;
00145             
00146             dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity);
00147 
00148             
00149             
00150             lambda = lambda + dLambda;
00151 
00152             if (lambda > btScalar(1.))
00153                 return false;
00154 
00155             if (lambda < btScalar(0.))
00156                 return false;
00157 
00158 
00159             //todo: next check with relative epsilon
00160             if (lambda <= lastLambda)
00161             {
00162                 return false;
00163                 //n.setValue(0,0,0);
00164                 break;
00165             }
00166             lastLambda = lambda;
00167 
00168             
00169 
00170             //interpolate to next lambda
00171             btTransform interpolatedTransA,interpolatedTransB,relativeTrans;
00172 
00173             btTransformUtil::integrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA);
00174             btTransformUtil::integrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB);
00175             relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA);
00176 
00177             if (result.m_debugDrawer)
00178             {
00179                 result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(),0.2f,btVector3(1,0,0));
00180             }
00181 
00182             result.DebugDraw( lambda );
00183 
00184             btPointCollector    pointCollector;
00185             btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver);
00186             btGjkPairDetector::ClosestPointInput input;
00187             input.m_transformA = interpolatedTransA;
00188             input.m_transformB = interpolatedTransB;
00189             gjk.getClosestPoints(input,pointCollector,0);
00190             if (pointCollector.m_hasResult)
00191             {
00192                 if (pointCollector.m_distance < btScalar(0.))
00193                 {
00194                     //degenerate ?!
00195                     result.m_fraction = lastLambda;
00196                     n = pointCollector.m_normalOnBInWorld;
00197                     result.m_normal=n;//.setValue(1,1,1);// = n;
00198                     result.m_hitPoint = pointCollector.m_pointInWorld;
00199                     return true;
00200                 }
00201                 c = pointCollector.m_pointInWorld;      
00202                 n = pointCollector.m_normalOnBInWorld;
00203                 dist = pointCollector.m_distance;
00204             } else
00205             {
00206                 //??
00207                 return false;
00208             }
00209             
00210 
00211         }
00212     
00213         if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=result.m_allowedPenetration)//SIMD_EPSILON)
00214             return false;
00215             
00216         result.m_fraction = lambda;
00217         result.m_normal = n;
00218         result.m_hitPoint = c;
00219         return true;
00220     }
00221 
00222     return false;
00223 
00224 /*
00225 //todo:
00226     //if movement away from normal, discard result
00227     btVector3 move = transBLocalTo.getOrigin() - transBLocalFrom.getOrigin();
00228     if (result.m_fraction < btScalar(1.))
00229     {
00230         if (move.dot(result.m_normal) <= btScalar(0.))
00231         {
00232         }
00233     }
00234 */
00235 
00236 }