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 }

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