00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
00081
00082 int numIter = 0;
00083
00084
00085
00086 btTransform identityTrans;
00087 identityTrans.setIdentity();
00088
00089 btSphereShape raySphere(btScalar(0.0));
00090 raySphere.setMargin(btScalar(0.));
00091
00092
00093
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
00103
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
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;
00132 }
00133 btScalar dLambda = btScalar(0.);
00134
00135 projectedLinearVelocity = relLinVel.dot(n);
00136
00137
00138
00139
00140
00141
00142
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
00160 if (lambda <= lastLambda)
00161 {
00162 return false;
00163
00164 break;
00165 }
00166 lastLambda = lambda;
00167
00168
00169
00170
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
00195 result.m_fraction = lastLambda;
00196 n = pointCollector.m_normalOnBInWorld;
00197 result.m_normal=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)
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
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 }