Blender V2.61 - r43446
|
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 }