#include "Stdafx.h" #include "EtComputeDist.h" #ifdef _DEBUG #define new new(_NORMAL_BLOCK,__FILE__,__LINE__) #endif // ÇÑ Á÷¼±°ú ÇÑ Á¡À» °¡Áö°í, CCWÀÎÁö CWÀÎÁö¸¦ ÆÇ´ÜÇÑ´Ù. À½¼ö¸é CCW. °°Àº ¼±»ó¿¡ ÀÖÀ¸¸é 0¸®ÅÏ. float CCW( EtVector2 &Line1, EtVector2 &Line2, EtVector2 &Point ) { return ((Line1.x - Point.x) * (Line2.y - Point.y)) - ((Line1.y - Point.y) * (Line2.x - Point.x)); } // ±³Â÷ÇÒ¶§¸¸ true, ±× ¿Ü ³ª¸ÓÁö °æ¿ì false bool IntrLine2DToLine2D( EtVector2 &Line1, EtVector2 &Line2, EtVector2 &Line3, EtVector2 &Line4 ) { if( (CCW(Line1, Line2, Line3) * CCW(Line1, Line2, Line4)) < 0 && (CCW(Line3, Line4, Line1) * CCW(Line3, Line4, Line2)) < 0 ) return true; return false; } // ¿ÍÀϵå¸ÅÁ÷ Äڵ带 º¸¸é DistSegmentToSegment¿¡ ´ëÀÀµÇ´Â 2D¿ë ¼±ºÐ °Å¸® °Ë»çÄڵ尡 ÀÖ±ä Çѵ¥, // Á÷°üÀûÀÎ ÄÚµå·Î Â¥º¸·Á°í, Á÷Á¢ ¸¸µé¾îº»´Ù. PressDirÀÇ °æ¿ì ÇÊ¿ä¾øÀ¸¸é »ç¿ëÇÏÁö ¾Ê¾Æµµ ¹«¹æÇÔ. float DistLine2DToLine2D( EtVector2 &Line1, EtVector2 &Line2, EtVector2 &Line3, EtVector2 &Line4, EtVector2 &PressDir ) { // µÎ ¼±ºÐÀÌ ±³Â÷Çϸé 0.0f ¸®ÅÏ if( IntrLine2DToLine2D(Line1, Line2, Line3, Line4) ) return 0.0f; else { // µÎ ¼±ºÐ °¢°¢ ¼±ºÐ°ú ¾ç ³¡Á¡ÀÇ °Å¸®¸¦ Àç¼­ °¡Àå ªÀº °ÍÀ» ¸®ÅÏ. EtVector2 vDir1, vDir2, vDir3, vDir4; float fDist1 = DistPointToLine2D( Line3, Line1, Line2, vDir1 ); float fDist2 = DistPointToLine2D( Line4, Line1, Line2, vDir2 ); // °Å¸®°¡ ªÀº °ÍÀ» ±â¾ï. if( fDist1 > fDist2 ) { vDir1 = vDir2; fDist1 = fDist2; } // Ÿ°Ù¼±ºÐ¿¡¼­ ´õ ªÀº°Ô ³ª¿Â´Ù¸é PressDirÀ» ¹Ý´ë·Î ÇØÁØ´Ù. float fDist3 = DistPointToLine2D( Line1, Line3, Line4, vDir3 ); float fDist4 = DistPointToLine2D( Line2, Line3, Line4, vDir4 ); if( fDist3 > fDist4 ) { vDir3 = vDir4; fDist3 = fDist4; } vDir3 *= -1.0f; // °Å¸®°¡ °¡Àå ªÀº °ÍÀ» ¸®ÅÏ. if( fDist1 > fDist3 ) { vDir1 = vDir3; fDist1 = fDist3; } PressDir = vDir1; return fDist1; } } float DistPointToLine2D( EtVector2 &Point, EtVector2 &Line1, EtVector2 &Line2, EtVector2 &PressDir ) { EtVector2 vDiff; EtVector2 vOrig = Line1; EtVector2 vDir = Line2 - Line1; float fDot; vDiff = Point - vOrig; fDot = EtVec2Dot( &vDir, &vDiff ); if(fDot <= 0.0f) { fDot = 0.0f; } else { float fLengthSq; fLengthSq = EtVec2LengthSq( &vDir ); if( fDot >= fLengthSq ) { fDot = 1.0f; vDiff -= vDir; } else { fDot /= fLengthSq; vDiff -= fDot * vDir; } } EtVec2Normalize( &PressDir, &vDiff ); return EtVec2Length( &vDiff ); } float DistPointToSegment( EtVector3 &Point, SSegment &Segment, float &fSegParam ) { EtVector3 Diff; Diff = Point - Segment.vOrigin; fSegParam = EtVec3Dot( &Segment.vDirection, &Diff ); if(fSegParam <= 0.0f) { fSegParam = 0.0f; } else { float fLengthSq; fLengthSq = EtVec3LengthSq( &Segment.vDirection ); if( fSegParam >= fLengthSq ) { fSegParam = 1.0f; Diff -= Segment.vDirection; } else { fSegParam /= fLengthSq; Diff -= fSegParam * Segment.vDirection; } } return EtVec3LengthSq( &Diff ); } float DistPointToOBB( EtVector3 &Point, SCollisionBox &Box, float &fBoxParam0, float &fBoxParam1, float &fBoxParam2 ) { float fSqrDistance = 0.0f; // Compute the squared distance in the box's coordinate system. EtVector3 Diff = Point - Box.vCenter, Closest; for (int i = 0; i < 3; i++) { float fDelta; Closest[ i ] = EtVec3Dot( &Diff, Box.vAxis + i ); if(Closest[ i ] < -Box.fExtent[ i ]) { fDelta = Closest[ i ] + Box.fExtent[ i ]; fSqrDistance += fDelta * fDelta; Closest[ i ] = -Box.fExtent[ i ]; } else if(Closest[ i ] > Box.fExtent[ i ]) { fDelta = Closest[ i ] - Box.fExtent[ i ]; fSqrDistance += fDelta * fDelta; Closest[ i ] = Box.fExtent[ i ]; } } fBoxParam0 = Closest[ 0 ]; fBoxParam1 = Closest[ 1 ]; fBoxParam2 = Closest[ 2 ]; return fSqrDistance; } float DistSegmentToSegment( SSegment &Segment1, SSegment &Segment2, float &fSeg0Param, float &fSeg1Param ) { const float fTolerance = 1e-06f; float fTmp; float fA, fB, fC, fD, fE, fF; EtVector3 Diff; Diff = Segment1.vOrigin - Segment2.vOrigin; fA = EtVec3Dot( &Segment1.vDirection, &Segment1.vDirection ); fB = -EtVec3Dot( &Segment1.vDirection, &Segment2.vDirection ); fC = EtVec3Dot( &Segment2.vDirection, &Segment2.vDirection ); fD = EtVec3Dot( &Segment1.vDirection, &Diff ); fE = -EtVec3Dot( &Segment2.vDirection, &Diff ); fF = EtVec3Dot( &Diff, &Diff ); // fA*fC-fB*fB = |Cross(Dir0, Dir1)|^2 >= 0 float fDet; EtVector3 Cross; fDet = fabs( fA * fC - fB * fB ); EtVec3Cross( &Cross, &Segment1.vDirection, &Segment2.vDirection ); if( EtVec3LengthSq( &Cross ) > fTolerance ) { // line segments are not parallel fSeg0Param = fB * fE - fC * fD; fSeg1Param = fB * fD - fA * fE; if( fSeg0Param >= 0 ) { if( fSeg0Param <= fDet ) { if( fSeg1Param >= 0 ) { if( fSeg1Param <= fDet ) // region 0 (interior) { // minimum at two interior points of 3D lines float fInvDet; fInvDet = 1.0f / fDet; fSeg0Param *= fInvDet; fSeg1Param *= fInvDet; return fabs( fSeg0Param * ( fA * fSeg0Param + fB * fSeg1Param + 2 * fD ) + fSeg1Param * (fB * fSeg0Param + fC * fSeg1Param + 2 * fE ) + fF); } else // region 3 (side) { fSeg1Param = 1; fTmp = fB + fD; if( fTmp >= 0 ) { fSeg0Param = 0; return fabs( fC + 2 * fE + fF ); } else if( -fTmp >= fA ) { fSeg0Param = 1; return fabs( fA + fC + fF + 2 * ( fE + fTmp ) ); } else { fSeg0Param = -fTmp / fA; return fabs( fTmp * fSeg0Param + fC + 2 * fE + fF ); } } } else // region 7 (side) { fSeg1Param = 0; if( fD >= 0 ) { fSeg0Param = 0; return fabs( fF ); } else if( -fD >= fA ) { fSeg0Param = 1; return fabs( fA + 2 * fD + fF ); } else { fSeg0Param = -fD / fA; return fabs( fD * fSeg0Param + fF ); } } } else { if( fSeg1Param >= 0 ) { if( fSeg1Param <= fDet ) // region 1 (side) { fSeg0Param = 1; fTmp = fB + fE; if( fTmp >= 0 ) { fSeg1Param = 0; return fabs( fA + 2 * fD + fF ); } else if( -fTmp >= fC ) { fSeg1Param = 1; return fabs( fA + fC + fF + 2 * ( fD + fTmp ) ); } else { fSeg1Param = -fTmp / fC; return fabs( fTmp * fSeg1Param + fA + 2 * fD + fF ); } } else // region 2 (corner) { fTmp = fB + fD; if( -fTmp <= fA ) { fSeg1Param = 1; if( fTmp >= 0 ) { fSeg0Param = 0; return fabs( fC + 2 * fE + fF ); } else { fSeg0Param = -fTmp / fA; return fabs( fTmp * fSeg0Param + fC + 2 * fE + fF ); } } else { fSeg0Param = 1; fTmp = fB + fE; if( -fTmp >= fC ) { fSeg1Param = 1; return fabs( fA + fC + fF + 2 * ( fD + fTmp ) ); } else if( fTmp > 0 ) { fSeg1Param = 0; return fabs( fA + 2 * fD + fF ); } else { fSeg1Param = -fTmp / fC; return fabs( fTmp * fSeg1Param + fA + 2 * fD + fF ); } } } } else // region 8 (corner) { if( -fD < fA ) { fSeg1Param = 0; if( fD >= 0 ) { fSeg0Param = 0; return fabs( fF ); } else { fSeg0Param = -fD / fA; return fabs( fD * fSeg0Param + fF ); } } else { fSeg0Param = 1; fTmp = fB + fE; if( fTmp >= 0 ) { fSeg1Param = 0; return fabs( fA + 2 * fD + fF ); } else if(-fTmp >= fC) { fSeg1Param = 1; return fabs( fA + fC + fF + 2 * ( fD + fTmp ) ); } else { fSeg1Param = -fTmp / fC; return fabs( fTmp * fSeg1Param + fA + 2 * fD + fF ); } } } } } else { if( fSeg1Param >= 0 ) { if( fSeg1Param <= fDet ) // region 5 (side) { fSeg0Param = 0; if( fE >= 0 ) { fSeg1Param = 0; return fabs( fF ); } else if( -fE >= fC ) { fSeg1Param = 1; return fabs( fC + 2 * fE + fF ); } else { fSeg1Param = -fE / fC; return fabs( fE * fSeg1Param + fF ); } } else // region 4 (corner) { fTmp = fB + fD; if( fTmp < 0 ) { fSeg1Param = 1; if( -fTmp >= fA ) { fSeg0Param = 1; return fabs( fA + fC + fF + 2 * ( fE + fTmp ) ); } else { fSeg0Param = -fTmp / fA; return fabs( fTmp * fSeg0Param + fC + 2 * fE + fF ); } } else { fSeg0Param = 0; fTmp = fC + fE; if( fTmp <= 0 ) { fSeg1Param = 1; return fabs( fC + 2 * fE + fF ); } else if( fE >= 0 ) { fSeg1Param = 0; return fabs( fF ); } else { fSeg1Param = -fE / fC; return fabs( fE * fSeg1Param + fF ); } } } } else // region 6 (corner) { if( fD < 0 ) { fSeg1Param = 0; if( -fD >= fA ) { fSeg0Param = 1; return fabs( fA + 2 * fD + fF ); } else { fSeg0Param = -fD / fA; return fabs( fD * fSeg0Param + fF ); } } else { fSeg0Param = 0; if( fE >= 0 ) { fSeg1Param = 0; return fabs( fF ); } else if( -fE >= fC ) { fSeg1Param = 1; return fabs( fC + 2 * fE + fF ); } else { fSeg1Param = -fE / fC; return fabs( fE * fSeg1Param + fF ); } } } } } else { // line segments are parallel if( fB > 0 ) { // direction vectors form an obtuse angle if( fD >= 0 ) { fSeg0Param = 0; fSeg1Param = 0; return fabs( fF ); } else if( -fD <= fA ) { fSeg0Param = -fD / fA; fSeg1Param = 0; return fabs( fD * fSeg0Param + fF ); } else { fSeg0Param = 1; fTmp = fA + fD; if( -fTmp >= fB ) { fSeg1Param = 1; return fabs( fA + fC + fF + 2 * ( fB + fD + fE ) ); } else { fSeg1Param = -fTmp / fB; return fabs( fA + 2 * fD + fF + fSeg1Param * ( fC * fSeg1Param + 2 * ( fB + fE ) ) ); } } } else { // direction vectors form an acute angle if( -fD >= fA ) { fSeg0Param = 1; fSeg1Param = 0; return fabs( fA + 2 * fD + fF ); } else if(fD <= 0) { fSeg0Param = -fD / fA; fSeg1Param = 0; return fabs( fD * fSeg0Param + fF ); } else { fSeg0Param = 0; if( fD >= -fB ) { fSeg1Param = 1; return fabs( fC + 2 * fE + fF ); } else { fSeg1Param = -fD / fB; return fabs( fF + fSeg1Param * ( 2 * fE + fC * fSeg1Param ) ); } } } } } float DistSegToBox( SSegment &Segment, SCollisionBox &Box, float &fSegParam, float &fBoxParam0, float &fBoxParam1, float &fBoxParam2 ) { // compute coordinates of line in box coordinate system EtVector3 Diff = Segment.vOrigin - Box.vCenter; EtVector3 DiffDotAxis, Direction; DiffDotAxis.x = EtVec3Dot( &Diff, Box.vAxis ); DiffDotAxis.y = EtVec3Dot( &Diff, Box.vAxis + 1 ); DiffDotAxis.z = EtVec3Dot( &Diff, Box.vAxis + 2 ); Direction.x = EtVec3Dot( &Segment.vDirection, Box.vAxis ); Direction.y = EtVec3Dot( &Segment.vDirection, Box.vAxis + 1 ); Direction.z = EtVec3Dot( &Segment.vDirection, Box.vAxis + 2 ); // Apply reflections so that direction vector has nonnegative components. int i; bool bReflect[ 3 ]; for ( i = 0; i < 3; i++ ) { if( Direction[ i ] < 0.0f ) { DiffDotAxis[ i ] = -DiffDotAxis[ i ]; Direction[ i ] = -Direction[ i ]; bReflect[ i ] = true; } else { bReflect[ i ] = false; } } float fSqrDistance = 0.0f; fSegParam = 0.0f; // parameter for closest point on line if( Direction.x > 0.0f ) { if( Direction.y > 0.0f ) { if( Direction.z > 0.0f ) // (+,+,+) { CaseNoZeros( Box, DiffDotAxis, Direction, fSegParam, fSqrDistance ); } else // (+,+,0) { Case0( Box, 0, 1, 2, DiffDotAxis, Direction, fSegParam, fSqrDistance ); } } else { if( Direction.z > 0.0f ) // (+,0,+) { Case0( Box, 0, 2, 1, DiffDotAxis, Direction, fSegParam, fSqrDistance ); } else // (+,0,0) { Case00( Box, 0, 1, 2, DiffDotAxis, Direction, fSegParam, fSqrDistance ); } } } else { if( Direction.y > 0.0f ) { if( Direction.z > 0.0f ) // (0,+,+) { Case0( Box, 1, 2, 0, DiffDotAxis, Direction, fSegParam, fSqrDistance ); } else // (0,+,0) { Case00( Box, 1, 0, 2, DiffDotAxis, Direction, fSegParam, fSqrDistance ); } } else { if( Direction.z > 0.0f ) // (0,0,+) { Case00( Box, 2, 0, 1, DiffDotAxis, Direction, fSegParam, fSqrDistance ); } else // (0,0,0) { Case000( Box, DiffDotAxis, fSqrDistance ); } } } if( fSegParam >= 0.0f ) { if( fSegParam <= 1.0f ) { for ( i = 0; i < 3; i++ ) { // undo the reflections applied previously if( bReflect[ i ] ) { DiffDotAxis[ i ] = -DiffDotAxis[ i ]; } } fBoxParam0 = DiffDotAxis[ 0 ]; fBoxParam1 = DiffDotAxis[ 1 ]; fBoxParam2 = DiffDotAxis[ 2 ]; } else { fSegParam = 1.0f; fSqrDistance = DistPointToOBB( Segment.vOrigin + Segment.vDirection, Box, fBoxParam0, fBoxParam1, fBoxParam2 ); } } else { fSegParam = 0.0f; fSqrDistance = DistPointToOBB( Segment.vOrigin, Box, fBoxParam0, fBoxParam1, fBoxParam2 ); } return fSqrDistance; } void Face( SCollisionBox &Box, int i0, int i1, int i2, EtVector3 &Point, EtVector3 &Direction, EtVector3 &PmE, float &fLParam, float &fSqrDistance ) { EtVector3 ExtentPoint; float fLSqr, fInv, fTmp, fParam, fT, fDelta; ExtentPoint[ i1 ] = Point[ i1 ] + Box.fExtent[ i1 ]; ExtentPoint[ i2 ] = Point[ i2 ] + Box.fExtent[ i2 ]; if( Direction[ i0 ] * ExtentPoint[ i1 ] >= Direction[ i1 ] * PmE[ i0 ] ) { if( Direction[ i0 ] * ExtentPoint[ i2 ] >= Direction[ i2 ] * PmE[ i0 ] ) { // v[ i1 ] >= -e[ i1 ], v[ i2 ] >= -e[ i2 ] (distance = 0) Point[ i0 ] = Box.fExtent[ i0 ]; fInv = 1.0f / Direction[ i0 ]; Point[ i1 ] -= Direction[ i1 ] * PmE[ i0 ] * fInv; Point[ i2 ] -= Direction[ i2 ] * PmE[ i0 ] * fInv; fLParam = -PmE[ i0 ] * fInv; } else { // v[ i1 ] >= -e[ i1 ], v[ i2 ] < -e[ i2 ] fLSqr = Direction[ i0 ] * Direction[ i0 ] + Direction[ i2 ] * Direction[ i2 ]; fTmp = fLSqr * ExtentPoint[ i1 ] - Direction[ i1 ] * (Direction[ i0 ] * PmE[ i0 ] + Direction[ i2 ] * ExtentPoint[ i2 ]); if( fTmp <= 2.0f * fLSqr * Box.fExtent[ i1 ] ) { fT = fTmp / fLSqr; fLSqr += Direction[ i1 ] * Direction[ i1 ]; fTmp = ExtentPoint[ i1 ] - fT; fDelta = Direction[ i0 ] * PmE[ i0 ] + Direction[ i1 ] * fTmp + Direction[ i2 ] * ExtentPoint[ i2 ]; fParam = -fDelta / fLSqr; fSqrDistance += PmE[ i0 ] * PmE[ i0 ] + fTmp * fTmp + ExtentPoint[ i2 ] * ExtentPoint[ i2 ] + fDelta * fParam; fLParam = fParam; Point[ i0 ] = Box.fExtent[ i0 ]; Point[ i1 ] = fT - Box.fExtent[ i1 ]; Point[ i2 ] = -Box.fExtent[ i2 ]; } else { fLSqr += Direction[ i1 ] * Direction[ i1 ]; fDelta = Direction[ i0 ] * PmE[ i0 ] + Direction[ i1 ] * PmE[ i1 ] + Direction[ i2 ] * ExtentPoint[ i2 ]; fParam = -fDelta / fLSqr; fSqrDistance += PmE[ i0 ] * PmE[ i0 ] + PmE[ i1 ] * PmE[ i1 ] + ExtentPoint[ i2 ] * ExtentPoint[ i2 ] + fDelta * fParam; fLParam = fParam; Point[ i0 ] = Box.fExtent[ i0 ]; Point[ i1 ] = Box.fExtent[ i1 ]; Point[ i2 ] = -Box.fExtent[ i2 ]; } } } else { if( Direction[ i0 ] * ExtentPoint[ i2 ] >= Direction[ i2 ] * PmE[ i0 ] ) { // v[ i1 ] < -e[ i1 ], v[ i2 ] >= -e[ i2 ] fLSqr = Direction[ i0 ] * Direction[ i0 ] + Direction[ i1 ] * Direction[ i1 ]; fTmp = fLSqr * ExtentPoint[ i2 ] - Direction[ i2 ] * (Direction[ i0 ] * PmE[ i0 ] + Direction[ i1 ] * ExtentPoint[ i1 ]); if( fTmp <= 2.0f * fLSqr * Box.fExtent[ i2 ] ) { fT = fTmp / fLSqr; fLSqr += Direction[ i2 ] * Direction[ i2 ]; fTmp = ExtentPoint[ i2 ] - fT; fDelta = Direction[ i0 ] * PmE[ i0 ] + Direction[ i1 ] * ExtentPoint[ i1 ] + Direction[ i2 ] * fTmp; fParam = -fDelta / fLSqr; fSqrDistance += PmE[ i0 ] * PmE[ i0 ] + ExtentPoint[ i1 ] * ExtentPoint[ i1 ] + fTmp * fTmp + fDelta * fParam; fLParam = fParam; Point[ i0 ] = Box.fExtent[ i0 ]; Point[ i1 ] = -Box.fExtent[ i1 ]; Point[ i2 ] = fT - Box.fExtent[ i2 ]; } else { fLSqr += Direction[ i2 ] * Direction[ i2 ]; fDelta = Direction[ i0 ] * PmE[ i0 ] + Direction[ i1 ] * ExtentPoint[ i1 ] + Direction[ i2 ] * PmE[ i2 ]; fParam = -fDelta / fLSqr; fSqrDistance += PmE[ i0 ] * PmE[ i0 ] + ExtentPoint[ i1 ] * ExtentPoint[ i1 ] + PmE[ i2 ] * PmE[ i2 ] + fDelta * fParam; fLParam = fParam; Point[ i0 ] = Box.fExtent[ i0 ]; Point[ i1 ] = -Box.fExtent[ i1 ]; Point[ i2 ] = Box.fExtent[ i2 ]; } } else { // v[ i1 ] < -e[ i1 ], v[ i2 ] < -e[ i2 ] fLSqr = Direction[ i0 ] * Direction[ i0 ]+Direction[ i2 ] * Direction[ i2 ]; fTmp = fLSqr * ExtentPoint[ i1 ] - Direction[ i1 ] * (Direction[ i0 ] * PmE[ i0 ] + Direction[ i2 ] * ExtentPoint[ i2 ]); if( fTmp >= (float)0.0 ) { // v[ i1 ]-edge is closest if( fTmp <= 2.0f * fLSqr * Box.fExtent[ i1 ] ) { fT = fTmp / fLSqr; fLSqr += Direction[ i1 ] * Direction[ i1 ]; fTmp = ExtentPoint[ i1 ] - fT; fDelta = Direction[ i0 ] * PmE[ i0 ] + Direction[ i1 ] * fTmp + Direction[ i2 ] * ExtentPoint[ i2 ]; fParam = -fDelta / fLSqr; fSqrDistance += PmE[ i0 ] * PmE[ i0 ] + fTmp * fTmp + ExtentPoint[ i2 ] * ExtentPoint[ i2 ] + fDelta * fParam; fLParam = fParam; Point[ i0 ] = Box.fExtent[ i0 ]; Point[ i1 ] = fT - Box.fExtent[ i1 ]; Point[ i2 ] = -Box.fExtent[ i2 ]; } else { fLSqr += Direction[ i1 ] * Direction[ i1 ]; fDelta = Direction[ i0 ] * PmE[ i0 ] + Direction[ i1 ] * PmE[ i1 ] + Direction[ i2 ] * ExtentPoint[ i2 ]; fParam = -fDelta / fLSqr; fSqrDistance += PmE[ i0 ] * PmE[ i0 ] + PmE[ i1 ] * PmE[ i1 ] + ExtentPoint[ i2 ] * ExtentPoint[ i2 ] + fDelta * fParam; fLParam = fParam; Point[ i0 ] = Box.fExtent[ i0 ]; Point[ i1 ] = Box.fExtent[ i1 ]; Point[ i2 ] = -Box.fExtent[ i2 ]; } return; } fLSqr = Direction[ i0 ] * Direction[ i0 ] + Direction[ i1 ] * Direction[ i1 ]; fTmp = fLSqr * ExtentPoint[ i2 ] - Direction[ i2 ] * (Direction[ i0 ] * PmE[ i0 ] + Direction[ i1 ] * ExtentPoint[ i1 ]); if( fTmp >= 0.0f ) { // v[ i2 ]-edge is closest if( fTmp <= 2.0f * fLSqr * Box.fExtent[ i2 ] ) { fT = fTmp / fLSqr; fLSqr += Direction[ i2 ] * Direction[ i2 ]; fTmp = ExtentPoint[ i2 ] - fT; fDelta = Direction[ i0 ] * PmE[ i0 ] + Direction[ i1 ] * ExtentPoint[ i1 ] + Direction[ i2 ] * fTmp; fParam = -fDelta / fLSqr; fSqrDistance += PmE[ i0 ] * PmE[ i0 ] + ExtentPoint[ i1 ] * ExtentPoint[ i1 ] + fTmp * fTmp + fDelta * fParam; fLParam = fParam; Point[ i0 ] = Box.fExtent[ i0 ]; Point[ i1 ] = -Box.fExtent[ i1 ]; Point[ i2 ] = fT - Box.fExtent[ i2 ]; } else { fLSqr += Direction[ i2 ] * Direction[ i2 ]; fDelta = Direction[ i0 ] * PmE[ i0 ] + Direction[ i1 ] * ExtentPoint[ i1 ] + Direction[ i2 ] * PmE[ i2 ]; fParam = -fDelta / fLSqr; fSqrDistance += PmE[ i0 ] * PmE[ i0 ] + ExtentPoint[ i1 ] * ExtentPoint[ i1 ] + PmE[ i2 ] * PmE[ i2 ] + fDelta * fParam; fLParam = fParam; Point[ i0 ] = Box.fExtent[ i0 ]; Point[ i1 ] = -Box.fExtent[ i1 ]; Point[ i2 ] = Box.fExtent[ i2 ]; } return; } // (v[ i1 ],v[ i2 ])-corner is closest fLSqr += Direction[ i2 ] * Direction[ i2 ]; fDelta = Direction[ i0 ] * PmE[ i0 ] + Direction[ i1 ] * ExtentPoint[ i1 ] + Direction[ i2 ] * ExtentPoint[ i2 ]; fParam = -fDelta / fLSqr; fSqrDistance += PmE[ i0 ] * PmE[ i0 ] + ExtentPoint[ i1 ] * ExtentPoint[ i1 ] + ExtentPoint[ i2 ] * ExtentPoint[ i2 ] + fDelta * fParam; fLParam = fParam; Point[ i0 ] = Box.fExtent[ i0 ]; Point[ i1 ] = -Box.fExtent[ i1 ]; Point[ i2 ] = -Box.fExtent[ i2 ]; } } } void CaseNoZeros( SCollisionBox &Box, EtVector3 &Point, EtVector3 &Direction, float &fLParam, float &fSqrDistance ) { EtVector3 PmE; PmE.x = Point.x - Box.fExtent[ 0 ]; PmE.y = Point.y - Box.fExtent[ 1 ]; PmE.z = Point.z - Box.fExtent[ 2 ]; float fProdDxPy = Direction.x * PmE.y; float fProdDyPx = Direction.y * PmE.x; float fProdDzPx, fProdDxPz, fProdDzPy, fProdDyPz; if( fProdDyPx >= fProdDxPy ) { fProdDzPx = Direction.z * PmE.x; fProdDxPz = Direction.x * PmE.z; if( fProdDzPx >= fProdDxPz ) { // line intersects x = e0 Face( Box, 0, 1, 2, Point, Direction, PmE, fLParam, fSqrDistance ); } else { // line intersects z = e2 Face( Box, 2, 0, 1, Point, Direction, PmE, fLParam, fSqrDistance ); } } else { fProdDzPy = Direction.z * PmE.y; fProdDyPz = Direction.y * PmE.z; if( fProdDzPy >= fProdDyPz ) { // line intersects y = e1 Face( Box, 1, 2, 0, Point, Direction, PmE, fLParam, fSqrDistance ); } else { // line intersects z = e2 Face( Box, 2, 0, 1, Point, Direction, PmE, fLParam, fSqrDistance ); } } } void Case0( SCollisionBox &Box, int i0, int i1, int i2, EtVector3 &Point, EtVector3 &Direction, float &fLParam, float &fSqrDistance ) { float fPmE0 = Point[ i0 ] - Box.fExtent[ i0 ]; float fPmE1 = Point[ i1 ] - Box.fExtent[ i1 ]; float fProd0 = Direction[ i1 ] * fPmE0; float fProd1 = Direction[ i0 ] * fPmE1; float fDelta, fInvLSqr, fInv; if( fProd0 >= fProd1 ) { // line intersects P[ i0 ] = e[ i0 ] Point[ i0 ] = Box.fExtent[ i0 ]; float fPpE1 = Point[ i1 ] + Box.fExtent[ i1 ]; fDelta = fProd0 - Direction[ i0 ] * fPpE1; if( fDelta >= 0.0f ) { fInvLSqr = 1.0f / ( Direction[ i0 ] * Direction[ i0 ]+Direction[ i1 ] * Direction[ i1 ] ); fSqrDistance += fDelta * fDelta * fInvLSqr; Point[ i1 ] = -Box.fExtent[ i1 ]; fLParam = -( Direction[ i0 ] * fPmE0+Direction[ i1 ] * fPpE1 ) * fInvLSqr; } else { fInv = 1.0f / Direction[ i0 ]; Point[ i1 ] -= fProd0 * fInv; fLParam = -fPmE0 * fInv; } } else { // line intersects P[ i1 ] = e[ i1 ] Point[ i1 ] = Box.fExtent[ i1 ]; float fPpE0 = Point[ i0 ] + Box.fExtent[ i0 ]; fDelta = fProd1 - Direction[ i1 ] * fPpE0; if( fDelta >= 0.0f ) { fInvLSqr = 1.0f / ( Direction[ i0 ] * Direction[ i0 ]+Direction[ i1 ] * Direction[ i1 ] ); fSqrDistance += fDelta * fDelta * fInvLSqr; Point[ i0 ] = -Box.fExtent[ i0 ]; fLParam = -( Direction[ i0 ] * fPpE0+Direction[ i1 ] * fPmE1 ) * fInvLSqr; } else { fInv = ( 1.0f ) / Direction[ i1 ]; Point[ i0 ] -= fProd1 * fInv; fLParam = -fPmE1 * fInv; } } if( Point[ i2 ] < -Box.fExtent[ i2 ] ) { fDelta = Point[ i2 ] + Box.fExtent[ i2 ]; fSqrDistance += fDelta * fDelta; Point[ i2 ] = -Box.fExtent[ i2 ]; } else if( Point[ i2 ] > Box.fExtent[ i2 ] ) { fDelta = Point[ i2 ] - Box.fExtent[ i2 ]; fSqrDistance += fDelta * fDelta; Point[ i2 ] = Box.fExtent[ i2 ]; } } void Case00( SCollisionBox &Box, int i0, int i1, int i2, EtVector3 &Point, EtVector3 &Direction, float &fLParam, float &fSqrDistance ) { float fDelta; fLParam = ( Box.fExtent[ i0 ] - Point[ i0 ] ) / Direction[ i0 ]; Point[ i0 ] = Box.fExtent[ i0 ]; if( Point[ i1 ] < -Box.fExtent[ i1 ] ) { fDelta = Point[ i1 ] + Box.fExtent[ i1 ]; fSqrDistance += fDelta * fDelta; Point[ i1 ] = -Box.fExtent[ i1 ]; } else if( Point[ i1 ] > Box.fExtent[ i1 ] ) { fDelta = Point[ i1 ] - Box.fExtent[ i1 ]; fSqrDistance += fDelta * fDelta; Point[ i1 ] = Box.fExtent[ i1 ]; } if( Point[ i2 ] < -Box.fExtent[ i2 ] ) { fDelta = Point[ i2 ] + Box.fExtent[ i2 ]; fSqrDistance += fDelta * fDelta; Point[ i2 ] = -Box.fExtent[ i2 ]; } else if( Point[ i2 ] > Box.fExtent[ i2 ] ) { fDelta = Point[ i2 ] - Box.fExtent[ i2 ]; fSqrDistance += fDelta * fDelta; Point[ i2 ] = Box.fExtent[ i2 ]; } } void Case000( SCollisionBox &Box, EtVector3 &Point, float &fSqrDistance ) { float fDelta; if( Point.x < -Box.fExtent[ 0 ] ) { fDelta = Point.x + Box.fExtent[ 0 ]; fSqrDistance += fDelta * fDelta; Point.x = -Box.fExtent[ 0 ]; } else if( Point.x > Box.fExtent[ 0 ] ) { fDelta = Point.x - Box.fExtent[ 0 ]; fSqrDistance += fDelta * fDelta; Point.x = Box.fExtent[ 0 ]; } if( Point.y < -Box.fExtent[ 1 ] ) { fDelta = Point.y + Box.fExtent[ 1 ]; fSqrDistance += fDelta * fDelta; Point.y = -Box.fExtent[ 1 ]; } else if( Point.y > Box.fExtent[ 1 ] ) { fDelta = Point.y - Box.fExtent[ 1 ]; fSqrDistance += fDelta * fDelta; Point.y = Box.fExtent[ 1 ]; } if( Point.z < -Box.fExtent[ 2 ] ) { fDelta = Point.z + Box.fExtent[ 2 ]; fSqrDistance += fDelta * fDelta; Point.z = -Box.fExtent[ 2 ]; } else if( Point.z > Box.fExtent[ 2 ] ) { fDelta = Point.z - Box.fExtent[ 2 ]; fSqrDistance += fDelta * fDelta; Point.z = Box.fExtent[ 2 ]; } } #define COMPARE_MIN( fTmpMinD, fMinD, fTmpSeg, fSeg, fTmpTri0, fTri0, fTmpTri1, fTri1 ) \ { \ if( fTmpMinD < fMinD ) \ { \ fMinD = fTmpMinD; \ fSeg = fTmpSeg; \ fTri0 = fTmpTri0; \ fTri1 = fTmpTri1; \ } \ } float DistPointToTriangle( EtVector3 &vPoint, SCollisionTriangle &Triangle, float &fTriParam0, float &fTriParam1 ) { EtVector3 vDiff = Triangle.vOrigin - vPoint; float fA = EtVec3Dot( &Triangle.vEdge1, &Triangle.vEdge1 ); float fB = EtVec3Dot( &Triangle.vEdge1, &Triangle.vEdge2 ); float fC = EtVec3Dot( &Triangle.vEdge2, &Triangle.vEdge2 ); float fD = EtVec3Dot( &vDiff, &Triangle.vEdge1 ); float fE = EtVec3Dot( &vDiff, &Triangle.vEdge2 ); float fF = EtVec3Dot( &vDiff, &vDiff ); float fDet = fabs( fA * fC - fB * fB ); fTriParam0 = fB * fE - fC * fD; fTriParam1 = fB * fD - fA * fE; if( fTriParam0 + fTriParam1 <= fDet ) { if( fTriParam0 < 0.0f ) { if( fTriParam1 < 0.0f ) // region 4 { if( fD < 0.0f ) { fTriParam1 = 0.0f; if( -fD >= fA ) { fTriParam0 = 1.0f; return fabs( fA + 2.0f * fD + fF ); } else { fTriParam0 = -fD / fA; return fabs( fD * fTriParam0 + fF ); } } else { fTriParam0 = 0.0f; if( fE >= 0.0f ) { fTriParam1 = 0.0f; return fabs(fF); } else if( -fE >= fC ) { fTriParam1 = 1.0f; return fabs( fC + 2.0f * fE + fF ); } else { fTriParam1 = -fE / fC; return fabs( fE * fTriParam1 + fF ); } } } else // region 3 { fTriParam0 = 0.0f; if( fE >= 0.0f ) { fTriParam1 = 0.0f; return fabs( fF ); } else if( -fE >= fC ) { fTriParam1 = 1.0f; return fabs( fC + 2.0f * fE + fF ); } else { fTriParam1 = -fE / fC; return fabs( fE * fTriParam1 + fF ); } } } else if( fTriParam1 < 0.0f ) // region 5 { fTriParam1 = 0.0f; if( fD >= 0.0f ) { fTriParam0 = 0.0f; return fabs( fF ); } else if( -fD >= fA ) { fTriParam0 = 1.0f; return fabs( fA + 2.0f * fD + fF ); } else { fTriParam0 = -fD / fA; return fabs( fD * fTriParam0 + fF ); } } else // region 0 { // minimum at interior point float fInvDet = 1.0f / fDet; fTriParam0 *= fInvDet; fTriParam1 *= fInvDet; return fabs( fTriParam0 * ( fA * fTriParam0 + fB * fTriParam1 + 2 * fD ) + fTriParam1 * ( fB * fTriParam0 + fC * fTriParam1 + 2 * fE ) + fF ); } } else { float fTmp0; float fTmp1; float fNumer; float fDenom; if( fTriParam0 < 0.0f ) // region 2 { fTmp0 = fB + fD; fTmp1 = fC + fE; if( fTmp1 > fTmp0 ) { fNumer = fTmp1 - fTmp0; fDenom = fA - 2.0f * fB + fC; if( fNumer >= fDenom ) { fTriParam0 = 1.0f; fTriParam1 = 0.0f; return fabs( fA + 2.0f * fD + fF ); } else { fTriParam0 = fNumer / fDenom; fTriParam1 = 1.0f - fTriParam0; return fabs( fC + 2.0f * fE + fF - fNumer * fTriParam0 ); } } else { fTriParam0 = 0.0f; if( fTmp1 <= 0.0f ) { fTriParam1 = 1.0f; return fabs( fC + 2.0f * fE + fF ); } else if( fE >= 0.0f ) { fTriParam1 = 0.0f; return fabs( fF ); } else { fTriParam1 = -fE / fC; return fabs( fE * fTriParam1 + fF ); } } } else if( fTriParam1 < 0.0f ) // region 6 { fTmp0 = fB + fE; fTmp1 = fA + fD; if( fTmp1 > fTmp0 ) { fNumer = fTmp1 - fTmp0; fDenom = fA - 2.0f * fB + fC; if( fNumer >= fDenom ) { fTriParam1 = 1.0f; fTriParam0 = 0.0f; return fabs( fC + 2.0f * fE + fF ); } else { fTriParam1 = fNumer / fDenom; fTriParam0 = 1.0f - fTriParam1; return fabs( fA + 2.0f * fD + fF - fNumer * fTriParam1 ); } } else { fTriParam1 = 0.0f; if( fTmp1 <= 0.0f ) { fTriParam0 = 1.0f; return fabs( fA + 2.0f * fD + fF ); } else if( fD >= 0.0f ) { fTriParam0 = 0.0f; return fabs( fF ); } else { fTriParam0 = -fD / fA; return fabs( fD * fTriParam0 + fF ); } } } else // region 1 { fNumer = ( fC + fE ) - ( fB + fD ); if(fNumer <= 0) { fTriParam0 = 0.0f; fTriParam1 = 1.0f; return fabs( fC + 2.0f * fE + fF ); } else { fDenom = fA - 2.0f * fB + fC; if( fNumer >= fDenom ) { fTriParam0 = 1.0f; fTriParam1 = 0.0f; return fabs( fA + 2.0f * fD + fF ); } else { fTriParam0 = fNumer / fDenom; fTriParam1 = 1.0f - fTriParam0; return fabs( fC + 2.0f * fE + fF - fNumer * fTriParam0 ); } } } } } float DistSegmentToTriangle( SSegment &Segment, SCollisionTriangle &Triangle, float &fSegParm, float &fTriParm0, float &fTriParm1 ) { const float fTolerance = 1e-05f; SSegment TriangleSeg; EtVector3 vPoint; float fMin, fMin0, fTmpSegParm, fTmpTriParm0, fTmpTriParm1; EtVector3 vDiff = Triangle.vOrigin - Segment.vOrigin; float fA00 = EtVec3Dot( &Segment.vDirection, &Segment.vDirection ); float fA01 = -EtVec3Dot( &Segment.vDirection, &Triangle.vEdge1 ); float fA02 = -EtVec3Dot( &Segment.vDirection, &Triangle.vEdge2 ); float fA11 = EtVec3Dot( &Triangle.vEdge1, &Triangle.vEdge1 ); float fA12 = EtVec3Dot( &Triangle.vEdge1, &Triangle.vEdge2 ); float fA22 = EtVec3Dot( &Triangle.vEdge2, &Triangle.vEdge2 ); float fB0 = -EtVec3Dot( &vDiff, &Segment.vDirection ); float fB1 = EtVec3Dot( &vDiff, &Triangle.vEdge1 ); float fB2 = EtVec3Dot( &vDiff, &Triangle.vEdge2 ); EtVector3 vPlaneNormal; EtVec3Cross( &vPlaneNormal, &Triangle.vEdge1, &Triangle.vEdge2 ); if( fabs( EtVec3Dot( &vPlaneNormal, &Segment.vDirection ) ) > ( fTolerance * ( EtVec3Length( &vPlaneNormal ) * EtVec3Length( &Segment.vDirection ) ) ) ) { float fCof00 = fA11 * fA22 - fA12 * fA12; float fCof01 = fA02 * fA12 - fA01 * fA22; float fCof02 = fA01 * fA12 - fA02 * fA11; float fCof11 = fA00 * fA22 - fA02 * fA02; float fCof12 = fA02 * fA01 - fA00 * fA12; float fCof22 = fA00 * fA11 - fA01 * fA01; float fDet = fA00 * fCof00 + fA01 * fCof01 + fA02 * fCof02; float fInvDet = 1.0f / fDet; float fRhs0 = -fB0 * fInvDet; float fRhs1 = -fB1 * fInvDet; float fRhs2 = -fB2 * fInvDet; fSegParm = fCof00 * fRhs0 + fCof01 * fRhs1 + fCof02 * fRhs2; fTriParm0 = fCof01 * fRhs0 + fCof11 * fRhs1 + fCof12 * fRhs2; fTriParm1 = fCof02 * fRhs0 + fCof12 * fRhs1 + fCof22 * fRhs2; if( fSegParm < 0.0f ) { if( fTriParm0 + fTriParm1 <= 1.0f ) { if( fTriParm0 < 0.0f ) { if( fTriParm1 < 0.0f ) { TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge2; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 0.0f; TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge1; fMin0 = DistSegmentToSegment( Segment, TriangleSeg, fTmpSegParm, fTmpTriParm0 ); fTmpTriParm1 = 0.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); fMin0 = DistPointToTriangle( Segment.vOrigin, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 0.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } else { TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge2; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 0.0f; fMin0 = DistPointToTriangle( Segment.vOrigin, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 0.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } } else if( fTriParm1 < 0.0f ) { // min on face TP1=0 or SP=0 TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge1; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm0 ); fTriParm1 = 0.0f; fMin0 = DistPointToTriangle( Segment.vOrigin, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 0.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } else // region 0m, min face on SP=0 { fMin = DistPointToTriangle( Segment.vOrigin, Triangle, fTriParm0, fTriParm1) ; fSegParm = 0.0f; } } else { if( fTriParm0 < 0.0f ) // region 2m { // min on face TP0=0 or TP0+TP1=1 or SP=0 TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge2; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 0.0f; TriangleSeg.vOrigin = Triangle.vOrigin + Triangle.vEdge1; TriangleSeg.vDirection = Triangle.vEdge2-Triangle.vEdge1; fMin0 = DistSegmentToSegment( Segment, TriangleSeg, fTmpSegParm, fTmpTriParm1); fTmpTriParm0 = 1.0f - fTmpTriParm1; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); fMin0 = DistPointToTriangle( Segment.vOrigin, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 0.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } else if(fTriParm1 < 0.0f) // region 6m { // min on face TP1=0 or TP0+TP1=1 or SP=0 TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge1; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm0 ); fTriParm1 = 0.0f; TriangleSeg.vOrigin = Triangle.vOrigin + Triangle.vEdge1; TriangleSeg.vDirection = Triangle.vEdge2-Triangle.vEdge1; fMin0 = DistSegmentToSegment( Segment, TriangleSeg, fTmpSegParm, fTmpTriParm1 ); fTmpTriParm0 = 1.0f - fTmpTriParm1; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); fMin0 = DistPointToTriangle( Segment.vOrigin, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 0.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } else // region 1m, min on face TP0+TP1=1 or SP=0 { TriangleSeg.vOrigin = Triangle.vOrigin + Triangle.vEdge1; TriangleSeg.vDirection = Triangle.vEdge2-Triangle.vEdge1; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 1.0f - fTriParm1; fMin0 = DistPointToTriangle( Segment.vOrigin, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 0.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } } } else if( fSegParm <= 1.0f ) { if( fTriParm0 + fTriParm1 <= 1.0f ) { if( fTriParm0 < 0.0f ) { if( fTriParm1 < 0.0f ) // region 4 { // min on face TP0=0 or TP1=0 TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge2; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 0.0f; TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge1; fMin0 = DistSegmentToSegment( Segment, TriangleSeg, fTmpSegParm, fTmpTriParm0) ; fTmpTriParm1 = 0.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } else // region 3, min on face TP0=0 { TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge2; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 0.0f; } } else if( fTriParm1 < 0.0f ) // region 5, min on face TP1=0 { TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge1; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm0 ); fTriParm1 = 0.0f; } else // region 0, global minimum is interior, so done { fMin = 0.0f; } } else { if( fTriParm0 < 0.0f ) // region 2 { // min on face TP0=0 or TP0+TP1=1 TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge2; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 0.0f; TriangleSeg.vOrigin = Triangle.vOrigin + Triangle.vEdge1; TriangleSeg.vDirection = Triangle.vEdge2 - Triangle.vEdge1; fMin0 = DistSegmentToSegment( Segment, TriangleSeg, fTmpSegParm, fTmpTriParm1 ); fTmpTriParm0 = 1.0f - fTmpTriParm1; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } else if(fTriParm1 < 0.0f) // region 6 { // min on face TP1=0 or TP0+TP1=1 TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge1; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm0 ); fTriParm1 = 0.0f; TriangleSeg.vOrigin = Triangle.vOrigin + Triangle.vEdge1; TriangleSeg.vDirection = Triangle.vEdge2 - Triangle.vEdge1; fMin0 = DistSegmentToSegment( Segment, TriangleSeg, fTmpSegParm, fTmpTriParm1 ); fTmpTriParm0 = 1.0f - fTmpTriParm1; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } else // region 1, min on face TP0+TP1=1 { TriangleSeg.vOrigin = Triangle.vOrigin + Triangle.vEdge1; TriangleSeg.vDirection = Triangle.vEdge2 - Triangle.vEdge1; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 1.0f - fTriParm1; } } } else // fSegParm > 1 { if( fTriParm0 + fTriParm1 <= 1.0f ) { if( fTriParm0 < 0.0f ) { if( fTriParm1 < 0.0f ) // region 4p { // min on face TP0=0 or TP1=0 or SP=1 TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge2; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 0.0f; TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge1; fMin0 = DistSegmentToSegment( Segment, TriangleSeg, fTmpSegParm, fTmpTriParm0 ); fTmpTriParm1 = 0.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); vPoint = Segment.vOrigin + Segment.vDirection; fMin0 = DistPointToTriangle( vPoint, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 1.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } else // region 3p, min on face TP0=0 or SP=1 { TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge2; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 0.0f; vPoint = Segment.vOrigin + Segment.vDirection; fMin0 = DistPointToTriangle( vPoint, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 1.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } } else if( fTriParm1 < 0.0f ) // region 5p { // min on face TP1=0 or SP=1 TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge1; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm0 ); fTriParm1 = 0.0f; vPoint = Segment.vOrigin + Segment.vDirection; fMin0 = DistPointToTriangle( vPoint, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 1.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } else // region 0p, min face on SP=1 { vPoint = Segment.vOrigin + Segment.vDirection; fMin = DistPointToTriangle( vPoint, Triangle, fTriParm0, fTriParm1 ); fSegParm = 1.0f; } } else { if( fTriParm0 < 0.0f ) // region 2p { // min on face TP0=0 or TP0+TP1=1 or SP=1 TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge2; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 0.0f; TriangleSeg.vOrigin = Triangle.vOrigin + Triangle.vEdge1; TriangleSeg.vDirection = Triangle.vEdge2 - Triangle.vEdge1; fMin0 = DistSegmentToSegment( Segment, TriangleSeg, fTmpSegParm, fTmpTriParm1 ); fTmpTriParm0 = 1.0f - fTmpTriParm1; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); vPoint = Segment.vOrigin + Segment.vDirection; fMin0 = DistPointToTriangle( vPoint, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 1.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } else if( fTriParm1 < 0.0f ) // region 6p { // min on face TP1=0 or TP0+TP1=1 or SP=1 TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge1; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm0 ); fTriParm1 = 0.0f; TriangleSeg.vOrigin = Triangle.vOrigin + Triangle.vEdge1; TriangleSeg.vDirection = Triangle.vEdge2 - Triangle.vEdge1; fMin0 = DistSegmentToSegment( Segment, TriangleSeg, fTmpSegParm, fTmpTriParm1 ); fTmpTriParm0 = 1.0f - fTmpTriParm1; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); vPoint = Segment.vOrigin + Segment.vDirection; fMin0 = DistPointToTriangle( vPoint, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 1.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } else // region 1p, min on face TP0+TP1=1 or SP=1 { TriangleSeg.vOrigin = Triangle.vOrigin + Triangle.vEdge1; TriangleSeg.vDirection = Triangle.vEdge2 - Triangle.vEdge1; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm1 ); fTriParm0 = 1.0f - fTriParm1; vPoint = Segment.vOrigin + Segment.vDirection; fMin0 = DistPointToTriangle( vPoint, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 1.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); } } } return fMin; } // Segment and triangle are parallel. TriangleSeg.vOrigin = Triangle.vOrigin; TriangleSeg.vDirection = Triangle.vEdge1; fMin = DistSegmentToSegment( Segment, TriangleSeg, fSegParm, fTriParm0 ); fTriParm1 = 0.0f; TriangleSeg.vDirection = Triangle.vEdge2; fMin0 = DistSegmentToSegment( Segment, TriangleSeg, fTmpSegParm, fTmpTriParm1 ); fTmpTriParm0 = 0.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); TriangleSeg.vOrigin = TriangleSeg.vOrigin + Triangle.vEdge1; TriangleSeg.vDirection = TriangleSeg.vDirection - Triangle.vEdge1; fMin0 = DistSegmentToSegment( Segment, TriangleSeg, fTmpSegParm, fTmpTriParm1 ); fTmpTriParm0 = 1.0f - fTmpTriParm1; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); fMin0 = DistPointToTriangle( Segment.vOrigin, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 0.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); vPoint = Segment.vOrigin + Segment.vDirection; fMin0 = DistPointToTriangle( vPoint, Triangle, fTmpTriParm0, fTmpTriParm1 ); fTmpSegParm = 1.0f; COMPARE_MIN( fMin0, fMin, fTmpSegParm, fSegParm, fTmpTriParm0, fTriParm0, fTmpTriParm1, fTriParm1 ); return fMin; }