Blender V2.61 - r43446

btConvexConvexAlgorithm.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 
00019 //define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1
00020 
00021 #include "btConvexConvexAlgorithm.h"
00022 
00023 //#include <stdio.h>
00024 #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
00025 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
00026 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
00027 #include "BulletCollision/CollisionShapes/btConvexShape.h"
00028 #include "BulletCollision/CollisionShapes/btCapsuleShape.h"
00029 
00030 
00031 #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
00032 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
00033 #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
00034 #include "BulletCollision/CollisionShapes/btBoxShape.h"
00035 #include "BulletCollision/CollisionDispatch/btManifoldResult.h"
00036 
00037 #include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
00038 #include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
00039 #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
00040 #include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
00041 
00042 
00043 
00044 #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
00045 #include "BulletCollision/CollisionShapes/btSphereShape.h"
00046 
00047 #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
00048 
00049 #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
00050 #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
00051 
00052 
00053 
00055 
00056 
00057 
00058 static SIMD_FORCE_INLINE void segmentsClosestPoints(
00059     btVector3& ptsVector,
00060     btVector3& offsetA,
00061     btVector3& offsetB,
00062     btScalar& tA, btScalar& tB,
00063     const btVector3& translation,
00064     const btVector3& dirA, btScalar hlenA,
00065     const btVector3& dirB, btScalar hlenB )
00066 {
00067     // compute the parameters of the closest points on each line segment
00068 
00069     btScalar dirA_dot_dirB = btDot(dirA,dirB);
00070     btScalar dirA_dot_trans = btDot(dirA,translation);
00071     btScalar dirB_dot_trans = btDot(dirB,translation);
00072 
00073     btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
00074 
00075     if ( denom == 0.0f ) {
00076         tA = 0.0f;
00077     } else {
00078         tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
00079         if ( tA < -hlenA )
00080             tA = -hlenA;
00081         else if ( tA > hlenA )
00082             tA = hlenA;
00083     }
00084 
00085     tB = tA * dirA_dot_dirB - dirB_dot_trans;
00086 
00087     if ( tB < -hlenB ) {
00088         tB = -hlenB;
00089         tA = tB * dirA_dot_dirB + dirA_dot_trans;
00090 
00091         if ( tA < -hlenA )
00092             tA = -hlenA;
00093         else if ( tA > hlenA )
00094             tA = hlenA;
00095     } else if ( tB > hlenB ) {
00096         tB = hlenB;
00097         tA = tB * dirA_dot_dirB + dirA_dot_trans;
00098 
00099         if ( tA < -hlenA )
00100             tA = -hlenA;
00101         else if ( tA > hlenA )
00102             tA = hlenA;
00103     }
00104 
00105     // compute the closest points relative to segment centers.
00106 
00107     offsetA = dirA * tA;
00108     offsetB = dirB * tB;
00109 
00110     ptsVector = translation - offsetA + offsetB;
00111 }
00112 
00113 
00114 static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance(
00115     btVector3& normalOnB,
00116     btVector3& pointOnB,
00117     btScalar capsuleLengthA,
00118     btScalar    capsuleRadiusA,
00119     btScalar capsuleLengthB,
00120     btScalar    capsuleRadiusB,
00121     int capsuleAxisA,
00122     int capsuleAxisB,
00123     const btTransform& transformA,
00124     const btTransform& transformB,
00125     btScalar distanceThreshold )
00126 {
00127     btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA);
00128     btVector3 translationA = transformA.getOrigin();
00129     btVector3 directionB = transformB.getBasis().getColumn(capsuleAxisB);
00130     btVector3 translationB = transformB.getOrigin();
00131 
00132     // translation between centers
00133 
00134     btVector3 translation = translationB - translationA;
00135 
00136     // compute the closest points of the capsule line segments
00137 
00138     btVector3 ptsVector;           // the vector between the closest points
00139     
00140     btVector3 offsetA, offsetB;    // offsets from segment centers to their closest points
00141     btScalar tA, tB;              // parameters on line segment
00142 
00143     segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation,
00144                            directionA, capsuleLengthA, directionB, capsuleLengthB );
00145 
00146     btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB;
00147 
00148     if ( distance > distanceThreshold )
00149         return distance;
00150 
00151     btScalar lenSqr = ptsVector.length2();
00152     if (lenSqr<= (SIMD_EPSILON*SIMD_EPSILON))
00153     {
00154         //degenerate case where 2 capsules are likely at the same location: take a vector tangential to 'directionA'
00155         btVector3 q;
00156         btPlaneSpace1(directionA,normalOnB,q);
00157     } else
00158     {
00159         // compute the contact normal
00160         normalOnB = ptsVector*-btRecipSqrt(lenSqr);
00161     }
00162     pointOnB = transformB.getOrigin()+offsetB + normalOnB * capsuleRadiusB;
00163 
00164     return distance;
00165 }
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00174 
00175 
00176 
00177 
00178 
00179 btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface*           simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
00180 {
00181     m_numPerturbationIterations = 0;
00182     m_minimumPointsPerturbationThreshold = 3;
00183     m_simplexSolver = simplexSolver;
00184     m_pdSolver = pdSolver;
00185 }
00186 
00187 btConvexConvexAlgorithm::CreateFunc::~CreateFunc() 
00188 { 
00189 }
00190 
00191 btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
00192 : btActivatingCollisionAlgorithm(ci,body0,body1),
00193 m_simplexSolver(simplexSolver),
00194 m_pdSolver(pdSolver),
00195 m_ownManifold (false),
00196 m_manifoldPtr(mf),
00197 m_lowLevelOfDetail(false),
00198 #ifdef USE_SEPDISTANCE_UTIL2
00199 m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngularMotionDisc(),
00200               (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()),
00201 #endif
00202 m_numPerturbationIterations(numPerturbationIterations),
00203 m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
00204 {
00205     (void)body0;
00206     (void)body1;
00207 }
00208 
00209 
00210 
00211 
00212 btConvexConvexAlgorithm::~btConvexConvexAlgorithm()
00213 {
00214     if (m_ownManifold)
00215     {
00216         if (m_manifoldPtr)
00217             m_dispatcher->releaseManifold(m_manifoldPtr);
00218     }
00219 }
00220 
00221 void    btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
00222 {
00223     m_lowLevelOfDetail = useLowLevel;
00224 }
00225 
00226 
00227 struct btPerturbedContactResult : public btManifoldResult
00228 {
00229     btManifoldResult* m_originalManifoldResult;
00230     btTransform m_transformA;
00231     btTransform m_transformB;
00232     btTransform m_unPerturbedTransform;
00233     bool    m_perturbA;
00234     btIDebugDraw*   m_debugDrawer;
00235 
00236 
00237     btPerturbedContactResult(btManifoldResult* originalResult,const btTransform& transformA,const btTransform& transformB,const btTransform& unPerturbedTransform,bool perturbA,btIDebugDraw* debugDrawer)
00238         :m_originalManifoldResult(originalResult),
00239         m_transformA(transformA),
00240         m_transformB(transformB),
00241         m_unPerturbedTransform(unPerturbedTransform),
00242         m_perturbA(perturbA),
00243         m_debugDrawer(debugDrawer)
00244     {
00245     }
00246     virtual ~ btPerturbedContactResult()
00247     {
00248     }
00249 
00250     virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar orgDepth)
00251     {
00252         btVector3 endPt,startPt;
00253         btScalar newDepth;
00254         btVector3 newNormal;
00255 
00256         if (m_perturbA)
00257         {
00258             btVector3 endPtOrg = pointInWorld + normalOnBInWorld*orgDepth;
00259             endPt = (m_unPerturbedTransform*m_transformA.inverse())(endPtOrg);
00260             newDepth = (endPt -  pointInWorld).dot(normalOnBInWorld);
00261             startPt = endPt+normalOnBInWorld*newDepth;
00262         } else
00263         {
00264             endPt = pointInWorld + normalOnBInWorld*orgDepth;
00265             startPt = (m_unPerturbedTransform*m_transformB.inverse())(pointInWorld);
00266             newDepth = (endPt -  startPt).dot(normalOnBInWorld);
00267             
00268         }
00269 
00270 //#define DEBUG_CONTACTS 1
00271 #ifdef DEBUG_CONTACTS
00272         m_debugDrawer->drawLine(startPt,endPt,btVector3(1,0,0));
00273         m_debugDrawer->drawSphere(startPt,0.05,btVector3(0,1,0));
00274         m_debugDrawer->drawSphere(endPt,0.05,btVector3(0,0,1));
00275 #endif //DEBUG_CONTACTS
00276 
00277         
00278         m_originalManifoldResult->addContactPoint(normalOnBInWorld,startPt,newDepth);
00279     }
00280 
00281 };
00282 
00283 extern btScalar gContactBreakingThreshold;
00284 
00285 
00286 //
00287 // Convex-Convex collision algorithm
00288 //
00289 void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00290 {
00291 
00292     if (!m_manifoldPtr)
00293     {
00294         //swapped?
00295         m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
00296         m_ownManifold = true;
00297     }
00298     resultOut->setPersistentManifold(m_manifoldPtr);
00299 
00300     //comment-out next line to test multi-contact generation
00301     //resultOut->getPersistentManifold()->clearManifold();
00302     
00303 
00304     btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape());
00305     btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape());
00306 
00307     btVector3  normalOnB;
00308         btVector3  pointOnBWorld;
00309 #ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
00310     if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
00311     {
00312         btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
00313         btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
00314         btVector3 localScalingA = capsuleA->getLocalScaling();
00315         btVector3 localScalingB = capsuleB->getLocalScaling();
00316         
00317         btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
00318 
00319         btScalar dist = capsuleCapsuleDistance(normalOnB,   pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(),
00320             capsuleB->getHalfHeight(),capsuleB->getRadius(),capsuleA->getUpAxis(),capsuleB->getUpAxis(),
00321             body0->getWorldTransform(),body1->getWorldTransform(),threshold);
00322 
00323         if (dist<threshold)
00324         {
00325             btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
00326             resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);   
00327         }
00328         resultOut->refreshContactPoints();
00329         return;
00330     }
00331 #endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
00332 
00333 
00334 #ifdef USE_SEPDISTANCE_UTIL2
00335     if (dispatchInfo.m_useConvexConservativeDistanceUtil)
00336     {
00337         m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(),body1->getWorldTransform());
00338     }
00339 
00340     if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f)
00341 #endif //USE_SEPDISTANCE_UTIL2
00342 
00343     {
00344 
00345     
00346     btGjkPairDetector::ClosestPointInput input;
00347 
00348     btGjkPairDetector   gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
00349     //TODO: if (dispatchInfo.m_useContinuous)
00350     gjkPairDetector.setMinkowskiA(min0);
00351     gjkPairDetector.setMinkowskiB(min1);
00352 
00353 #ifdef USE_SEPDISTANCE_UTIL2
00354     if (dispatchInfo.m_useConvexConservativeDistanceUtil)
00355     {
00356         input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
00357     } else
00358 #endif //USE_SEPDISTANCE_UTIL2
00359     {
00360         if (dispatchInfo.m_convexMaxDistanceUseCPT)
00361         {
00362             input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold();
00363         } else
00364         {
00365             input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
00366         }
00367         input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
00368     }
00369 
00370     input.m_stackAlloc = dispatchInfo.m_stackAllocator;
00371     input.m_transformA = body0->getWorldTransform();
00372     input.m_transformB = body1->getWorldTransform();
00373 
00374     gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
00375 
00376     
00377 
00378 #ifdef USE_SEPDISTANCE_UTIL2
00379     btScalar sepDist = 0.f;
00380     if (dispatchInfo.m_useConvexConservativeDistanceUtil)
00381     {
00382         sepDist = gjkPairDetector.getCachedSeparatingDistance();
00383         if (sepDist>SIMD_EPSILON)
00384         {
00385             sepDist += dispatchInfo.m_convexConservativeDistanceThreshold;
00386             //now perturbe directions to get multiple contact points
00387             
00388         }
00389     }
00390 #endif //USE_SEPDISTANCE_UTIL2
00391 
00392     //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
00393     
00394     //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points
00395     if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
00396     {
00397         
00398         int i;
00399         btVector3 v0,v1;
00400         btVector3 sepNormalWorldSpace;
00401     
00402         sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized();
00403         btPlaneSpace1(sepNormalWorldSpace,v0,v1);
00404 
00405 
00406         bool perturbeA = true;
00407         const btScalar angleLimit = 0.125f * SIMD_PI;
00408         btScalar perturbeAngle;
00409         btScalar radiusA = min0->getAngularMotionDisc();
00410         btScalar radiusB = min1->getAngularMotionDisc();
00411         if (radiusA < radiusB)
00412         {
00413             perturbeAngle = gContactBreakingThreshold /radiusA;
00414             perturbeA = true;
00415         } else
00416         {
00417             perturbeAngle = gContactBreakingThreshold / radiusB;
00418             perturbeA = false;
00419         }
00420         if ( perturbeAngle > angleLimit ) 
00421                 perturbeAngle = angleLimit;
00422 
00423         btTransform unPerturbedTransform;
00424         if (perturbeA)
00425         {
00426             unPerturbedTransform = input.m_transformA;
00427         } else
00428         {
00429             unPerturbedTransform = input.m_transformB;
00430         }
00431         
00432         for ( i=0;i<m_numPerturbationIterations;i++)
00433         {
00434             if (v0.length2()>SIMD_EPSILON)
00435             {
00436             btQuaternion perturbeRot(v0,perturbeAngle);
00437             btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
00438             btQuaternion rotq(sepNormalWorldSpace,iterationAngle);
00439             
00440             
00441             if (perturbeA)
00442             {
00443                 input.m_transformA.setBasis(  btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0->getWorldTransform().getBasis());
00444                 input.m_transformB = body1->getWorldTransform();
00445 #ifdef DEBUG_CONTACTS
00446                 dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0);
00447 #endif //DEBUG_CONTACTS
00448             } else
00449             {
00450                 input.m_transformA = body0->getWorldTransform();
00451                 input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis());
00452 #ifdef DEBUG_CONTACTS
00453                 dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0);
00454 #endif
00455             }
00456             
00457             btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw);
00458             gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw);
00459             }
00460             
00461         }
00462     }
00463 
00464     
00465 
00466 #ifdef USE_SEPDISTANCE_UTIL2
00467     if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist>SIMD_EPSILON))
00468     {
00469         m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform());
00470     }
00471 #endif //USE_SEPDISTANCE_UTIL2
00472 
00473 
00474     }
00475 
00476     if (m_ownManifold)
00477     {
00478         resultOut->refreshContactPoints();
00479     }
00480 
00481 }
00482 
00483 
00484 
00485 bool disableCcd = false;
00486 btScalar    btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00487 {
00488     (void)resultOut;
00489     (void)dispatchInfo;
00491     
00494     btScalar resultFraction = btScalar(1.);
00495 
00496 
00497     btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
00498     btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
00499     
00500     if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
00501         squareMot1 < col1->getCcdSquareMotionThreshold())
00502         return resultFraction;
00503 
00504     if (disableCcd)
00505         return btScalar(1.);
00506 
00507 
00508     //An adhoc way of testing the Continuous Collision Detection algorithms
00509     //One object is approximated as a sphere, to simplify things
00510     //Starting in penetration should report no time of impact
00511     //For proper CCD, better accuracy and handling of 'allowed' penetration should be added
00512     //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
00513 
00514         
00516     {
00517         btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
00518 
00519         btSphereShape   sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
00520         btConvexCast::CastResult result;
00521         btVoronoiSimplexSolver voronoiSimplex;
00522         //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
00524         btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
00525         //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
00526         if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
00527             col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
00528         {
00529         
00530             //store result.m_fraction in both bodies
00531         
00532             if (col0->getHitFraction()> result.m_fraction)
00533                 col0->setHitFraction( result.m_fraction );
00534 
00535             if (col1->getHitFraction() > result.m_fraction)
00536                 col1->setHitFraction( result.m_fraction);
00537 
00538             if (resultFraction > result.m_fraction)
00539                 resultFraction = result.m_fraction;
00540 
00541         }
00542         
00543         
00544 
00545 
00546     }
00547 
00549     {
00550         btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
00551 
00552         btSphereShape   sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
00553         btConvexCast::CastResult result;
00554         btVoronoiSimplexSolver voronoiSimplex;
00555         //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
00557         btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
00558         //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
00559         if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
00560             col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
00561         {
00562         
00563             //store result.m_fraction in both bodies
00564         
00565             if (col0->getHitFraction()  > result.m_fraction)
00566                 col0->setHitFraction( result.m_fraction);
00567 
00568             if (col1->getHitFraction() > result.m_fraction)
00569                 col1->setHitFraction( result.m_fraction);
00570 
00571             if (resultFraction > result.m_fraction)
00572                 resultFraction = result.m_fraction;
00573 
00574         }
00575     }
00576     
00577     return resultFraction;
00578 
00579 }
00580