/* 0 1 2 3 4 5 6 7 01234567890123456789012345678901234567890123456789012345678901234567890123456789 -------------------------------------------------------------------------------- -- Description : Low level intersection -------------------------------------------------------------------------------- -- Creation date : 22 aug 1996 Author : FPI -------------------------------------------------------------------------------- */ #include "acp_base.h" #include "MTH.h" #include "MEC.h" #include "GMT.h" #include "GEO.h" #include "GLI.h" #include "COL/Inters.h" #include "tmr.h" #ifdef CODEWARRIOR #include "COL/futil.h" #endif /* XB 05/05/99 : add static */ static unsigned char ucPlaneCrossingdetect(MTH3D_tdstVector *p_stVertex1, /* End XB 05/05/99 */ MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint, MTH_tdxReal xT, char cFace); /* -------------------------------------------------------------------------------- -- Description : Trinome resolution -------------------------------------------------------------------------------- -- Creation date : 01 oct 1996 Author : FPI -------------------------------------------------------------------------------- */ /* resolution d un trinome */ /* used*/ ACP_tdxIndex INT_fn_xTrinomeResolution ( MTH_tdxReal xA, MTH_tdxReal xB, MTH_tdxReal xC, MTH_tdxReal *p_xT1, MTH_tdxReal *p_xT2 ) { MTH_tdxReal xDelta; MTH_tdxReal xDiv; if ( MTH_M_bDifferentZero ( xA ) ) { xDelta = MTH_M_xTrinomeDelta ( xA, xB, xC ); if ( MTH_M_bGreaterZero ( xDelta ) ) { xDelta = MTH_M_xSqrt ( xDelta ); xB = MTH_M_xNeg ( xB ); xDiv = MTH_M_xInv ( MTH_M_xAdd ( xA, xA ) ); *p_xT1 = MTH_M_xMul ( MTH_M_xAdd (xB, xDelta ), xDiv ); *p_xT2 = MTH_M_xMul ( MTH_M_xSub (xB, xDelta ), xDiv ); return INT_C_xTwoSolutions; } else { if ( MTH_M_bLessZero ( xDelta ) ) { return INT_C_xNoSolution; } else { if ( MTH_M_bEqualZero ( xDelta ) ) { *p_xT1 = MTH_M_xNeg ( MTH_M_xDiv ( xB, MTH_M_xAdd ( xA, xA ) ) ); return INT_C_xOneSolution; } } } } else { if ( MTH_M_bDifferentZero ( xB ) ) { *p_xT1 = MTH_M_xNeg ( MTH_M_xDiv ( xC, xB ) ); return INT_C_xOneSolution; } else { return INT_C_xNoSolution; } } return INT_C_xNoSolution; } /* -------------------------------------------------------------------------------- -- Description : Box with a box intersection test -------------------------------------------------------------------------------- -- Creation date : 22 aug 1996 Author : FPI -------------------------------------------------------------------------------- */ /* teste l intersection de deux boites */ /* used*/ ACP_tdxBool INT_fn_bIntersectBoxWithBox ( MTH3D_tdstVector *p_stMinPoint1, MTH3D_tdstVector *p_stMaxPoint1, MTH3D_tdstVector *p_stMinPoint2, MTH3D_tdstVector *p_stMaxPoint2 ) { return ( MTH_M_bLessEqual ( MTH_M_xMax ( MTH3D_M_xGetXofVector ( p_stMinPoint1 ), MTH3D_M_xGetXofVector ( p_stMinPoint2 ) ), MTH_M_xMin ( MTH3D_M_xGetXofVector ( p_stMaxPoint1 ), MTH3D_M_xGetXofVector ( p_stMaxPoint2 ) ) ) ) && ( MTH_M_bLessEqual ( MTH_M_xMax ( MTH3D_M_xGetYofVector ( p_stMinPoint1 ), MTH3D_M_xGetYofVector ( p_stMinPoint2 ) ), MTH_M_xMin ( MTH3D_M_xGetYofVector ( p_stMaxPoint1 ), MTH3D_M_xGetYofVector ( p_stMaxPoint2 ) ) ) ) && ( MTH_M_bLessEqual ( MTH_M_xMax ( MTH3D_M_xGetZofVector ( p_stMinPoint1 ), MTH3D_M_xGetZofVector ( p_stMinPoint2 ) ), MTH_M_xMin ( MTH3D_M_xGetZofVector ( p_stMaxPoint1 ), MTH3D_M_xGetZofVector ( p_stMaxPoint2 ) ) ) ); } /* -------------------------------------------------------------------------------- -- Description : Sphere with a box intersection test -------------------------------------------------------------------------------- -- Creation date : 10 jan 1997 Author : FPI -------------------------------------------------------------------------------- */ /* teste l intersection d une sphere et d une boite */ /* used*/ ACP_tdxBool INT_fn_bIntersectSphereWithBox ( MTH3D_tdstVector *p_stCenter, MTH_tdxReal xRadius, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint ) { MTH_tdxReal xDist; xDist = MTH_C_ZERO; if ( p_stCenter->xX < p_stMinPoint->xX ) { xDist = MTH_M_xAdd ( xDist, MTH_M_xSqr ( MTH_M_xSub ( p_stCenter->xX, p_stMinPoint->xX ) ) ); } else { if ( p_stCenter->xX > p_stMaxPoint->xX ) { xDist = MTH_M_xAdd ( xDist, MTH_M_xSqr ( MTH_M_xSub ( p_stCenter->xX, p_stMaxPoint->xX ) ) ); } } if ( p_stCenter->xY < p_stMinPoint->xY ) { xDist = MTH_M_xAdd ( xDist, MTH_M_xSqr ( MTH_M_xSub ( p_stCenter->xY, p_stMinPoint->xY ) ) ); } else { if ( p_stCenter->xY > p_stMaxPoint->xY ) { xDist = MTH_M_xAdd ( xDist, MTH_M_xSqr ( MTH_M_xSub ( p_stCenter->xY, p_stMaxPoint->xY ) ) ); } } if ( p_stCenter->xZ < p_stMinPoint->xZ ) { xDist = MTH_M_xAdd ( xDist, MTH_M_xSqr ( MTH_M_xSub ( p_stCenter->xZ, p_stMinPoint->xZ ) ) ); } else { if ( p_stCenter->xZ > p_stMaxPoint->xZ ) { xDist = MTH_M_xAdd ( xDist, MTH_M_xSqr ( MTH_M_xSub ( p_stCenter->xZ, p_stMaxPoint->xZ ) ) ); } } return xDist < MTH_M_xSqr ( xRadius ); } /* -------------------------------------------------------------------------------- -- Description : Sphere with a sphere intersection test -------------------------------------------------------------------------------- -- Creation date : 18 apr 1997 Author : FPI -------------------------------------------------------------------------------- */ /* teste l intersection de deux spheres */ /* used*/ ACP_tdxBool INT_fn_bIntersectSphereWithSphere ( MTH3D_tdstVector *p_stCenter1, MTH_tdxReal xRadius1, MTH3D_tdstVector *p_stCenter2, MTH_tdxReal xRadius2 ) { return MTH_M_bLessEqual ( MTH3D_M_xVectorGapSqr ( p_stCenter1, p_stCenter2 ), MTH_M_xSqr ( MTH_M_xAdd ( xRadius1, xRadius2 ) ) ); } /* -------------------------------------------------------------------------------- -- Description : Get the position of a point with a box -------------------------------------------------------------------------------- -- Creation date : 22 aug 1996 Author : FPI -------------------------------------------------------------------------------- */ /* Which of the six face-plane(s) is point P outside of? */ /* used*/ unsigned long INT_fn_ulGetPositionPointWithBox ( MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint ) { unsigned long ulOutCode; ulOutCode = COL_C_ulNullMask; if ( MTH_M_bLess ( MTH3D_M_xGetXofVector ( p_stPoint ), MTH3D_M_xGetXofVector ( p_stMinPoint ) ) ) ulOutCode |= COL_C_ulXMinMask; else if ( MTH_M_bGreater ( MTH3D_M_xGetXofVector ( p_stPoint ), MTH3D_M_xGetXofVector ( p_stMaxPoint ) ) ) ulOutCode |= COL_C_ulXMaxMask; if ( MTH_M_bLess ( MTH3D_M_xGetYofVector ( p_stPoint ), MTH3D_M_xGetYofVector ( p_stMinPoint ) ) ) ulOutCode |= COL_C_ulYMinMask; else if ( MTH_M_bGreater ( MTH3D_M_xGetYofVector ( p_stPoint ), MTH3D_M_xGetYofVector ( p_stMaxPoint ) ) ) ulOutCode |= COL_C_ulYMaxMask; if ( MTH_M_bLess ( MTH3D_M_xGetZofVector ( p_stPoint ), MTH3D_M_xGetZofVector ( p_stMinPoint ) ) ) ulOutCode |= COL_C_ulZMinMask; else if ( MTH_M_bGreater ( MTH3D_M_xGetZofVector ( p_stPoint ), MTH3D_M_xGetZofVector ( p_stMaxPoint ) ) ) ulOutCode |= COL_C_ulZMaxMask; return ulOutCode; } /* -------------------------------------------------------------------------------- -- Description : Point in XY range test -------------------------------------------------------------------------------- -- Creation date : 06 oct 1997 Author : FPI -------------------------------------------------------------------------------- */ /* used*/ ACP_tdxBool INT_fn_bInXYRange ( MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint ) { if ( MTH_M_bLess ( MTH3D_M_xGetXofVector ( p_stPoint ), MTH3D_M_xGetXofVector ( p_stMinPoint ) ) ) return FALSE; if ( MTH_M_bGreater ( MTH3D_M_xGetXofVector ( p_stPoint ), MTH3D_M_xGetXofVector ( p_stMaxPoint ) ) ) return FALSE; if ( MTH_M_bLess ( MTH3D_M_xGetYofVector ( p_stPoint ), MTH3D_M_xGetYofVector ( p_stMinPoint ) ) ) return FALSE; if ( MTH_M_bGreater ( MTH3D_M_xGetYofVector ( p_stPoint ), MTH3D_M_xGetYofVector ( p_stMaxPoint ) ) ) return FALSE; return TRUE; } /* -------------------------------------------------------------------------------- -- Description : Point in YZ range test -------------------------------------------------------------------------------- -- Creation date : 06 oct 1997 Author : FPI -------------------------------------------------------------------------------- */ /* used*/ ACP_tdxBool INT_fn_bInYZRange ( MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint ) { if ( MTH_M_bLess ( MTH3D_M_xGetYofVector ( p_stPoint ), MTH3D_M_xGetYofVector ( p_stMinPoint ) ) ) return FALSE; if ( MTH_M_bGreater ( MTH3D_M_xGetYofVector ( p_stPoint ), MTH3D_M_xGetYofVector ( p_stMaxPoint ) ) ) return FALSE; if ( MTH_M_bLess ( MTH3D_M_xGetZofVector ( p_stPoint ), MTH3D_M_xGetZofVector ( p_stMinPoint ) ) ) return FALSE; if ( MTH_M_bGreater ( MTH3D_M_xGetZofVector ( p_stPoint ), MTH3D_M_xGetZofVector ( p_stMaxPoint ) ) ) return FALSE; return TRUE; } /* -------------------------------------------------------------------------------- -- Description : Point in XZ range test -------------------------------------------------------------------------------- -- Creation date : 06 oct 1997 Author : FPI -------------------------------------------------------------------------------- */ /* used*/ ACP_tdxBool INT_fn_bInXZRange ( MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint ) { if ( MTH_M_bLess ( MTH3D_M_xGetXofVector ( p_stPoint ), MTH3D_M_xGetXofVector ( p_stMinPoint ) ) ) return FALSE; if ( MTH_M_bGreater ( MTH3D_M_xGetXofVector ( p_stPoint ), MTH3D_M_xGetXofVector ( p_stMaxPoint ) ) ) return FALSE; if ( MTH_M_bLess ( MTH3D_M_xGetZofVector ( p_stPoint ), MTH3D_M_xGetZofVector ( p_stMinPoint ) ) ) return FALSE; if ( MTH_M_bGreater ( MTH3D_M_xGetZofVector ( p_stPoint ), MTH3D_M_xGetZofVector ( p_stMaxPoint ) ) ) return FALSE; return TRUE; } /* -------------------------------------------------------------------------------- -- Description : Point with a box intersection test -------------------------------------------------------------------------------- -- Creation date : 22 aug 1996 Author : FPI -------------------------------------------------------------------------------- */ /* used*/ ACP_tdxBool INT_fn_bGetInclusionPointInBox ( MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint ) { if ( MTH_M_bLess ( MTH3D_M_xGetXofVector ( p_stPoint ), MTH3D_M_xGetXofVector ( p_stMinPoint ) ) ) return FALSE; if ( MTH_M_bGreater ( MTH3D_M_xGetXofVector ( p_stPoint ), MTH3D_M_xGetXofVector ( p_stMaxPoint ) ) ) return FALSE; if ( MTH_M_bLess ( MTH3D_M_xGetYofVector ( p_stPoint ), MTH3D_M_xGetYofVector ( p_stMinPoint ) ) ) return FALSE; if ( MTH_M_bGreater ( MTH3D_M_xGetYofVector ( p_stPoint ), MTH3D_M_xGetYofVector ( p_stMaxPoint ) ) ) return FALSE; if ( MTH_M_bLess ( MTH3D_M_xGetZofVector ( p_stPoint ), MTH3D_M_xGetZofVector ( p_stMinPoint ) ) ) return FALSE; if ( MTH_M_bGreater ( MTH3D_M_xGetZofVector ( p_stPoint ), MTH3D_M_xGetZofVector ( p_stMaxPoint ) ) ) return FALSE; return TRUE; } /* -------------------------------------------------------------------------------- -- Description : Get position of a point with the edge plans of a box -------------------------------------------------------------------------------- -- Creation date : 22 aug 1996 Author : FPI -------------------------------------------------------------------------------- */ /* Which of the twelve edge plane(s) is point P outside of? */ /* used*/ unsigned long INT_fn_ulGetPositionPointWithEdgeBox ( MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint, MTH3D_tdstVector *p_stDelta, MTH3D_tdstVector *p_stNegDelta ) { unsigned long ulOutCode; MTH3D_tdstVector stMulDeltaPoint; MTH3D_tdstVector stMulNegDeltaPoint; MTH3D_tdstVector stMulDeltaMax; MTH3D_tdstVector stMulNegDeltaMin; ulOutCode = 0; MTH3D_M_vScaleVector ( &stMulDeltaPoint, p_stDelta, p_stPoint ); MTH3D_M_vScaleVector ( &stMulNegDeltaPoint, p_stNegDelta, p_stPoint ); MTH3D_M_vScaleVector ( &stMulDeltaMax, p_stDelta, p_stMaxPoint ); MTH3D_M_vScaleVector ( &stMulNegDeltaMin, p_stNegDelta, p_stMinPoint ); if ( (stMulDeltaPoint.xX + stMulDeltaPoint.xY) > (stMulDeltaMax.xX + stMulDeltaMax.xY) ) ulOutCode |= 0x001; if ( (stMulDeltaPoint.xX + stMulNegDeltaPoint.xY) > (stMulDeltaMax.xX + stMulNegDeltaMin.xY) ) ulOutCode |= 0x002; if ( (stMulNegDeltaPoint.xX + stMulDeltaPoint.xY) > (stMulNegDeltaMin.xX + stMulDeltaMax.xY) ) ulOutCode |= 0x004; if ( (stMulNegDeltaPoint.xX + stMulNegDeltaPoint.xY) > (stMulNegDeltaMin.xX + stMulNegDeltaMin.xY) ) ulOutCode |= 0x008; if ( (stMulDeltaPoint.xX + stMulDeltaPoint.xZ) > (stMulDeltaMax.xX + stMulDeltaMax.xZ) ) ulOutCode |= 0x010; if ( (stMulDeltaPoint.xX + stMulNegDeltaPoint.xZ) > (stMulDeltaMax.xX + stMulNegDeltaMin.xZ) ) ulOutCode |= 0x020; if ( (stMulNegDeltaPoint.xX + stMulDeltaPoint.xZ) > (stMulNegDeltaMin.xX + stMulDeltaMax.xZ) ) ulOutCode |= 0x040; if ( (stMulNegDeltaPoint.xX + stMulNegDeltaPoint.xZ) > (stMulNegDeltaMin.xX + stMulNegDeltaMin.xZ) ) ulOutCode |= 0x080; if ( (stMulDeltaPoint.xY + stMulDeltaPoint.xZ) > (stMulDeltaMax.xY + stMulDeltaMax.xZ) ) ulOutCode |= 0x100; if ( (stMulDeltaPoint.xY + stMulNegDeltaPoint.xZ) > (stMulDeltaMax.xY + stMulNegDeltaMin.xZ) ) ulOutCode |= 0x200; if ( (stMulNegDeltaPoint.xY + stMulDeltaPoint.xZ) > (stMulNegDeltaMin.xY + stMulDeltaMax.xZ) ) ulOutCode |= 0x400; if ( (stMulNegDeltaPoint.xY + stMulNegDeltaPoint.xZ) > (stMulNegDeltaMin.xY + stMulNegDeltaMin.xZ) ) ulOutCode |= 0x800; return ulOutCode; } /*--------------------------------------------------------------------------------------*/ /* Name : INT_fn_bIntersectEdgeWithBoxWithHit*/ /* Author : Thierry QUERE*/ /* Date : 06/03/98*/ /* Description : */ /*--------------------------------------------------------------------------------------*/ /* used*/ ACP_tdxBool INT_fn_bIntersectEdgeWithBoxWithHit ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint, unsigned long ulExploredPlan, MTH3D_tdstVector * p_stHit) { MTH_tdxReal xT; if ( ulExploredPlan & COL_C_ulXMinMask ) { xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xX, p_stVertex1->xX ), p_stVect12->xX ); p_stHit->xX = p_stMinPoint->xX; p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, xT, p_stVertex1->xY ); p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, xT, p_stVertex1->xZ ); if ( INT_fn_bInYZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } if ( ulExploredPlan & COL_C_ulXMaxMask ) { xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xX, p_stVertex1->xX ), p_stVect12->xX ); p_stHit->xX = p_stMaxPoint->xX; p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, xT, p_stVertex1->xY ); p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, xT, p_stVertex1->xZ ); if ( INT_fn_bInYZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } if ( ulExploredPlan & COL_C_ulYMinMask ) { xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xY, p_stVertex1->xY ), p_stVect12->xY ); p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, xT, p_stVertex1->xX ); p_stHit->xY = p_stMinPoint->xY; p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, xT, p_stVertex1->xZ ); if ( INT_fn_bInXZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } if ( ulExploredPlan & COL_C_ulYMaxMask ) { xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xY, p_stVertex1->xY ), p_stVect12->xY ); p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, xT, p_stVertex1->xX ); p_stHit->xY = p_stMaxPoint->xY; p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, xT, p_stVertex1->xZ ); if ( INT_fn_bInXZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } if ( ulExploredPlan & COL_C_ulZMinMask ) { xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xZ, p_stVertex1->xZ ), p_stVect12->xZ ); p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, xT, p_stVertex1->xX ); p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, xT, p_stVertex1->xY ); p_stHit->xZ = p_stMinPoint->xZ; if ( INT_fn_bInXYRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } if ( ulExploredPlan & COL_C_ulZMaxMask ) { xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xZ, p_stVertex1->xZ ), p_stVect12->xZ ); p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, xT, p_stVertex1->xX ); p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, xT, p_stVertex1->xY ); p_stHit->xZ = p_stMaxPoint->xZ; if ( INT_fn_bInXYRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } return FALSE; } /* -------------------------------------------------------------------------------- -- Description : Segment with box intersection test -------------------------------------------------------------------------------- -- Creation date : 22 aug 1996 Author : FPI -------------------------------------------------------------------------------- */ /* used*/ ACP_tdxBool INT_fn_bIntersectSegmentWithBox ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint, MTH_tdxReal *p_xT, MTH3D_tdstVector *p_stHit, MTH3D_tdstVector *p_stNormal ) { unsigned long ulVertex1Test; unsigned long ulVertex2Test; unsigned long ulExploredPlan; /* optimisation sur les demi-espaces */ ulVertex1Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex1, p_stMinPoint, p_stMaxPoint ); if ( ulVertex1Test == COL_C_ulNullMask ) return FALSE; ulVertex2Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex2, p_stMinPoint, p_stMaxPoint ); if ( ulVertex1Test & ulVertex2Test ) return FALSE; ulExploredPlan = ulVertex1Test; if ( ulExploredPlan & COL_C_ulXMinMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xX, p_stVertex1->xX ), p_stVect12->xX ); p_stHit->xX = p_stMinPoint->xX; p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInYZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xXMin]) ); return TRUE; } } if ( ulExploredPlan & COL_C_ulXMaxMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xX, p_stVertex1->xX ), p_stVect12->xX ); p_stHit->xX = p_stMaxPoint->xX; p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInYZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xXMax]) ); return TRUE; } } if ( ulExploredPlan & COL_C_ulYMinMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xY, p_stVertex1->xY ), p_stVect12->xY ); p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); p_stHit->xY = p_stMinPoint->xY; p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInXZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xYMin]) ); return TRUE; } } if ( ulExploredPlan & COL_C_ulYMaxMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xY, p_stVertex1->xY ), p_stVect12->xY ); p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); p_stHit->xY = p_stMaxPoint->xY; p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInXZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xYMax]) ); return TRUE; } } if ( ulExploredPlan & COL_C_ulZMinMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xZ, p_stVertex1->xZ ), p_stVect12->xZ ); p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); p_stHit->xZ = p_stMinPoint->xZ; if ( INT_fn_bInXYRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xZMin]) ); return TRUE; } } if ( ulExploredPlan & COL_C_ulZMaxMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xZ, p_stVertex1->xZ ), p_stVect12->xZ ); p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); p_stHit->xZ = p_stMaxPoint->xZ; if ( INT_fn_bInXYRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xZMax]) ); return TRUE; } } return FALSE; } /* -------------------------------------------------------------------------------- -- Description : Semiaxe with box intersection test -------------------------------------------------------------------------------- -- Creation date : 12 nov 1996 Author : FPI -------------------------------------------------------------------------------- */ #ifdef ACTIVE_EDITOR /* active editor only*/ ACP_tdxBool INT_fn_bIntersectSemiAxeWithBox ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint, ACP_tdxBool *bBack, MTH_tdxReal *p_xT, MTH3D_tdstVector *p_stHit, MTH3D_tdstVector *p_stNormal ) { unsigned long ulVertex1Test; unsigned long ulVertex2Test; unsigned long ulExploredPlan; /* optimisation sur les demi-espaces */ ulVertex1Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex1, p_stMinPoint, p_stMaxPoint ); ulVertex2Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex2, p_stMinPoint, p_stMaxPoint ); /* intersections demi droite - cotes boite */ if ( ulVertex1Test == COL_C_ulNullMask ) { if ( ulVertex2Test == COL_C_ulNullMask ) { ulExploredPlan = COL_C_ulNullMask; if ( MTH_M_bGreaterZero ( p_stVect12->xX ) ) ulExploredPlan |= COL_C_ulXMaxMask; else ulExploredPlan |= COL_C_ulXMinMask; if ( MTH_M_bIsNull ( p_stVect12->xX ) ) ulExploredPlan &= ~( COL_C_ulXMinMask | COL_C_ulXMaxMask ); if ( MTH_M_bGreaterZero ( p_stVect12->xY ) ) ulExploredPlan |= COL_C_ulYMaxMask; else ulExploredPlan |= COL_C_ulYMinMask; if ( MTH_M_bIsNull ( p_stVect12->xY ) ) ulExploredPlan &= ~( COL_C_ulYMinMask | COL_C_ulYMaxMask ); if ( MTH_M_bGreaterZero ( p_stVect12->xZ ) ) ulExploredPlan |= COL_C_ulZMaxMask; else ulExploredPlan |= COL_C_ulZMinMask; if ( MTH_M_bIsNull ( p_stVect12->xZ ) ) ulExploredPlan &= ~( COL_C_ulZMinMask | COL_C_ulZMaxMask ); } else { ulExploredPlan = ulVertex2Test; } } else { if ( ulVertex1Test & ulVertex2Test ) { ulExploredPlan = ulVertex1Test & ulVertex2Test; if ( ( ulExploredPlan & COL_C_ulXMinMask ) && ( MTH_M_bLessEqualZero ( p_stVect12->xX ) ) ) ulExploredPlan &= ~COL_C_ulXMinMask; if ( ( ulExploredPlan & COL_C_ulXMaxMask ) && ( MTH_M_bGreaterEqualZero ( p_stVect12->xX ) ) ) ulExploredPlan &= ~COL_C_ulXMaxMask; if ( ( ulExploredPlan & COL_C_ulYMinMask ) && ( MTH_M_bLessEqualZero ( p_stVect12->xY ) ) ) ulExploredPlan &= ~COL_C_ulYMinMask; if ( ( ulExploredPlan & COL_C_ulYMaxMask ) && ( MTH_M_bGreaterEqualZero ( p_stVect12->xY ) ) ) ulExploredPlan &= ~COL_C_ulYMaxMask; if ( ( ulExploredPlan & COL_C_ulZMinMask ) && ( MTH_M_bLessEqualZero ( p_stVect12->xZ ) ) ) ulExploredPlan &= ~COL_C_ulZMinMask; if ( ( ulExploredPlan & COL_C_ulZMaxMask ) && ( MTH_M_bGreaterEqualZero ( p_stVect12->xZ ) ) ) ulExploredPlan &= ~COL_C_ulZMaxMask; } else { ulExploredPlan = ulVertex1Test; } } if ( ulExploredPlan & COL_C_ulXMinMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xX, p_stVertex1->xX ), p_stVect12->xX ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { p_stHit->xX = p_stMinPoint->xX; p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInYZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bLessZero ( p_stVect12->xX ); MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xXMin]) ); return TRUE; } } } if ( ulExploredPlan & COL_C_ulXMaxMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xX, p_stVertex1->xX ), p_stVect12->xX ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { p_stHit->xX = p_stMaxPoint->xX; p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInYZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bGreaterZero ( p_stVect12->xX ); MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xXMax]) ); return TRUE; } } } if ( ulExploredPlan & COL_C_ulYMinMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xY, p_stVertex1->xY ), p_stVect12->xY ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); p_stHit->xY = p_stMinPoint->xY; p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInXZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bLessZero ( p_stVect12->xY ); MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xYMin]) ); return TRUE; } } } if ( ulExploredPlan & COL_C_ulYMaxMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xY, p_stVertex1->xY ), p_stVect12->xY ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); p_stHit->xY = p_stMaxPoint->xY; p_stHit->xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInXZRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bGreaterZero ( p_stVect12->xY ); MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xYMax]) ); return TRUE; } } } if ( ulExploredPlan & COL_C_ulZMinMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xZ, p_stVertex1->xZ ), p_stVect12->xZ ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); p_stHit->xZ = p_stMinPoint->xZ; if ( INT_fn_bInXYRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bLessZero ( p_stVect12->xZ ); MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xZMin]) ); return TRUE; } } } if ( ulExploredPlan & COL_C_ulZMaxMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xZ, p_stVertex1->xZ ), p_stVect12->xZ ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { p_stHit->xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); p_stHit->xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); p_stHit->xZ = p_stMaxPoint->xZ; if ( INT_fn_bInXYRange ( p_stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bGreaterZero ( p_stVect12->xZ ); MTH3D_M_vCopyVector ( p_stNormal, &(COL_g_a6_stBoxSidesNormal[COL_C_xZMax]) ); return TRUE; } } } return FALSE; } #endif /* -------------------------------------------------------------------------------- -- Description : Semiaxe with box intersection test for octree -------------------------------------------------------------------------------- -- Creation date : 19 mar 1997 Author : FPI -------------------------------------------------------------------------------- */ #ifdef ACTIVE_EDITOR /* active editor only*/ ACP_tdxBool INT_fn_bIntersectSemiAxeWithBoxForOctree ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint, ACP_tdxBool *bBack, MTH_tdxReal *p_xT ) { unsigned long ulVertex1Test; unsigned long ulVertex2Test; unsigned long ulExploredPlan; MTH3D_tdstVector stHit; /* optimisation sur les demi-espaces */ ulVertex1Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex1, p_stMinPoint, p_stMaxPoint ); ulVertex2Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex2, p_stMinPoint, p_stMaxPoint ); /* intersections demi droite - cotes boite */ if ( ulVertex1Test == COL_C_ulNullMask ) { if ( ulVertex2Test == COL_C_ulNullMask ) { ulExploredPlan = COL_C_ulNullMask; if ( MTH_M_bGreaterZero ( p_stVect12->xX ) ) ulExploredPlan |= COL_C_ulXMaxMask; else ulExploredPlan |= COL_C_ulXMinMask; if ( MTH_M_bIsNull ( p_stVect12->xX ) ) ulExploredPlan &= ~( COL_C_ulXMinMask | COL_C_ulXMaxMask ); if ( MTH_M_bGreaterZero ( p_stVect12->xY ) ) ulExploredPlan |= COL_C_ulYMaxMask; else ulExploredPlan |= COL_C_ulYMinMask; if ( MTH_M_bIsNull ( p_stVect12->xY ) ) ulExploredPlan &= ~( COL_C_ulYMinMask | COL_C_ulYMaxMask ); if ( MTH_M_bGreaterZero ( p_stVect12->xZ ) ) ulExploredPlan |= COL_C_ulZMaxMask; else ulExploredPlan |= COL_C_ulZMinMask; if ( MTH_M_bIsNull ( p_stVect12->xZ ) ) ulExploredPlan &= ~( COL_C_ulZMinMask | COL_C_ulZMaxMask ); } else { ulExploredPlan = ulVertex2Test; } } else { if ( ulVertex1Test & ulVertex2Test ) { ulExploredPlan = ulVertex1Test & ulVertex2Test; if ( ( ulExploredPlan & COL_C_ulXMinMask ) && ( MTH_M_bLessEqualZero ( p_stVect12->xX ) ) ) ulExploredPlan &= ~COL_C_ulXMinMask; if ( ( ulExploredPlan & COL_C_ulXMaxMask ) && ( MTH_M_bGreaterEqualZero ( p_stVect12->xX ) ) ) ulExploredPlan &= ~COL_C_ulXMaxMask; if ( ( ulExploredPlan & COL_C_ulYMinMask ) && ( MTH_M_bLessEqualZero ( p_stVect12->xY ) ) ) ulExploredPlan &= ~COL_C_ulYMinMask; if ( ( ulExploredPlan & COL_C_ulYMaxMask ) && ( MTH_M_bGreaterEqualZero ( p_stVect12->xY ) ) ) ulExploredPlan &= ~COL_C_ulYMaxMask; if ( ( ulExploredPlan & COL_C_ulZMinMask ) && ( MTH_M_bLessEqualZero ( p_stVect12->xZ ) ) ) ulExploredPlan &= ~COL_C_ulZMinMask; if ( ( ulExploredPlan & COL_C_ulZMaxMask ) && ( MTH_M_bGreaterEqualZero ( p_stVect12->xZ ) ) ) ulExploredPlan &= ~COL_C_ulZMaxMask; } else { ulExploredPlan = ulVertex1Test; } } if ( ulExploredPlan & COL_C_ulXMinMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xX, p_stVertex1->xX ), p_stVect12->xX ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { stHit.xX = p_stMinPoint->xX; stHit.xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); stHit.xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInYZRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bLessZero ( p_stVect12->xX ); return TRUE; } } } if ( ulExploredPlan & COL_C_ulXMaxMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xX, p_stVertex1->xX ), p_stVect12->xX ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { stHit.xX = p_stMaxPoint->xX; stHit.xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); stHit.xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInYZRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bGreaterZero ( p_stVect12->xX ); return TRUE; } } } if ( ulExploredPlan & COL_C_ulYMinMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xY, p_stVertex1->xY ), p_stVect12->xY ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { stHit.xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); stHit.xY = p_stMinPoint->xY; stHit.xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInXZRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bLessZero ( p_stVect12->xY ); return TRUE; } } } if ( ulExploredPlan & COL_C_ulYMaxMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xY, p_stVertex1->xY ), p_stVect12->xY ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { stHit.xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); stHit.xY = p_stMaxPoint->xY; stHit.xZ = MTH_M_xMulAdd ( p_stVect12->xZ, *p_xT, p_stVertex1->xZ ); if ( INT_fn_bInXZRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bGreaterZero ( p_stVect12->xY ); return TRUE; } } } if ( ulExploredPlan & COL_C_ulZMinMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMinPoint->xZ, p_stVertex1->xZ ), p_stVect12->xZ ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { stHit.xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); stHit.xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); stHit.xZ = p_stMinPoint->xZ; if ( INT_fn_bInXYRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bLessZero ( p_stVect12->xZ ); return TRUE; } } } if ( ulExploredPlan & COL_C_ulZMaxMask ) { *p_xT = MTH_M_xDiv ( MTH_M_xSub ( p_stMaxPoint->xZ, p_stVertex1->xZ ), p_stVect12->xZ ); if ( MTH_M_bGreaterEqualZero ( *p_xT ) ) { stHit.xX = MTH_M_xMulAdd ( p_stVect12->xX, *p_xT, p_stVertex1->xX ); stHit.xY = MTH_M_xMulAdd ( p_stVect12->xY, *p_xT, p_stVertex1->xY ); stHit.xZ = p_stMaxPoint->xZ; if ( INT_fn_bInXYRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) { *bBack = MTH_M_bGreaterZero ( p_stVect12->xZ ); return TRUE; } } } return FALSE; } #endif /* -------------------------------------------------------------------------------- -- Description : Semiaxe with box intersection detection -------------------------------------------------------------------------------- -- Creation date : 06 feb 1997 Author : FPI -------------------------------------------------------------------------------- */ #ifdef ACTIVE_EDITOR /* active editor only*/ ACP_tdxBool INT_fn_bDetectIntersectSemiAxeWithBox ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint ) { unsigned long ulVertex1Test; unsigned long ulVertex2Test; unsigned long ulExploredPlan; MTH_tdxReal xT; MTH3D_tdstVector stHit; /* optimisation sur les demi-espaces */ ulVertex1Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex1, p_stMinPoint, p_stMaxPoint ); if ( ulVertex1Test == COL_C_ulNullMask ) { return TRUE; } ulVertex2Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex2, p_stMinPoint, p_stMaxPoint ); if ( ulVertex2Test == COL_C_ulNullMask ) { return TRUE; } /* intersections demi droite - cotes boite */ if ( ulVertex1Test & ulVertex2Test ) { ulExploredPlan = ulVertex1Test & ulVertex2Test; /* if ( ( ulExploredPlan & COL_C_ulXMinMask ) && ( MTH_M_bGreaterEqualZero ( p_stVect12->xX ) ) ) ulExploredPlan &= ~COL_C_ulXMinMask; if ( ( ulExploredPlan & COL_C_ulXMaxMask ) && ( MTH_M_bLessEqualZero ( p_stVect12->xX ) ) ) ulExploredPlan &= ~COL_C_ulXMaxMask; if ( ( ulExploredPlan & COL_C_ulYMinMask ) && ( MTH_M_bGreaterEqualZero ( p_stVect12->xY ) ) ) ulExploredPlan &= ~COL_C_ulYMinMask; if ( ( ulExploredPlan & COL_C_ulYMaxMask ) && ( MTH_M_bLessEqualZero ( p_stVect12->xY ) ) ) ulExploredPlan &= ~COL_C_ulYMaxMask; if ( ( ulExploredPlan & COL_C_ulZMinMask ) && ( MTH_M_bGreaterEqualZero ( p_stVect12->xZ ) ) ) ulExploredPlan &= ~COL_C_ulZMinMask; if ( ( ulExploredPlan & COL_C_ulZMaxMask ) && ( MTH_M_bLessEqualZero ( p_stVect12->xZ ) ) ) ulExploredPlan &= ~COL_C_ulZMaxMask; */ if ( ( ulExploredPlan & COL_C_ulXMinMask ) && ( MTH_M_bLessZero ( p_stVect12->xX ) ) ) return FALSE; if ( ( ulExploredPlan & COL_C_ulXMaxMask ) && ( MTH_M_bGreaterZero ( p_stVect12->xX ) ) ) return FALSE; if ( ( ulExploredPlan & COL_C_ulYMinMask ) && ( MTH_M_bLessZero ( p_stVect12->xY ) ) ) return FALSE; if ( ( ulExploredPlan & COL_C_ulYMaxMask ) && ( MTH_M_bGreaterZero ( p_stVect12->xY ) ) ) return FALSE; if ( ( ulExploredPlan & COL_C_ulZMinMask ) && ( MTH_M_bLessZero ( p_stVect12->xZ ) ) ) return FALSE; if ( ( ulExploredPlan & COL_C_ulZMaxMask ) && ( MTH_M_bGreaterZero ( p_stVect12->xZ ) ) ) return FALSE; } else { ulExploredPlan = ulVertex1Test; } if ( ulExploredPlan & COL_C_ulXMinMask ) { /*HP 260898*/ xT=MTH_M_xSub ( p_stMinPoint->xX, p_stVertex1->xX ); if(p_stVect12->xX) xT = MTH_M_xDiv ( xT, p_stVect12->xX ); if ( MTH_M_bGreaterEqualZero ( xT ) ) { stHit.xX = p_stMinPoint->xX; stHit.xY = MTH_M_xMulAdd ( p_stVect12->xY, xT, p_stVertex1->xY ); stHit.xZ = MTH_M_xMulAdd ( p_stVect12->xZ, xT, p_stVertex1->xZ ); if ( INT_fn_bInYZRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } } if ( ulExploredPlan & COL_C_ulXMaxMask ) { /*HP 260898*/ xT=MTH_M_xSub ( p_stMaxPoint->xX, p_stVertex1->xX ); if(p_stVect12->xX) xT = MTH_M_xDiv ( xT, p_stVect12->xX ); if ( MTH_M_bGreaterEqualZero ( xT ) ) { stHit.xX = p_stMaxPoint->xX; stHit.xY = MTH_M_xMulAdd ( p_stVect12->xY, xT, p_stVertex1->xY ); stHit.xZ = MTH_M_xMulAdd ( p_stVect12->xZ, xT, p_stVertex1->xZ ); if ( INT_fn_bInYZRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } } if ( ulExploredPlan & COL_C_ulYMinMask ) { /*HP 260898*/ xT = MTH_M_xSub ( p_stMinPoint->xY, p_stVertex1->xY ); if(p_stVect12->xY) xT = MTH_M_xDiv ( xT, p_stVect12->xY ); if ( MTH_M_bGreaterEqualZero ( xT ) ) { stHit.xX = MTH_M_xMulAdd ( p_stVect12->xX, xT, p_stVertex1->xX ); stHit.xY = p_stMinPoint->xY; stHit.xZ = MTH_M_xMulAdd ( p_stVect12->xZ, xT, p_stVertex1->xZ ); if ( INT_fn_bInXZRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } } if ( ulExploredPlan & COL_C_ulYMaxMask ) { /*HP 260898*/ xT=MTH_M_xSub ( p_stMaxPoint->xY, p_stVertex1->xY ); if(p_stVect12->xY) xT = MTH_M_xDiv ( xT, p_stVect12->xY ); if ( MTH_M_bGreaterEqualZero ( xT ) ) { stHit.xX = MTH_M_xMulAdd ( p_stVect12->xX, xT, p_stVertex1->xX ); stHit.xY = p_stMaxPoint->xY; stHit.xZ = MTH_M_xMulAdd ( p_stVect12->xZ, xT, p_stVertex1->xZ ); if ( INT_fn_bInXZRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } } if ( ulExploredPlan & COL_C_ulZMinMask ) { /*HP 260898*/ xT=MTH_M_xSub ( p_stMinPoint->xZ, p_stVertex1->xZ ); if(p_stVect12->xZ) xT = MTH_M_xDiv ( xT, p_stVect12->xZ ); if ( MTH_M_bGreaterEqualZero ( xT ) ) { stHit.xX = MTH_M_xMulAdd ( p_stVect12->xX, xT, p_stVertex1->xX ); stHit.xY = MTH_M_xMulAdd ( p_stVect12->xY, xT, p_stVertex1->xY ); stHit.xZ = p_stMinPoint->xZ; if ( INT_fn_bInXYRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } } if ( ulExploredPlan & COL_C_ulZMaxMask ) { /*HP260898*/ xT=MTH_M_xSub ( p_stMaxPoint->xZ, p_stVertex1->xZ ); if(p_stVect12->xZ) xT = MTH_M_xDiv (xT, p_stVect12->xZ ); if ( MTH_M_bGreaterEqualZero ( xT ) ) { stHit.xX = MTH_M_xMulAdd ( p_stVect12->xX, xT, p_stVertex1->xX ); stHit.xY = MTH_M_xMulAdd ( p_stVect12->xY, xT, p_stVertex1->xY ); stHit.xZ = p_stMaxPoint->xZ; if ( INT_fn_bInXYRange ( &stHit, p_stMinPoint, p_stMaxPoint ) ) return TRUE; } } return FALSE; } #endif /* this macros return x,y or z of the vector if num == 0,1 or 2 */ #define M_GetCoord(p_stVect,Num) \ *( ((MTH_tdxReal*)p_stVect) + Num) /* result :*/ /* 0 --> no detection*/ /* 1 --> detection*/ /* 2 --> don't know*/ /* used*/ static unsigned char ucPlaneCrossingdetect(MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint, MTH_tdxReal xT, char cFace) { unsigned long idx1,idx2; MTH_tdxReal xTmp; /* compute variables according to the face to manage*/ switch (cFace) { case 'X': idx1 = 1; idx2 = 2; break; case 'Y': idx1 = 0; idx2 = 2; break; case 'Z': idx1 = 0; idx2 = 1; break; default: assert(0); break; } /* all comments are written in the case 'X', with idx1 = 1 (Y) and idx2 = 2 (Z)*/ /* xTmp is the y of the intersection point with the side of the box*/ xTmp = MTH_M_xMulAdd (M_GetCoord(p_stVect12,idx1), xT, M_GetCoord(p_stVertex1,idx1)); if (MTH_M_bGreaterZero(M_GetCoord(p_stVect12,idx1))) { /* the A point is on the front, the B point is in the back*/ /* if it intersects the side of the box behind the back plane, it is out !*/ if (MTH_M_bGreater (xTmp,M_GetCoord(p_stMaxPoint,idx1)) ) return 0; /* if it intersects the left side of the box behind the front plane, continue search on up / down plane !*/ if (MTH_M_bGreaterEqual(xTmp,M_GetCoord(p_stMinPoint,idx1)) ) { /* xTmp is the z of the intersection point with the left side of the box*/ xTmp = MTH_M_xMulAdd (M_GetCoord(p_stVect12,idx2), xT, M_GetCoord(p_stVertex1,idx2)); if (MTH_M_bGreaterZero(M_GetCoord(p_stVect12,idx2))) { /* the A point is down, the B point is up*/ /* if it intersects the left side of the box higher than the up plane, it is out !*/ if (MTH_M_bGreater (xTmp,M_GetCoord(p_stMaxPoint,idx2)) ) return 0; /* if it intersects the left side of the box higher than the down plane, it is in !!!*/ if (MTH_M_bGreaterEqual(xTmp,M_GetCoord(p_stMinPoint,idx2)) ) { return 1; } /* else we don't know....*/ } else { /* the A point is up, the B point is down*/ /* if it intersects the left side of the box lower than the down plane, it is out !*/ if (MTH_M_bLess (xTmp,M_GetCoord(p_stMinPoint,idx2)) ) return 0; /* if it intersects the left side of the box lower than the up plane, it is in !!!*/ if (MTH_M_bLessEqual(xTmp,M_GetCoord(p_stMaxPoint,idx2)) ) { return 1; } /* else we don't know....*/ } } /* else we don't know... continue searching*/ } else { /* the A point is in the back, the B point is on the front*/ /* if it intersects the left side of the box before the front plane, it is out !*/ if (MTH_M_bLess (xTmp,M_GetCoord(p_stMinPoint,idx1)) ) return 0; /* if it intersects the left side of the box before the back plane, continue search on up / down plane !*/ if (MTH_M_bLessEqual(xTmp,M_GetCoord(p_stMaxPoint,idx1)) ) { /* xTmp is the z of the intersection point with the left side of the box*/ xTmp = MTH_M_xMulAdd (M_GetCoord(p_stVect12,idx2), xT, M_GetCoord(p_stVertex1,idx2)); if (MTH_M_bGreaterZero(M_GetCoord(p_stVect12,idx2))) { /* the A point is down, the B point is up*/ /* if it intersects the left side of the box higher than the up plane, it is out !*/ if (MTH_M_bGreater (xTmp,M_GetCoord(p_stMaxPoint,idx2)) ) return 0; /* if it intersects the left side of the box higher than the down plane, it is in !!!*/ if (MTH_M_bGreaterEqual(xTmp,M_GetCoord(p_stMinPoint,idx2)) ) { return 1; } /* else we don't know....*/ } else { /* the A point is up, the B point is down*/ /* if it intersects the left side of the box lower than the down plane, it is out !*/ if (MTH_M_bLess (xTmp,M_GetCoord(p_stMinPoint,idx2)) ) return 0; /* if it intersects the left side of the box lower than the up plane, it is in !!!*/ if (MTH_M_bLessEqual(xTmp,M_GetCoord(p_stMaxPoint,idx2)) ) { return 1; } /* else we don't know....*/ } } /* else we don't know... continue searching*/ } return 2; } /* used*/ ACP_tdxBool INT_fn_bDetectIntersectSegmentWithBox ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint, MTH_tdxReal *_p_xT) { unsigned long ulVertex1Test; unsigned long ulVertex2Test; unsigned long ulExploredPlan; MTH_tdxReal xT,*p_xT; MTH3D_tdstVector stVertex2; ACP_tdxBool bResult,bWithxT; if (_p_xT == NULL) { bWithxT = FALSE; p_xT = &xT; } else { p_xT = _p_xT; bWithxT = TRUE; } /* optimisation sur les demi-espaces */ ulVertex1Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex1, p_stMinPoint, p_stMaxPoint ); if ( ulVertex1Test == COL_C_ulNullMask ) { /* first point is inside the box !*/ *p_xT = MTH_C_ZERO; return TRUE; } MTH3D_M_vAddVector(&stVertex2,p_stVertex1,p_stVect12); ulVertex2Test = INT_fn_ulGetPositionPointWithBox ( &stVertex2, p_stMinPoint, p_stMaxPoint ); if ( ulVertex2Test == COL_C_ulNullMask ) { /* second point is inside the box !*/ *p_xT = 1; return TRUE; } if (ulVertex1Test & ulVertex2Test) { /* both point are located on the same side of the same plan of the box (but don't care which plan it is)*/ /* but they are located on the wrong side, so the segment can't intersect the box !*/ return FALSE; } ulExploredPlan = ulVertex1Test | ulVertex2Test; if (!(ulExploredPlan & (COL_C_ulXMinMask | COL_C_ulXMaxMask | COL_C_ulYMinMask | COL_C_ulYMaxMask))) { /* both point are inside the box, according to X and Y planes*/ /* and those points can't be on the same side of the Z plane (already tested up there)... there is collision*/ if (!bWithxT) return TRUE; /* compute xT*/ if ( ulVertex1Test & COL_C_ulZMinMask ) { *p_xT = MTH_M_xSub ( p_stMinPoint->xZ, p_stVertex1->xZ ); } else { *p_xT = MTH_M_xSub ( p_stMaxPoint->xZ, p_stVertex1->xZ ); } *p_xT = MTH_M_xDiv ( *p_xT, p_stVect12->xZ ); return TRUE; } if (!(ulExploredPlan & (COL_C_ulXMinMask | COL_C_ulXMaxMask | COL_C_ulZMinMask | COL_C_ulZMaxMask))) { /* both point are inside the box, according to X and Z planes*/ /* and those points can't be on the same side of the Y plane (already tested up there)... there is collision*/ if (!bWithxT) return TRUE; /* compute xT*/ if ( ulVertex1Test & COL_C_ulYMinMask ) { *p_xT = MTH_M_xSub ( p_stMinPoint->xY, p_stVertex1->xY ); } else { *p_xT = MTH_M_xSub ( p_stMaxPoint->xY, p_stVertex1->xY ); } *p_xT = MTH_M_xDiv ( *p_xT, p_stVect12->xY ); return TRUE; } if (!(ulExploredPlan & (COL_C_ulZMinMask | COL_C_ulZMaxMask | COL_C_ulYMinMask | COL_C_ulYMaxMask))) { /* both point are inside the box, according to Z and Y planes*/ /* and those points can't be on the same side of the X plane (already tested up there)... there is collision*/ if (!bWithxT) return TRUE; /* compute xT*/ if ( ulVertex1Test & COL_C_ulXMinMask ) { *p_xT = MTH_M_xSub ( p_stMinPoint->xX, p_stVertex1->xX ); } else { *p_xT = MTH_M_xSub ( p_stMaxPoint->xX, p_stVertex1->xX ); } *p_xT = MTH_M_xDiv ( *p_xT, p_stVect12->xX ); return TRUE; } /* complete calcul... (parametric, plane after plane... lot of code, but fast computation)*/ ulExploredPlan = ulVertex1Test; if ( ulExploredPlan & COL_C_ulXMinMask ) { /* left plane :*/ *p_xT=MTH_M_xSub ( p_stMinPoint->xX, p_stVertex1->xX ); /* xT must be >0 because the case COL_C_ulXMinMask means the point A is on the left of the box ! */ /* p_stVect12->xX must be > 0 else both A and B points will be on the left of the box, which is treated up there*/ assert(MTH_M_bGreaterZero(p_stVect12->xX)); assert(MTH_M_bGreaterZero(*p_xT)); *p_xT = MTH_M_xDiv ( *p_xT, p_stVect12->xX ); if ( (bResult = ucPlaneCrossingdetect(p_stVertex1,p_stVect12,p_stMinPoint,p_stMaxPoint,*p_xT,'X')) < 2) { return bResult; } } if ( ulExploredPlan & COL_C_ulXMaxMask ) { /* right plane :*/ *p_xT=MTH_M_xSub ( p_stMaxPoint->xX, p_stVertex1->xX ); /* xT must be <0 because the case COL_C_ulXMaxMask means the point A is on the right of the box ! */ /* p_stVect12->xX must be < 0 else both A and B points will be on the right of the box, which is treated up there*/ assert(MTH_M_bLessZero(p_stVect12->xX)); assert(MTH_M_bLessZero(*p_xT)); *p_xT = MTH_M_xDiv ( *p_xT, p_stVect12->xX ); if ( (bResult = ucPlaneCrossingdetect(p_stVertex1,p_stVect12,p_stMinPoint,p_stMaxPoint,*p_xT,'X')) < 2) { return bResult; } } if ( ulExploredPlan & COL_C_ulYMinMask ) { /* front plane :*/ *p_xT=MTH_M_xSub ( p_stMinPoint->xY, p_stVertex1->xY ); /* xT must be >0 because the case COL_C_ulYMinMask means the point A is in front of the box ! */ /* p_stVect12->xY must be > 0 else both A and B points will be in front of the box, which is treated up there*/ assert(MTH_M_bGreaterZero(p_stVect12->xY)); assert(MTH_M_bGreaterZero(*p_xT)); *p_xT = MTH_M_xDiv ( *p_xT, p_stVect12->xY ); if ( (bResult = ucPlaneCrossingdetect(p_stVertex1,p_stVect12,p_stMinPoint,p_stMaxPoint,*p_xT,'Y')) < 2) { return bResult; } } if ( ulExploredPlan & COL_C_ulYMaxMask ) { /* back plane :*/ *p_xT=MTH_M_xSub ( p_stMaxPoint->xY, p_stVertex1->xY ); /* xT must be <0 because the case COL_C_ulYMaxMask means the point A is behind the box ! */ /* p_stVect12->xY must be < 0 else both A and B points will be behind the box, which is treated up there*/ assert(MTH_M_bLessZero(p_stVect12->xY)); assert(MTH_M_bLessZero(*p_xT)); *p_xT = MTH_M_xDiv ( *p_xT, p_stVect12->xY ); if ( (bResult = ucPlaneCrossingdetect(p_stVertex1,p_stVect12,p_stMinPoint,p_stMaxPoint,*p_xT,'Y')) < 2) { return bResult; } } if ( ulExploredPlan & COL_C_ulZMinMask ) { /* bottom plane :*/ *p_xT=MTH_M_xSub ( p_stMinPoint->xZ, p_stVertex1->xZ ); /* xT must be >0 because the case COL_C_ulZMinMask means the point A is under the box ! */ /* p_stVect12->xZ must be > 0 else both A and B points will be under the box, which is treated up there*/ assert(MTH_M_bGreaterZero(p_stVect12->xZ)); assert(MTH_M_bGreaterZero(*p_xT)); *p_xT = MTH_M_xDiv ( *p_xT, p_stVect12->xZ ); if ( (bResult = ucPlaneCrossingdetect(p_stVertex1,p_stVect12,p_stMinPoint,p_stMaxPoint,*p_xT,'Z')) < 2) { return bResult; } } if ( ulExploredPlan & COL_C_ulZMaxMask ) { /* top plane :*/ *p_xT=MTH_M_xSub ( p_stMaxPoint->xZ, p_stVertex1->xZ ); /* xT must be <0 because the case COL_C_ulZMaxMask means the point A is above the box ! */ /* p_stVect12->xZ must be < 0 else both A and B points will be above the box, which is treated up there*/ assert(MTH_M_bLessZero(p_stVect12->xZ)); assert(MTH_M_bLessZero(*p_xT)); *p_xT = MTH_M_xDiv ( *p_xT, p_stVect12->xZ ); if ( (bResult = ucPlaneCrossingdetect(p_stVertex1,p_stVect12,p_stMinPoint,p_stMaxPoint,*p_xT,'Z')) < 2) { return bResult; } } return FALSE; } /* -------------------------------------------------------------------------------- -- Description : Get the inclusion of point in triangle -------------------------------------------------------------------------------- -- Creation date : 29 oct 1996 Author : FPI -------------------------------------------------------------------------------- */ /* Test if 3D point is inside 3D triangle */ /* without epsilon = exact method and point vectors gligou */ /* used*/ ACP_tdxBool INT_fn_bGetPointInTriangle ( MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stVertex0, MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stNormal ) { MTH3D_tdstVector stVectP0; MTH3D_tdstVector stVectP1; MTH3D_tdstVector stVectP2; MTH_tdxReal xDet; MTH3D_M_vSubVector ( &stVectP0, p_stVertex0, p_stPoint ); MTH3D_M_vSubVector ( &stVectP1, p_stVertex1, p_stPoint ); MTH3D_M_vSubVector ( &stVectP2, p_stVertex2, p_stPoint ); /* on prend la composante maximale de la normale et on calcule les determinants */ if ( MTH_M_xAbs ( p_stNormal->xZ ) >= MTH_C_InvSqrt3 ) { /* c est Z */ xDet = MTH3D_M_xDetXYVector ( &stVectP0, &stVectP1 ); if ( FUT_M_bSameSign ( xDet, p_stNormal->xZ ) ) { xDet = MTH3D_M_xDetXYVector ( &stVectP1, &stVectP2 ); if ( FUT_M_bSameSign ( xDet, p_stNormal->xZ ) ) { xDet = MTH3D_M_xDetXYVector ( &stVectP2, &stVectP0 ); return FUT_M_bSameSign ( xDet, p_stNormal->xZ ); } else { return FALSE; } } else { return FALSE; } } else { if ( MTH_M_xAbs ( p_stNormal->xX ) >= MTH_C_InvSqrt3 ) { /* c est X */ xDet = MTH3D_M_xDetYZVector ( &stVectP0, &stVectP1 ); if ( FUT_M_bSameSign ( xDet, p_stNormal->xX ) ) { xDet = MTH3D_M_xDetYZVector ( &stVectP1, &stVectP2 ); if ( FUT_M_bSameSign ( xDet, p_stNormal->xX ) ) { xDet = MTH3D_M_xDetYZVector ( &stVectP2, &stVectP0 ); return FUT_M_bSameSign ( xDet, p_stNormal->xX ); } else { return FALSE; } } else { return FALSE; } } else { /* c est Y */ xDet = MTH3D_M_xDetZXVector ( &stVectP0, &stVectP1 ); if ( FUT_M_bSameSign ( xDet, p_stNormal->xY ) ) { xDet = MTH3D_M_xDetZXVector ( &stVectP1, &stVectP2 ); if ( FUT_M_bSameSign ( xDet, p_stNormal->xY ) ) { xDet = MTH3D_M_xDetZXVector ( &stVectP2, &stVectP0 ); return FUT_M_bSameSign ( xDet, p_stNormal->xY ); } else { return FALSE; } } else { return FALSE; } } } } /* -------------------------------------------------------------------------------- -- Description : fast rejection of triangle / segment intersection test -------------------------------------------------------------------------------- */ /* used*/ ACP_tdxBool INT_fn_bFastRejectIntersectSegmentWithTriangle ( MTH3D_tdstVector *p_stVertexA, MTH3D_tdstVector *p_stVectAB, MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stVertex3 ) { MTH_tdxReal xMin; MTH_tdxReal xMax; MTH3D_tdstVector stVertexB; ACP_tdxBool bGreaterZero; MTH3D_M_vAddVector(&stVertexB, p_stVertexA, p_stVectAB); /* cas de rejection en X */ bGreaterZero = MTH_M_bGreaterZero ( p_stVectAB->xX ); /* min A, B */ xMin = bGreaterZero ? p_stVertexA->xX : stVertexB.xX; /* max 1, 2, 3 */ xMax = FUT_M_xMaxValue3 ( p_stVertex1->xX, p_stVertex2->xX, p_stVertex3->xX ); if ( MTH_M_bLess ( xMax, xMin ) ) { return FALSE; } /* max A, B */ xMax = bGreaterZero ? stVertexB.xX : p_stVertexA->xX; /* min 1, 2, 3 */ xMin = FUT_M_xMinValue3 ( p_stVertex1->xX, p_stVertex2->xX, p_stVertex3->xX ); if ( MTH_M_bLess ( xMax, xMin ) ) { return FALSE; } /* cas de rejection en Y */ bGreaterZero = MTH_M_bGreaterZero ( p_stVectAB->xY ); /* min A, B */ xMin = bGreaterZero ? p_stVertexA->xY : stVertexB.xY; /* max 1, 2, 3 */ xMax = FUT_M_xMaxValue3 ( p_stVertex1->xY, p_stVertex2->xY, p_stVertex3->xY ); if ( MTH_M_bLess ( xMax, xMin ) ) { return FALSE; } /* max A, B */ xMax = bGreaterZero ? stVertexB.xY : p_stVertexA->xY; /* min 1, 2, 3 */ xMin = FUT_M_xMinValue3 ( p_stVertex1->xY, p_stVertex2->xY, p_stVertex3->xY ); if ( MTH_M_bLess ( xMax, xMin ) ) { return FALSE; } /* cas de rejection en Z */ bGreaterZero = MTH_M_bGreaterZero ( p_stVectAB->xZ ); /* min A, B */ xMin = bGreaterZero ? p_stVertexA->xZ : stVertexB.xZ; /* max 1, 2, 3 */ xMax = FUT_M_xMaxValue3 ( p_stVertex1->xZ, p_stVertex2->xZ, p_stVertex3->xZ ); if ( MTH_M_bLess ( xMax, xMin ) ) { return FALSE; } /* max A, B */ xMax = bGreaterZero ? stVertexB.xZ : p_stVertexA->xZ; /* min 1, 2, 3 */ xMin = FUT_M_xMinValue3 ( p_stVertex1->xZ, p_stVertex2->xZ, p_stVertex3->xZ ); if ( MTH_M_bLess ( xMax, xMin ) ) { return FALSE; } return TRUE; } /* -------------------------------------------------------------------------------- -- Description : Segment with triangle intersection test -------------------------------------------------------------------------------- -- Creation date : 22 aug 1996 Author : FPI -------------------------------------------------------------------------------- */ /* teste l intersection d un segment et d un triangle */ /* used*/ ACP_tdxBool INT_fn_bIntersectSegmentWithTriangle ( MTH3D_tdstVector *p_stVertexA, MTH3D_tdstVector *p_stVectAB, MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stVertex3, MTH3D_tdstVector *p_stNormal, MTH_tdxReal xDPlan, MTH_tdxReal *p_xT, MTH3D_tdstVector *p_stHit ) { MTH_tdxReal xDotProdPara; MTH_tdxReal xDivid; MTH_tdxReal xT; #if 1 if ( !INT_fn_bFastRejectIntersectSegmentWithTriangle(p_stVertexA, p_stVectAB, p_stVertex1, p_stVertex2, p_stVertex3) ) return FALSE; #endif /* segment parallele au plan */ xDotProdPara = MTH3D_M_xDotProductVector ( p_stNormal, p_stVectAB ); /* backface du segment */ if ( MTH_M_bLessZero ( xDotProdPara ) ) { xDivid = MTH_M_xAdd ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertexA ), xDPlan ); if ( ( MTH_M_bGreaterZero ( xDivid ) ) && ( MTH_M_bLess ( xDivid, MTH_M_xNeg ( xDotProdPara ) ) ) ) { /* intersection segment plan du triangle */ xT = MTH_M_xNeg ( MTH_M_xDiv ( xDivid, xDotProdPara ) ); /* coordonnees du point d intersection */ MTH3D_M_vMulAddVector ( p_stHit, xT, p_stVectAB, p_stVertexA ); /* verification du point d intersection dans le triangle */ if ( INT_fn_bGetPointInTriangle ( p_stHit, p_stVertex1, p_stVertex2, p_stVertex3, p_stNormal ) ) { *p_xT = xT; return TRUE; } else { return FALSE; } } else { /* point d intersection en dehors du segment */ return FALSE; } } else { return FALSE; } } /* teste l intersection d un segment et d un triangle */ /* used*/ ACP_tdxBool INT_fn_bIntersectSegmentWithTriangle2 ( MTH3D_tdstVector *p_stVertexA, MTH3D_tdstVector *p_stVectAB, MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stVertex3, MTH3D_tdstVector *p_stNormal, MTH_tdxReal xDPlan, MTH_tdxReal xDotProduct, MTH_tdxReal *p_xT, MTH3D_tdstVector *p_stHit ) { MTH_tdxReal xDivid; MTH_tdxReal xT; #if 1 if ( !INT_fn_bFastRejectIntersectSegmentWithTriangle(p_stVertexA, p_stVectAB, p_stVertex1, p_stVertex2, p_stVertex3) ) return FALSE; #endif xDivid = MTH_M_xAdd ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertexA ), xDPlan ); /* jt 22/02/99 correction : intersection si acteur au contact et se déplace de epsilon vers la face ou est immobile if ( ( MTH_M_bGreaterZero ( xDivid ) ) && ( MTH_M_bLess ( xDivid, MTH_M_xNeg ( xDotProduct ) ) ) ) */ /* jt 140699 */ /* si xDotProduct == 0 à un epsilon près, il est possible de collisionner la face tangentiellemnt /* et il ne faut pas rejetter la collision à priori */ if (MTH_M_bIsNullWithEpsilon ( xDivid, MTH_M_xDoubleToReal(1e-3)) && MTH_M_bLess(xDotProduct, MTH_M_xDoubleToReal(-1e-3)) ) { *p_xT = MTH_C_ZERO; *p_stHit = *p_stVertexA; return TRUE; } /* end jt 140699 */ if ( ( MTH_M_bGreaterEqualZero ( xDivid ) ) && ( MTH_M_bLess ( xDivid, MTH_M_xNeg ( xDotProduct ) ) ) ) /* end jt */ { /* intersection segment plan du triangle */ xT = MTH_M_xNeg ( MTH_M_xDiv ( xDivid, xDotProduct ) ); /* coordonnees du point d intersection */ MTH3D_M_vMulAddVector ( p_stHit, xT, p_stVectAB, p_stVertexA ); /* verification du point d intersection dans le triangle */ if ( INT_fn_bGetPointInTriangle ( p_stHit, p_stVertex1, p_stVertex2, p_stVertex3, p_stNormal ) ) { *p_xT = xT; return TRUE; } else { return FALSE; } } else { /* point d intersection en dehors du segment */ return FALSE; } } /* -------------------------------------------------------------------------------- -- Description : Segment with triangle intersection test -------------------------------------------------------------------------------- -- Creation date : 22 aug 1996 Author : FPI -------------------------------------------------------------------------------- */ /* teste l intersection d un segment et d un triangle */ /* used*/ ACP_tdxBool INT_fn_bDetectIntersectSegmentWithTriangle ( MTH3D_tdstVector *p_stVertexA, MTH3D_tdstVector *p_stVectAB, MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stVertex3, MTH3D_tdstVector *p_stNormal, MTH_tdxReal xDPlan ) { MTH_tdxReal xDotProdPara; MTH_tdxReal xDivid; MTH_tdxReal xT; MTH3D_tdstVector stHit; #if 1 if ( !INT_fn_bFastRejectIntersectSegmentWithTriangle(p_stVertexA, p_stVectAB, p_stVertex1, p_stVertex2, p_stVertex3) ) return FALSE; #endif /* segment parallele au plan */ xDotProdPara = MTH3D_M_xDotProductVector ( p_stNormal, p_stVectAB ); /* backface du segment */ if ( MTH_M_bLessZero ( xDotProdPara ) ) { xDivid = MTH_M_xAdd ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertexA ), xDPlan ); /* intersection segment plan du triangle */ xT = MTH_M_xNeg ( MTH_M_xDiv ( xDivid, xDotProdPara ) ); /* verification du point d intersection sur le segment */ if ( MTH_M_bInUnitEqual ( xT ) ) { /* coordonnees du point d intersection */ MTH3D_M_vMulAddVector ( &stHit, xT, p_stVectAB, p_stVertexA ); /* verification du point d intersection dans le triangle */ return INT_fn_bGetPointInTriangle ( &stHit, p_stVertex1, p_stVertex2, p_stVertex3, p_stNormal ); } else { /* point d intersection en dehors du segment */ return FALSE; } } else { return FALSE; } } /* -------------------------------------------------------------------------------- -- Description : Semiaxe with triangle intersection test -------------------------------------------------------------------------------- -- Creation date : 12 nov 1996 Author : FPI -------------------------------------------------------------------------------- */ /* teste l intersection d une demi droite et d un triangle */ #if defined(ACTIVE_EDITOR) /*active editor only*/ ACP_tdxBool INT_fn_bIntersectSemiAxeWithTriangle ( MTH3D_tdstVector *p_stVertexA, MTH3D_tdstVector *p_stVectAB, MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stVertex3, MTH3D_tdstVector *p_stNormal, MTH_tdxReal xDPlan, ACP_tdxBool *bBack, MTH_tdxReal *p_xT, MTH3D_tdstVector *p_stHit ) { MTH_tdxReal xDotProd; /* droite parallele au plan */ xDotProd = MTH3D_M_xDotProductVector ( p_stNormal, p_stVectAB ); /* parallelisme de la droite */ if ( xDotProd != MTH_C_ZERO ) { /* backface */ *bBack = MTH_M_bGreaterEqualZero ( xDotProd ); /* intersection droite plan du triangle */ *p_xT = MTH_M_xNeg ( MTH_M_xDiv ( MTH_M_xAdd ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertexA ), xDPlan ), xDotProd ) ); /* verification du point d intersection sur la demi droite */ if ( MTH_C_ZERO <= *p_xT ) { /* coordonnees du point d intersection */ MTH3D_M_vMulAddVector ( p_stHit, *p_xT, p_stVectAB, p_stVertexA ); /* verification du point d intersection dans le triangle */ return INT_fn_bGetPointInTriangle ( p_stHit, p_stVertex1, p_stVertex2, p_stVertex3, p_stNormal ); } else /* point d intersection en dehors de la demi droite */ return FALSE; } else return FALSE; } #endif /*--------------------------------------------------------------------------------------*/ /* Name : INT_fn_bIntersectTriangleWithBoxWithHit*/ /* Author : Thierry QUERE*/ /* Date : 04/03/98*/ /* Description : Idem as before but returns some important results*/ /*--------------------------------------------------------------------------------------*/ /* used*/ ACP_tdxBool INT_fn_bIntersectTriangleWithBoxWithHit ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVertex2, MTH3D_tdstVector *p_stVertex3, MTH3D_tdstVector *p_stNormal, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint, MTH3D_tdstVector *p_stHit) { MTH3D_tdstVector stDelta; MTH3D_tdstVector stNegDelta; MTH3D_tdstVector stEdge; MTH3D_tdstVector stHit; MTH_tdxReal xDPlan; MTH_tdxReal xTDiag; MTH_tdxReal xDotProd; MTH_tdxReal xDivid; unsigned long ulVertex1Test, ulVertex2Test, ulVertex3Test; /* un point du triangle est dans la boite */ if ( (ulVertex1Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex1, p_stMinPoint, p_stMaxPoint )) == COL_C_ulNullMask ) return TRUE; if ( (ulVertex2Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex2, p_stMinPoint, p_stMaxPoint )) == COL_C_ulNullMask ) return TRUE; if ( (ulVertex3Test = INT_fn_ulGetPositionPointWithBox ( p_stVertex3, p_stMinPoint, p_stMaxPoint )) == COL_C_ulNullMask ) return TRUE; /* les trois points sont dans le meme demi espace exterieur */ if ( ulVertex1Test & ulVertex2Test & ulVertex3Test ) return FALSE; /* delta de la boite */ MTH3D_M_vSubVector ( &stDelta, p_stMaxPoint, p_stMinPoint ); MTH3D_M_vNegVector ( &stNegDelta, &stDelta ); /* test sur les demi espaces des aretes */ ulVertex1Test |= INT_fn_ulGetPositionPointWithEdgeBox ( p_stVertex1, p_stMinPoint, p_stMaxPoint, &stDelta, &stNegDelta ) << 8; ulVertex2Test |= INT_fn_ulGetPositionPointWithEdgeBox ( p_stVertex2, p_stMinPoint, p_stMaxPoint, &stDelta, &stNegDelta ) << 8; ulVertex3Test |= INT_fn_ulGetPositionPointWithEdgeBox ( p_stVertex3, p_stMinPoint, p_stMaxPoint, &stDelta, &stNegDelta ) << 8; if ( ulVertex1Test & ulVertex2Test & ulVertex3Test ) return FALSE; if (p_stHit == NULL) p_stHit = &stHit; /* une arete du triangle intersecte la boite */ if ( (ulVertex1Test & ulVertex2Test) == COL_C_ulNullMask ) { MTH3D_M_vSubVector ( &stEdge, p_stVertex2, p_stVertex1 ); if ( INT_fn_bIntersectEdgeWithBoxWithHit ( p_stVertex1, p_stVertex2, &stEdge, p_stMinPoint, p_stMaxPoint, ulVertex1Test|ulVertex2Test , p_stHit) ) return TRUE; } if ( (ulVertex1Test & ulVertex3Test) == COL_C_ulNullMask ) { MTH3D_M_vSubVector ( &stEdge, p_stVertex3, p_stVertex1 ); if ( INT_fn_bIntersectEdgeWithBoxWithHit ( p_stVertex1, p_stVertex3, &stEdge, p_stMinPoint, p_stMaxPoint, ulVertex1Test|ulVertex3Test, p_stHit ) ) return TRUE; } if ( (ulVertex2Test & ulVertex3Test) == COL_C_ulNullMask ) { MTH3D_M_vSubVector ( &stEdge, p_stVertex3, p_stVertex2 ); if ( INT_fn_bIntersectEdgeWithBoxWithHit ( p_stVertex2, p_stVertex3, &stEdge, p_stMinPoint, p_stMaxPoint, ulVertex2Test|ulVertex3Test, p_stHit ) ) return TRUE; } /* plan du triangle */ xDPlan = MTH_M_xNeg ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertex1 ) ); /* intersections avec les quatre diagonales */ /* le produit scalaire nous evite le plan parallele a la diagonale */ xDotProd = MTH_M_xMul ( p_stNormal->xX, stDelta.xX ) + MTH_M_xMul ( p_stNormal->xY, stDelta.xY ) + MTH_M_xMul ( p_stNormal->xZ, stDelta.xZ ); if ( MTH_M_bDifferentZero ( xDotProd ) ) { xDivid = MTH_M_xMul ( p_stNormal->xX, p_stMinPoint->xX ) + MTH_M_xMul ( p_stNormal->xY, p_stMinPoint->xY ) + MTH_M_xMul ( p_stNormal->xZ, p_stMinPoint->xZ ) + xDPlan; xTDiag = MTH_M_xNeg ( MTH_M_xDiv ( xDivid, xDotProd ) ); if ( MTH_M_bInUnitEqual ( xTDiag ) ) { p_stHit->xX = MTH_M_xMulAdd ( stDelta.xX, xTDiag, p_stMinPoint->xX ); p_stHit->xY = MTH_M_xMulAdd ( stDelta.xY, xTDiag, p_stMinPoint->xY ); p_stHit->xZ = MTH_M_xMulAdd ( stDelta.xZ, xTDiag, p_stMinPoint->xZ ); if ( INT_fn_bGetPointInTriangle ( p_stHit, p_stVertex1, p_stVertex2, p_stVertex3, p_stNormal ) ) return TRUE; } } xDotProd = MTH_M_xMul ( p_stNormal->xX, stDelta.xX ) + MTH_M_xMul ( p_stNormal->xY, stNegDelta.xY ) + MTH_M_xMul ( p_stNormal->xZ, stDelta.xZ ); if ( MTH_M_bDifferentZero ( xDotProd ) ) { xDivid = MTH_M_xMul ( p_stNormal->xX, p_stMinPoint->xX ) + MTH_M_xMul ( p_stNormal->xY, p_stMaxPoint->xY ) + MTH_M_xMul ( p_stNormal->xZ, p_stMinPoint->xZ ) + xDPlan; xTDiag = MTH_M_xNeg ( MTH_M_xDiv ( xDivid, xDotProd ) ); if ( MTH_M_bInUnitEqual ( xTDiag ) ) { p_stHit->xX = MTH_M_xMulAdd ( stDelta.xX, xTDiag, p_stMinPoint->xX ); p_stHit->xY = MTH_M_xMulAdd ( stNegDelta.xY, xTDiag, p_stMaxPoint->xY ); p_stHit->xZ = MTH_M_xMulAdd ( stDelta.xZ, xTDiag, p_stMinPoint->xZ ); if ( INT_fn_bGetPointInTriangle ( p_stHit, p_stVertex1, p_stVertex2, p_stVertex3, p_stNormal ) ) return TRUE; } } xDotProd = MTH_M_xMul ( p_stNormal->xX, stDelta.xX ) + MTH_M_xMul ( p_stNormal->xY, stDelta.xY ) + MTH_M_xMul ( p_stNormal->xZ, stNegDelta.xZ ); if ( MTH_M_bDifferentZero ( xDotProd ) ) { xDivid = MTH_M_xMul ( p_stNormal->xX, p_stMinPoint->xX ) + MTH_M_xMul ( p_stNormal->xY, p_stMinPoint->xY ) + MTH_M_xMul ( p_stNormal->xZ, p_stMaxPoint->xZ ) + xDPlan; xTDiag = MTH_M_xNeg ( MTH_M_xDiv ( xDivid, xDotProd ) ); if ( MTH_M_bInUnitEqual ( xTDiag ) ) { p_stHit->xX = MTH_M_xMulAdd ( stDelta.xX, xTDiag, p_stMinPoint->xX ); p_stHit->xY = MTH_M_xMulAdd ( stDelta.xY, xTDiag, p_stMinPoint->xY ); p_stHit->xZ = MTH_M_xMulAdd ( stNegDelta.xZ, xTDiag, p_stMaxPoint->xZ ); if ( INT_fn_bGetPointInTriangle ( p_stHit, p_stVertex1, p_stVertex2, p_stVertex3, p_stNormal ) ) return TRUE; } } xDotProd = MTH_M_xMul ( p_stNormal->xX, stDelta.xX ) + MTH_M_xMul ( p_stNormal->xY, stNegDelta.xY ) + MTH_M_xMul ( p_stNormal->xZ, stNegDelta.xZ ); if ( MTH_M_bDifferentZero ( xDotProd ) ) { xDivid = MTH_M_xMul ( p_stNormal->xX, p_stMinPoint->xX ) + MTH_M_xMul ( p_stNormal->xY, p_stMaxPoint->xY ) + MTH_M_xMul ( p_stNormal->xZ, p_stMaxPoint->xZ ) + xDPlan; xTDiag = MTH_M_xNeg ( MTH_M_xDiv ( xDivid, xDotProd ) ); if ( MTH_M_bInUnitEqual ( xTDiag ) ) { p_stHit->xX = MTH_M_xMulAdd ( stDelta.xX, xTDiag, p_stMinPoint->xX ); p_stHit->xY = MTH_M_xMulAdd ( stNegDelta.xY, xTDiag, p_stMaxPoint->xY ); p_stHit->xZ = MTH_M_xMulAdd ( stNegDelta.xZ, xTDiag, p_stMaxPoint->xZ ); if ( INT_fn_bGetPointInTriangle ( p_stHit, p_stVertex1, p_stVertex2, p_stVertex3, p_stNormal ) ) return TRUE; } } return FALSE; } /* -------------------------------------------------------------------------------- -- Description : Inclusion of a point in a sphere -------------------------------------------------------------------------------- -- Creation date : 17 jan 1997 Author : FPI -------------------------------------------------------------------------------- */ /* teste l inclusion d un point dans une sphere */ /* used*/ ACP_tdxBool INT_fn_bGetInclusionPointInSphere ( MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stSphereCenter, MTH_tdxReal xSphereRadius ) { return MTH_M_bLessEqual ( MTH3D_M_xVectorGapSqr ( p_stPoint, p_stSphereCenter ), MTH_M_xSqr ( xSphereRadius ) ); } /* -------------------------------------------------------------------------------- -- Description : fast rejection of sphere / segment intersection test -------------------------------------------------------------------------------- */ /* used*/ ACP_tdxBool INT_fn_bFastRejectIntersectSegmentWithSphere ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stSphereCenter, MTH_tdxReal xSphereRadius ) { MTH3D_tdstVector stM; MTH3D_tdstVector stMP; MTH_tdxReal xNegSphereRadius; MTH3D_M_vSubVector(&stM, p_stVertex1, p_stSphereCenter); MTH3D_M_vAddVector(&stMP, &stM, p_stVect12); xNegSphereRadius = MTH_M_xNeg(xSphereRadius); if (MTH_M_bGreaterZero(p_stVect12->xX)) { if (MTH_M_bGreater(stM.xX,xSphereRadius)) return FALSE; if (MTH_M_bLess(stMP.xX,xNegSphereRadius)) return FALSE; } else { if (MTH_M_bLess(stM.xX,xNegSphereRadius)) return FALSE; if (MTH_M_bGreater(stMP.xX,xSphereRadius)) return FALSE; } if (MTH_M_bGreaterZero(p_stVect12->xY)) { if (MTH_M_bGreater(stM.xY,xSphereRadius)) return FALSE; if (MTH_M_bLess(stMP.xY,xNegSphereRadius)) return FALSE; } else { if (MTH_M_bLess(stM.xY,xNegSphereRadius)) return FALSE; if (MTH_M_bGreater(stMP.xY,xSphereRadius)) return FALSE; } if (MTH_M_bGreaterZero(p_stVect12->xZ)) { if (MTH_M_bGreater(stM.xZ,xSphereRadius)) return FALSE; if (MTH_M_bLess(stMP.xZ,xNegSphereRadius)) return FALSE; } else { if (MTH_M_bLess(stM.xZ,xNegSphereRadius)) return FALSE; if (MTH_M_bGreater(stMP.xZ,xSphereRadius)) return FALSE; } return TRUE; } /* -------------------------------------------------------------------------------- -- Description : Segment with sphere intersection test -------------------------------------------------------------------------------- -- Creation date : 03 oct 1996 Author : FPI -------------------------------------------------------------------------------- */ /* teste l intersection d un segment et d une sphere */ /* used*/ ACP_tdxBool INT_fn_bIntersectSegmentWithSphere ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stSphereCenter, MTH_tdxReal xSphereRadius, MTH_tdxReal *p_xT, MTH3D_tdstVector *p_stHit, MTH3D_tdstVector *p_stNormal ) { MTH3D_tdstVector stVectS1; MTH_tdxReal xA; MTH_tdxReal xB; MTH_tdxReal xC; MTH_tdxReal xT1; MTH_tdxReal xT2; MTH_tdxReal xInvR; MTH_tdxReal xT; #if 1 if ( !INT_fn_bFastRejectIntersectSegmentWithSphere(p_stVertex1, p_stVect12, p_stSphereCenter, xSphereRadius) ) { return FALSE; } #endif MTH3D_M_vSubVector ( &stVectS1, p_stVertex1, p_stSphereCenter ); xA = MTH3D_M_xSqrVector ( p_stVect12 ); xB = MTH3D_M_xDotProductVector ( p_stVect12, &stVectS1 ); xB = MTH_M_xAdd ( xB, xB ); /* instead of multpiplication by 2, use add*/ xC = MTH_M_xSub ( MTH3D_M_xSqrVector ( &stVectS1 ), MTH_M_xSqr ( xSphereRadius ) ); /* resolution du trinome */ switch ( INT_fn_xTrinomeResolution ( xA, xB, xC, &xT1, &xT2 ) ) { case INT_C_xTwoSolutions : xT = MTH_M_xMin ( xT1, xT2 ); if ( MTH_M_bInUnitEqual ( xT ) ) { *p_xT = xT; MTH3D_M_vMulAddVector ( p_stHit, xT, p_stVect12, p_stVertex1 ); MTH3D_M_vSubVector ( p_stNormal, p_stHit, p_stSphereCenter ); xInvR = MTH_M_xInv ( xSphereRadius ); MTH3D_M_vMulScalarVector( p_stNormal, xInvR, p_stNormal ); return TRUE; } else { return FALSE; } break; case INT_C_xOneSolution : if ( MTH_M_bInUnitEqual ( xT1 ) ) { *p_xT = xT1; MTH3D_M_vMulAddVector ( p_stHit, xT1, p_stVect12, p_stVertex1 ); MTH3D_M_vSubVector ( p_stNormal, p_stHit, p_stSphereCenter ); xInvR = MTH_M_xInv ( xSphereRadius ); MTH3D_M_vMulScalarVector( p_stNormal, xInvR, p_stNormal ); return TRUE; } break; default : break; } return FALSE; } /* -------------------------------------------------------------------------------- -- Description : Segment with sphere intersection detection -------------------------------------------------------------------------------- -- Creation date : 08 oct 1998 Author : FBF -- !!!! OPTIMIZED !!!! -------------------------------------------------------------------------------- */ /* detecte l intersection d un segment et d une sphere */ /* used*/ ACP_tdxBool INT_fn_bDetectIntersectSegmentWithSphere ( MTH3D_tdstVector *p_stVertexA, MTH3D_tdstVector *p_stVectAB, MTH3D_tdstVector *p_stSphereCenter, MTH_tdxReal xSphereRadius ) { MTH3D_tdstVector stVectCA; MTH3D_tdstVector stVectCB; MTH_tdxReal xdist,xTemp; MTH_tdxReal xNegSphereRadius; MTH_tdxReal xSpecialRadius; MTH_tdxReal NormAB; /* C means the center of the sphere*/ /* fast rejection*/ MTH3D_M_vSubVector(&stVectCA, p_stVertexA, p_stSphereCenter); MTH3D_M_vAddVector(&stVectCB, &stVectCA, p_stVectAB); xNegSphereRadius = MTH_M_xNeg(xSphereRadius); xSpecialRadius = MTH_M_xSqr(xSphereRadius); /* B is inside the sphere*/ if ( MTH_M_bLessEqual(MTH3D_M_xSqrVector(&stVectCB), xSpecialRadius) ) return TRUE; /* A is inside the sphere*/ if ( MTH_M_bLessEqual(MTH3D_M_xSqrVector(&stVectCA), xSpecialRadius) ) return TRUE; if (MTH_M_bGreaterZero(p_stVectAB->xX)) { if (MTH_M_bGreater(stVectCA.xX,xSphereRadius)) return FALSE; if (MTH_M_bLess(stVectCB.xX,xNegSphereRadius)) return FALSE; } else { if (MTH_M_bLess(stVectCA.xX,xNegSphereRadius)) return FALSE; if (MTH_M_bGreater(stVectCB.xX,xSphereRadius)) return FALSE; } if (MTH_M_bGreaterZero(p_stVectAB->xY)) { if (MTH_M_bGreater(stVectCA.xY,xSphereRadius)) return FALSE; if (MTH_M_bLess(stVectCB.xY,xNegSphereRadius)) return FALSE; } else { if (MTH_M_bLess(stVectCA.xY,xNegSphereRadius)) return FALSE; if (MTH_M_bGreater(stVectCB.xY,xSphereRadius)) return FALSE; } if (MTH_M_bGreaterZero(p_stVectAB->xZ)) { if (MTH_M_bGreater(stVectCA.xZ,xSphereRadius)) return FALSE; if (MTH_M_bLess(stVectCB.xZ,xNegSphereRadius)) return FALSE; } else { if (MTH_M_bLess(stVectCA.xZ,xNegSphereRadius)) return FALSE; if (MTH_M_bGreater(stVectCB.xZ,xSphereRadius)) return FALSE; } /* check projection of C is on [AB)*/ xTemp = MTH3D_M_xDotProductVector (&stVectCA, p_stVectAB); if (MTH_M_bGreater(xTemp,MTH_C_ZERO)) { return FALSE; } /* compute value to test :*/ NormAB = MTH3D_M_xSqrVector (p_stVectAB); /* check projection of C is on [BA)*/ if (MTH_M_bGreater(MTH_M_xNeg(xTemp),NormAB)) return FALSE; /* here, we are sure that projection of C is on [AB]*/ /* there is certainly a collision...*/ /* complete check */ xSpecialRadius = MTH_M_xMul(xSpecialRadius,NormAB); /* first test :*/ /* check if (x2*y1 - x1*y2)² > R² * (AB)²*/ xdist = MTH_M_xSub(MTH_M_xMul(stVectCA.xX,p_stVectAB->xY),MTH_M_xMul(stVectCA.xY,p_stVectAB->xX)); xdist = MTH_M_xSqr(xdist); if (MTH_M_bGreaterEqual(xdist,xSpecialRadius)) return FALSE; /* if not*/ /* check if (x2*y1 - x1*y2)² + (x2*z1 - x1*z2)² > R² * (AB)²*/ xTemp = MTH_M_xSub(MTH_M_xMul(stVectCA.xX,p_stVectAB->xZ),MTH_M_xMul(stVectCA.xZ,p_stVectAB->xX)); xdist = MTH_M_xAdd(MTH_M_xSqr(xTemp),xdist); if (MTH_M_bGreaterEqual(xdist,xSpecialRadius)) return FALSE; /* if not*/ /* check if (x2*y1 - x1*y2)² + (x2*z1 - x1*z2)² + (y2*z1 - y1*z2)² > R² * (AB)²*/ xTemp = MTH_M_xSub(MTH_M_xMul(stVectCA.xY,p_stVectAB->xZ),MTH_M_xMul(stVectCA.xZ,p_stVectAB->xY)); xdist = MTH_M_xAdd(MTH_M_xSqr(xTemp),xdist); if (MTH_M_bGreaterEqual(xdist,xSpecialRadius)) return FALSE; /* if not, then the distance between the sphere center and the segment is < R */ return TRUE; } /* detecte l intersection d un segment et d une sphere */ /*ACP_tdxBool INT_fn_bDetectIntersectSegmentWithSphere ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stSphereCenter, MTH_tdxReal xSphereRadius ) { MTH3D_tdstVector stVectS1; MTH3D_tdstVector stVectS2; MTH_tdxReal xA; MTH_tdxReal xB; MTH_tdxReal xC; MTH_tdxReal xT; #if 1 if ( !INT_fn_bFastRejectIntersectSegmentWithSphere(p_stVertex1, p_stVect12, p_stSphereCenter, xSphereRadius) ) return FALSE; #endif xA = MTH3D_M_xSqrVector ( p_stVect12 ); if ( MTH_M_bEqualZero ( xA ) ) return FALSE; MTH3D_M_vSubVector ( &stVectS1, p_stVertex1, p_stSphereCenter ); if ( MTH_M_bLessEqual ( MTH3D_M_xSqrVector ( &stVectS1 ), MTH_M_xSqr ( xSphereRadius ) ) ) { return TRUE; } else { xB = MTH3D_M_xDotProductVector ( p_stVect12, &stVectS1 ); xB = MTH_M_xAdd ( xB, xB ); // instead of multpiplication by 2, use add xC = MTH_M_xSub ( MTH3D_M_xSqrVector ( &stVectS1 ), MTH_M_xSqr ( xSphereRadius ) ); // delta if ( MTH_M_xTrinomeDelta ( xA, xB, xC ) >= MTH_C_ZERO ) { // inclusion du point 2 MTH3D_M_vAddVector ( &stVectS2, &stVectS1, p_stVect12 ); if ( MTH_M_bLessEqual ( MTH3D_M_xSqrVector ( &stVectS2 ), MTH_M_xSqr ( xSphereRadius ) ) ) { return TRUE; } else { // sans projection xT = MTH3D_M_xDotProductVector ( p_stVect12, &stVectS1 ); if ( ( xT <= MTH_C_ZERO ) && ( xT >= MTH_M_xNeg ( xA ) ) ) { return TRUE; } else { return FALSE; } } } else { return FALSE; } } return FALSE; } */ /* -------------------------------------------------------------------------------- -- Description : fast rejection of sphere / semiaxe intersection test -------------------------------------------------------------------------------- */ #if defined(ACTIVE_EDITOR) /*active editor only*/ ACP_tdxBool INT_fn_bFastRejectIntersectSemiaxeWithSphere ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stSphereCenter, MTH_tdxReal xSphereRadius ) { MTH_tdxReal xMin; MTH_tdxReal xMax; /* far extremity of the segment*/ MTH3D_tdstVector stvertex2; MTH3D_M_vAddVector(&stvertex2, p_stVertex1, p_stVect12); /* cas de rejection en X */ if ( MTH_M_bGreaterZero ( p_stVect12->xX ) ) { xMin = p_stVertex1->xX; xMax = MTH_M_xAdd ( p_stSphereCenter->xX, xSphereRadius ); } else { xMin = MTH_M_xSub ( p_stSphereCenter->xX, xSphereRadius ); xMax = p_stVertex1->xX; } if ( MTH_M_bLess ( xMax, xMin ) ) { return FALSE; } /* cas de rejection en Y */ if ( MTH_M_bGreaterZero ( p_stVect12->xY ) ) { xMin = p_stVertex1->xY; xMax = MTH_M_xAdd ( p_stSphereCenter->xY, xSphereRadius ); } else { xMin = MTH_M_xSub ( p_stSphereCenter->xY, xSphereRadius ); xMax = p_stVertex1->xY; } if ( MTH_M_bLess ( xMax, xMin ) ) { return FALSE; } /* cas de rejection en Z */ if ( MTH_M_bGreaterZero ( p_stVect12->xZ ) ) { xMin = p_stVertex1->xZ; xMax = MTH_M_xAdd ( p_stSphereCenter->xZ, xSphereRadius ); } else { xMin = MTH_M_xSub ( p_stSphereCenter->xZ, xSphereRadius ); xMax = p_stVertex1->xZ; } if ( MTH_M_bLess ( xMax, xMin ) ) { return FALSE; } return TRUE; } #endif /* -------------------------------------------------------------------------------- -- Description : Semiaxe with sphere intersection test -------------------------------------------------------------------------------- -- Creation date : 12 nov 1996 Author : FPI -------------------------------------------------------------------------------- */ /* teste l intersection d une demi droite et d une sphere */ #if defined(ACTIVE_EDITOR) /*active editor only*/ ACP_tdxBool INT_fn_bIntersectSemiAxeWithSphere ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stSphereCenter, MTH_tdxReal xSphereRadius, ACP_tdxBool *bBack, MTH_tdxReal *p_xT, MTH3D_tdstVector *p_stHit, MTH3D_tdstVector *p_stNormal ) { MTH3D_tdstVector stVectS1; MTH_tdxReal xA; MTH_tdxReal xB; MTH_tdxReal xC; MTH_tdxReal xT1; MTH_tdxReal xT2; MTH_tdxReal xInvR; #if 1 if ( !INT_fn_bFastRejectIntersectSemiaxeWithSphere(p_stVertex1, p_stVect12, p_stSphereCenter, xSphereRadius) ) return FALSE; #endif MTH3D_M_vSubVector ( &stVectS1, p_stVertex1, p_stSphereCenter ); xA = MTH3D_M_xSqrVector ( p_stVect12 ); xB = MTH3D_M_xDotProductVector ( p_stVect12, &stVectS1 ); xB = MTH_M_xAdd ( xB, xB ); /* instead of multpiplication by 2, use add*/ xC = MTH_M_xSub ( MTH3D_M_xSqrVector ( &stVectS1 ), MTH_M_xSqr ( xSphereRadius ) ); /* resolution du trinome */ switch ( INT_fn_xTrinomeResolution ( xA, xB, xC, &xT1, &xT2 ) ) { case INT_C_xTwoSolutions : *p_xT = MTH_M_xMin ( xT1, xT2 ); if ( MTH_C_ZERO <= *p_xT ) { *bBack = FALSE; MTH3D_M_vMulAddVector ( p_stHit, *p_xT, p_stVect12, p_stVertex1 ); MTH3D_M_vSubVector ( p_stNormal, p_stHit, p_stSphereCenter ); xInvR = MTH_M_xInv ( xSphereRadius ); MTH3D_M_vMulScalarVector( p_stNormal, xInvR, p_stNormal ); return TRUE; } else { *p_xT = MTH_M_xMax ( xT1, xT2 ); if ( MTH_C_ZERO <= *p_xT ) { *bBack = TRUE; MTH3D_M_vMulAddVector ( p_stHit, *p_xT, p_stVect12, p_stVertex1 ); MTH3D_M_vSubVector ( p_stNormal, p_stHit, p_stSphereCenter ); xInvR = MTH_M_xInv ( xSphereRadius ); MTH3D_M_vMulScalarVector( p_stNormal, xInvR, p_stNormal ); return TRUE; } } break; case INT_C_xOneSolution : if ( MTH_C_ZERO <= xT1 ) { *bBack = TRUE; *p_xT = xT1; MTH3D_M_vMulAddVector ( p_stHit, *p_xT, p_stVect12, p_stVertex1 ); MTH3D_M_vSubVector ( p_stNormal, p_stHit, p_stSphereCenter ); xInvR = MTH_M_xInv ( xSphereRadius ); MTH3D_M_vMulScalarVector( p_stNormal, xInvR, p_stNormal ); return TRUE; } break; default : break; } return FALSE; } #endif /* -------------------------------------------------------------------------------- -- Description : Semiaxe with sphere intersection detection -------------------------------------------------------------------------------- -- Creation date : 06 feb 1997 Author : FPI -------------------------------------------------------------------------------- */ /* detecte l intersection d une demi droite et d une sphere */ /* Vect12 n'est pas considéré comme étant normé*/ /* optimised by FBF*/ #ifdef ACTIVE_EDITOR /* active editor only*/ ACP_tdxBool INT_fn_bDetectIntersectSemiAxeWithSphere ( MTH3D_tdstVector *p_stPointA, MTH3D_tdstVector *p_stVectAB, MTH3D_tdstVector *p_stSphereCenter, MTH_tdxReal xSphereRadius ) { MTH3D_tdstVector stVectAC; MTH_tdxReal xACNorm; MTH_tdxReal xABNorm; MTH_tdxReal xDist; MTH_tdxReal xRadiusSqr; MTH_tdxReal xDotPdt; /* compute distance AC*/ MTH3D_M_vSubVector (&stVectAC, p_stPointA, p_stSphereCenter); xACNorm = MTH3D_M_xSqrVector (&stVectAC); xRadiusSqr = MTH_M_xSqr(xSphereRadius); /* if A is inside the sphere, return TRUE;*/ if (MTH_M_bGreaterEqual(xRadiusSqr,xACNorm)) return TRUE; /* compute dot product to see where the sphere center is according to the semiaxe beginning*/ xDotPdt = MTH3D_M_xDotProductVector (p_stVectAB, &stVectAC); /* if dot product is <= 0, then the sphere is on the wrong side --> return FALSE;*/ if (MTH_M_bLessEqual(xDotPdt,MTH_C_ZERO)) return FALSE; /* complete calculation, general case.*/ xABNorm = MTH3D_M_xSqrVector (p_stVectAB); xDotPdt = MTH_M_xSqr(xDotPdt); xDist = MTH_M_xSub(xACNorm, MTH_M_xDiv(xDotPdt,xABNorm)); if (MTH_M_bGreaterEqual(xRadiusSqr,xDist)) return TRUE; } #endif /* -------------------------------------------------------------------------------- -- Description : Segment with cylinder intersection test -------------------------------------------------------------------------------- -- Creation date : 04 dec 1996 Author : FPI -------------------------------------------------------------------------------- */ /* teste l intersection d un segment et d un cylindre */ /* used*/ ACP_tdxBool INT_fn_bIntersectSegmentWithCylinder ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stVertexA, MTH3D_tdstVector *p_stVectAB, MTH_tdxReal xCylinderRadius, MTH_tdxReal *p_xTSegment, MTH3D_tdstVector *p_stHitSegment, MTH3D_tdstVector *p_stHitLine ) { MTH3D_tdstVector stVectA1; MTH3D_tdstVector stVectP; MTH3D_tdstVector stVectQ; MTH_tdxReal xTLine; MTH_tdxReal xK; MTH_tdxReal xL; MTH_tdxReal xM; MTH_tdxReal xA; MTH_tdxReal xB; MTH_tdxReal xC; MTH_tdxReal xT1; MTH_tdxReal xT2; MTH_tdxReal xTmp; #if 1 MTH_tdxReal xMin; MTH_tdxReal xMax; ACP_tdxBool bGreaterZero1, bGreaterZero2; /* INT_g_lIntTriangle ++;*/ MTH3D_M_vAddVector(&stVectP, p_stVertex1, p_stVect12); MTH3D_M_vAddVector(&stVectA1, p_stVertexA, p_stVectAB); /* cas de rejection en X */ bGreaterZero1 = MTH_M_bGreaterZero ( p_stVect12->xX ); bGreaterZero2 = MTH_M_bGreaterZero ( p_stVectAB->xX ); /* min 1, 2 */ xMin = bGreaterZero1 ? p_stVertex1->xX : stVectP.xX; /* max A, B */ xMax = bGreaterZero2 ? stVectA1.xX : p_stVertexA->xX; if ( MTH_M_bLess ( MTH_M_xAdd ( xMax, xCylinderRadius ), xMin ) ) { return FALSE; } /* max 1, 2 */ xMax = bGreaterZero1 ? stVectP.xX : p_stVertex1->xX; /* min A, B */ xMin = bGreaterZero2 ? p_stVertexA->xX : stVectA1.xX; if ( MTH_M_bLess ( xMax, MTH_M_xSub ( xMin, xCylinderRadius ) ) ) { return FALSE; } /* cas de rejection en Y */ bGreaterZero1 = MTH_M_bGreaterZero ( p_stVect12->xY ); bGreaterZero2 = MTH_M_bGreaterZero ( p_stVectAB->xY ); /* min 1, 2 */ xMin = bGreaterZero1 ? p_stVertex1->xY : stVectP.xY; /* max A, B */ xMax = bGreaterZero2 ? stVectA1.xY : p_stVertexA->xY; if ( MTH_M_bLess ( MTH_M_xAdd ( xMax, xCylinderRadius ), xMin ) ) { return FALSE; } /* max 1, 2 */ xMax = bGreaterZero1 ? stVectP.xY : p_stVertex1->xY; /* min A, B */ xMin = bGreaterZero2 ? p_stVertexA->xY : stVectA1.xY; if ( MTH_M_bLess ( xMax, MTH_M_xSub ( xMin, xCylinderRadius ) ) ) { return FALSE; } /* cas de rejection en Z */ bGreaterZero1 = MTH_M_bGreaterZero ( p_stVect12->xZ ); bGreaterZero2 = MTH_M_bGreaterZero ( p_stVectAB->xZ ); /* min 1, 2 */ xMin = bGreaterZero1 ? p_stVertex1->xZ : stVectP.xZ; /* max A, B */ xMax = bGreaterZero2 ? stVectA1.xZ : p_stVertexA->xZ; if ( MTH_M_bLess ( MTH_M_xAdd ( xMax, xCylinderRadius ), xMin ) ) { return FALSE; } /* max 1, 2 */ xMax = bGreaterZero1 ? stVectP.xZ : p_stVertex1->xZ; /* min A, B */ xMin = bGreaterZero2 ? p_stVertexA->xZ : stVectA1.xZ; if ( MTH_M_bLess ( xMax, MTH_M_xSub ( xMin, xCylinderRadius ) ) ) { return FALSE; } #endif #if 1 MTH3D_M_vSubVector ( &stVectA1, p_stVertex1, p_stVertexA ); xM = MTH3D_M_xSqrVector ( p_stVectAB ); if ( MTH_M_bEqualZero ( xM ) ) return FALSE; xM = MTH_M_xInv ( xM ); xK = MTH3D_M_xDotProductVector ( p_stVectAB, p_stVect12 ); xL = MTH3D_M_xDotProductVector ( p_stVectAB, &stVectA1 ); xTmp = MTH_M_xMul ( xK, xM ); MTH3D_M_vMulScalarVector ( &stVectP, xTmp, p_stVectAB ); if ( !(MTH3D_M_bEqualVector ( &stVectP, p_stVect12 )) ) { MTH3D_M_vSubVector ( &stVectP, &stVectP, p_stVect12 ); xTmp = MTH_M_xMul ( xL, xM ); MTH3D_M_vMulScalarVector ( &stVectQ, xTmp, p_stVectAB ); MTH3D_M_vSubVector ( &stVectQ, &stVectQ, &stVectA1 ); xA = MTH3D_M_xSqrVector ( &stVectP ); xB = MTH3D_M_xDotProductVector ( &stVectP, &stVectQ ); xB = MTH_M_xAdd ( xB, xB ); /* instead of multpiplication by 2, use add*/ xC = MTH_M_xSub ( MTH3D_M_xSqrVector ( &stVectQ ), MTH_M_xSqr ( xCylinderRadius ) ); /* resolution du trinome */ switch ( INT_fn_xTrinomeResolution ( xA, xB, xC, &xT1, &xT2 ) ) { case INT_C_xTwoSolutions : *p_xTSegment = MTH_M_xMin ( xT1, xT2 ); // *p_xTSegment = MTH_M_xMax ( xT1, xT2 ); if ( !(MTH_M_bInUnitEqual ( *p_xTSegment )) ) { return FALSE; } break; case INT_C_xNoSolution : return FALSE; case INT_C_xOneSolution : if ( MTH_M_bInUnitEqual ( xT1 ) ) { *p_xTSegment = xT1; } else return FALSE; break; default : break; } MTH3D_M_vMulAddVector ( p_stHitSegment, *p_xTSegment, p_stVect12, p_stVertex1 ); xTLine = MTH_M_xMul ( MTH_M_xAdd ( MTH_M_xMul ( xK, *p_xTSegment ), xL ), xM ); // xTLine = *p_xTSegment; // if (MTH_M_bGreater(xTLine,MTH_C_ONE)) xTLine = MTH_C_ONE; // if (MTH_M_bLess(xTLine,MTH_C_ZERO)) xTLine = MTH_C_ZERO; if ( MTH_M_bInUnitEqual ( xTLine ) ) // if ( MTH_M_bGreater(xTLine,MTH_M_xDoubleToReal(-0.1)) && MTH_M_bLess(xTLine,MTH_M_xDoubleToReal(1.1)) ) { MTH3D_M_vMulAddVector ( p_stHitLine, xTLine, p_stVectAB, p_stVertexA ); return TRUE; } else { return FALSE; } } else { return FALSE; } #endif return FALSE; } /* -------------------------------------------------------------------------------- -- Description : Semiaxe with cone intersection test -------------------------------------------------------------------------------- -- Creation date : 08 apr 1997 Author : FPI -------------------------------------------------------------------------------- */ /* teste l intersection d un semiaxe et d un cone */ #if defined(ACTIVE_EDITOR) /*active editor only*/ ACP_tdxBool INT_fn_bIntersectSemiAxeWithCone ( MTH3D_tdstVector *p_stVertex1, MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stTopPoint, MTH3D_tdstVector *p_stBasePoint, MTH_tdxReal xBaseRadius, ACP_tdxBool *bBack, MTH_tdxReal *p_xT, MTH3D_tdstVector *p_stHit ) { MTH3D_tdstVector stVectTB; MTH3D_tdstVector stVectT1; MTH_tdxReal xF; MTH_tdxReal xG; MTH_tdxReal xH; MTH_tdxReal xM; MTH_tdxReal xN; MTH_tdxReal xP; MTH_tdxReal xA; MTH_tdxReal xB; MTH_tdxReal xC; MTH_tdxReal xT1; MTH_tdxReal xT2; MTH_tdxReal xTLine; MTH3D_M_vSubVector ( &stVectTB, p_stBasePoint, p_stTopPoint ); MTH3D_M_vSubVector ( &stVectT1, p_stVertex1, p_stTopPoint ); xF = MTH_M_xSub ( MTH3D_M_xSqrVector ( &stVectTB ), MTH_M_xSqr ( xBaseRadius ) ); xG = MTH3D_M_xSqrVector ( &stVectT1 ); xH = MTH3D_M_xSqrVector ( p_stVect12 ); xM = MTH3D_M_xDotProductVector ( p_stVect12, &stVectTB ); xN = MTH3D_M_xDotProductVector ( &stVectT1, &stVectTB ); xP = MTH3D_M_xDotProductVector ( p_stVect12, &stVectT1 ); xA = MTH_M_xSub ( MTH_M_xSqr ( xM ), MTH_M_xMul ( xH, xF ) ); xB = MTH_M_xSub ( MTH_M_xMul ( xN, xM ), MTH_M_xMul ( xP, xF ) ); xB = MTH_M_xAdd ( xB, xB ); /* instead of multpiplication by 2, use add*/ xC = MTH_M_xSub ( MTH_M_xSqr ( xN ), MTH_M_xMul ( xG, xF ) ); /* resolution du trinome */ switch ( INT_fn_xTrinomeResolution ( xA, xB, xC, &xT1, &xT2 ) ) { case INT_C_xOneSolution : if ( MTH_C_ZERO <= xT1 ) { *p_xT = xT1; xTLine = MTH_M_xDiv ( MTH_M_xAdd ( MTH_M_xMul ( xM, *p_xT ), xN ), MTH3D_M_xSqrVector ( &stVectTB ) ); if ( MTH_M_bInUnitEqual ( xTLine ) ) { *bBack = TRUE; MTH3D_M_vMulAddVector ( p_stHit, *p_xT, p_stVect12, p_stVertex1 ); return TRUE; } } break; case INT_C_xTwoSolutions : *p_xT = MTH_M_xMin ( xT1, xT2 ); if ( MTH_C_ZERO <= *p_xT ) { xTLine = MTH_M_xDiv ( MTH_M_xAdd ( MTH_M_xMul ( xM, *p_xT ), xN ), MTH3D_M_xSqrVector ( &stVectTB ) ); if ( MTH_M_bInUnitEqual ( xTLine ) ) { *bBack = FALSE; MTH3D_M_vMulAddVector ( p_stHit, *p_xT, p_stVect12, p_stVertex1 ); return TRUE; } else { *p_xT = MTH_M_xMax ( xT1, xT2 ); if ( MTH_C_ZERO <= *p_xT ) { xTLine = MTH_M_xDiv ( MTH_M_xAdd ( MTH_M_xMul ( xM, *p_xT ), xN ), MTH3D_M_xSqrVector ( &stVectTB ) ); if ( MTH_M_bInUnitEqual ( xTLine ) ) { *bBack = FALSE; MTH3D_M_vMulAddVector ( p_stHit, *p_xT, p_stVect12, p_stVertex1 ); return TRUE; } } } } else { *p_xT = MTH_M_xMax ( xT1, xT2 ); if ( MTH_C_ZERO <= *p_xT ) { xTLine = MTH_M_xDiv ( MTH_M_xAdd ( MTH_M_xMul ( xM, *p_xT ), xN ), MTH3D_M_xSqrVector ( &stVectTB ) ); if ( MTH_M_bInUnitEqual ( xTLine ) ) { *bBack = TRUE; MTH3D_M_vMulAddVector ( p_stHit, *p_xT, p_stVect12, p_stVertex1 ); return TRUE; } } } break; default : break; } return FALSE; } #endif /* -------------------------------------------------------------------------------- -- Description : Inclusion of a point in a cone -------------------------------------------------------------------------------- -- Creation date : 21 jan 1997 Author : FPI -------------------------------------------------------------------------------- */ /* used*/ /* teste l inclusion d un point dans un cone */ ACP_tdxBool INT_fn_bGetInclusionPointInCone ( MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stTopPoint, MTH3D_tdstVector *p_stBasePoint, MTH_tdxReal xBaseRadius ) { MTH_tdxReal xT; MTH3D_tdstVector stHit; MTH_tdxReal xDist; /*ANNECY TQ 04/05/98{*/ MTH3D_tdstVector stTopBaseVector; MTH3D_M_vSubVector(&stTopBaseVector, p_stBasePoint, p_stTopPoint); xDist = INT_fn_xDistancePointToLine ( p_stPoint, p_stTopPoint, &stTopBaseVector, &xT, &stHit ); /*ENDANNECY TQ}*/ return ( ( MTH_M_bInUnitEqual ( xT ) ) && ( MTH_M_bLessEqual ( xDist, MTH_M_xMul ( xT, xBaseRadius ) ) ) ); } /* -------------------------------------------------------------------------------- -- Description : Compute distance point to a line -------------------------------------------------------------------------------- -- Creation date : 18 nov 1996 Author : FPI -------------------------------------------------------------------------------- */ /* used*/ MTH_tdxReal INT_fn_xDistancePointToLine ( MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stVertexA, MTH3D_tdstVector *p_stVectAB, MTH_tdxReal *p_xT, MTH3D_tdstVector *p_stHit ) { MTH3D_tdstVector stVectAP; if ( !(MTH3D_M_bIsNullVector ( p_stVectAB )) ) { MTH3D_M_vSubVector ( &stVectAP, p_stPoint, p_stVertexA ); /* 3 add */ *p_xT = MTH_M_xDiv ( MTH3D_M_xDotProductVector ( p_stVectAB, &stVectAP ), MTH3D_M_xSqrVector ( p_stVectAB ) ); /* 3 mul 2 add 3 mul 2 add 1 div */ MTH3D_M_vMulAddVector ( p_stHit, *p_xT, p_stVectAB, p_stVertexA ); /* 3 mul 3 add */ } else { *p_xT = MTH_C_ZERO; MTH3D_M_vCopyVector ( p_stHit, p_stVertexA ); } return MTH3D_M_xVectorGap ( p_stHit, p_stPoint ); /* 3 add 3 mul 2 add 1 sqrt */ /* 15 add 12 mul 1 div 1 sqrt */ } /* -------------------------------------------------------------------------------- -- Description : Compute squared distance point to a segment -------------------------------------------------------------------------------- -- Creation date : 04 jun 1997 Author : FPI -------------------------------------------------------------------------------- */ #ifndef U64 /* used only for complex shadow calculation*/ MTH_tdxReal INT_fn_xSqrDistancePointToSegment ( MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stVertexA, MTH3D_tdstVector *p_stVectAB ) { MTH3D_tdstVector stVectAP; MTH_tdxReal xT; MTH3D_tdstVector stHit; MTH3D_M_vSubVector ( &stVectAP, p_stPoint, p_stVertexA ); if ( !(MTH3D_M_bIsNullVector ( p_stVectAB )) ) { xT = MTH_M_xDiv ( MTH3D_M_xDotProductVector ( p_stVectAB, &stVectAP ), MTH3D_M_xSqrVector ( p_stVectAB ) ); if ( xT < MTH_C_ZERO ) { MTH3D_M_vCopyVector ( &stHit, p_stVertexA ); } else { if ( xT > MTH_C_ONE ) { MTH3D_M_vAddVector ( &stHit, p_stVectAB, p_stVertexA ); } else { MTH3D_M_vMulAddVector ( &stHit, xT, p_stVectAB, p_stVertexA ); } } } else { MTH3D_M_vCopyVector ( &stHit, p_stVertexA ); } return MTH3D_M_xVectorGapSqr ( &stHit, p_stPoint ); } #endif /* -------------------------------------------------------------------------------- -- Description : Compute distance segment to a line -------------------------------------------------------------------------------- -- Creation date : 18 nov 1996 Author : FPI -------------------------------------------------------------------------------- */ #if defined(ACTIVE_EDITOR) /* active editor only*/ MTH_tdxReal INT_fn_xDistanceSegmentToLine ( MTH3D_tdstVector *p_stVertex1, /* segment */ MTH3D_tdstVector *p_stVect12, MTH3D_tdstVector *p_stVertexA, /* line */ MTH3D_tdstVector *p_stVectAB, MTH_tdxReal *p_xTLine, MTH3D_tdstVector *p_stHitSegment, MTH3D_tdstVector *p_stHitLine ) { MTH3D_tdstVector stVectA1; MTH_tdxReal xTSegment; MTH_tdxReal xK; MTH_tdxReal xL; MTH_tdxReal xM; MTH3D_tdstVector stVectP; MTH3D_tdstVector stVectQ; MTH3D_M_vSubVector ( &stVectA1, p_stVertex1, p_stVertexA ); xK = MTH3D_M_xDotProductVector ( p_stVectAB, p_stVect12 ); xL = MTH3D_M_xDotProductVector ( p_stVectAB, &stVectA1 ); xM = MTH_M_xInv ( MTH3D_M_xSqrVector ( p_stVectAB ) ); MTH3D_M_vMulScalarVector ( &stVectP, MTH_M_xMul ( xK, xM ), p_stVectAB ); if ( !(MTH3D_M_bEqualVector ( &stVectP, p_stVect12 )) ) { MTH3D_M_vSubVector ( &stVectP, &stVectP, p_stVect12 ); MTH3D_M_vMulScalarVector ( &stVectQ, MTH_M_xMul ( xL, xM ), p_stVectAB ); MTH3D_M_vSubVector ( &stVectQ, &stVectQ, &stVectA1 ); xTSegment = MTH_M_xNeg ( MTH_M_xDiv ( MTH3D_M_xDotProductVector ( &stVectP, &stVectQ ), MTH3D_M_xSqrVector ( &stVectP ) ) ); if ( MTH_M_bLess ( xTSegment, MTH_C_ZERO ) ) { xTSegment = MTH_C_ZERO; MTH3D_M_vCopyVector ( p_stHitSegment, p_stVertex1 ); } else { if ( MTH_M_bLess ( MTH_C_ONE, xTSegment ) ) { xTSegment = MTH_C_ONE; MTH3D_M_vAddVector ( p_stHitSegment, p_stVect12, p_stVertex1 ); } else { MTH3D_M_vMulAddVector ( p_stHitSegment, xTSegment, p_stVect12, p_stVertex1 ); } } } else { /* on prend vertex1 quand segment line parallele */ xTSegment = MTH_C_ZERO; MTH3D_M_vCopyVector ( p_stHitSegment, p_stVertex1 ); } *p_xTLine = MTH_M_xMul ( MTH_M_xAdd ( MTH_M_xMul ( xK, xTSegment ), xL ), xM ); MTH3D_M_vMulAddVector ( p_stHitLine, *p_xTLine, p_stVectAB, p_stVertexA ); return MTH3D_M_xVectorGap ( p_stHitSegment, p_stHitLine ); } #endif /*======================================================================================= * Description TRUE if the I point is on the egdes of the [ABC] triangle (with epsilon) * * Creation date 26/03/98 * Author Marc Trabucato *=====================================================================================*/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ /* ACP_tdxBool INT_fn_bIsOnTriangle( MTH3D_tdstVector *_p_stPointI, MTH3D_tdstVector *_p_stPointA, MTH3D_tdstVector *_p_stPointB, MTH3D_tdstVector *_p_stPointC ) { #define COL_C_Epsilon MTH_M_xFloatToReal(1e-3) MTH_tdxReal xAlpha,xMin,xMax,xNorm2,xDotProduct; MTH3D_tdstVector stAB, stAI, stIP, stPointP; // X Test xMin = FUT_M_xMinValue3( MTH3D_M_xGetXofVector( _p_stPointA ), MTH3D_M_xGetXofVector( _p_stPointB ), MTH3D_M_xGetXofVector( _p_stPointC ) ); if( MTH_M_bLess( MTH3D_M_xGetXofVector( _p_stPointI ), MTH_M_xSub( xMin, COL_C_Epsilon ) ) ) return FALSE; xMax = FUT_M_xMaxValue3( MTH3D_M_xGetXofVector( _p_stPointA ), MTH3D_M_xGetXofVector( _p_stPointB ), MTH3D_M_xGetXofVector( _p_stPointC ) ); if( MTH_M_bGreater( MTH3D_M_xGetXofVector( _p_stPointI ), MTH_M_xAdd( xMax, COL_C_Epsilon ) ) ) return FALSE; // Y Test xMin = FUT_M_xMinValue3( MTH3D_M_xGetYofVector( _p_stPointA ), MTH3D_M_xGetYofVector( _p_stPointB ), MTH3D_M_xGetYofVector( _p_stPointC ) ); if( MTH_M_bLess( MTH3D_M_xGetYofVector( _p_stPointI ), MTH_M_xSub( xMin, COL_C_Epsilon ) ) ) return FALSE; xMax = FUT_M_xMaxValue3( MTH3D_M_xGetYofVector( _p_stPointA ), MTH3D_M_xGetYofVector( _p_stPointB ), MTH3D_M_xGetYofVector( _p_stPointC ) ); if( MTH_M_bGreater( MTH3D_M_xGetYofVector( _p_stPointI ), MTH_M_xAdd( xMax, COL_C_Epsilon ) ) ) return FALSE; // Z Test xMin = FUT_M_xMinValue3( MTH3D_M_xGetZofVector( _p_stPointA ), MTH3D_M_xGetZofVector( _p_stPointB ), MTH3D_M_xGetZofVector( _p_stPointC ) ); if( MTH_M_bLess( MTH3D_M_xGetZofVector( _p_stPointI ), MTH_M_xSub( xMin, COL_C_Epsilon ) ) ) return FALSE; xMax = FUT_M_xMaxValue3( MTH3D_M_xGetZofVector( _p_stPointA ), MTH3D_M_xGetZofVector( _p_stPointB ), MTH3D_M_xGetZofVector( _p_stPointC ) ); if( MTH_M_bGreater( MTH3D_M_xGetZofVector( _p_stPointI ), MTH_M_xAdd( xMax, COL_C_Epsilon ) ) ) return FALSE; // segment AB MTH3D_M_vSubVector( &stAB, _p_stPointB, _p_stPointA ); // AB MTH3D_M_vSubVector( &stAI, _p_stPointI, _p_stPointA ); // AI xDotProduct = MTH3D_M_xDotProductVector( &stAI, &stAB ); // AI.AB xNorm2 = MTH3D_M_xSqrVector( &stAB ); // ||AB||² xAlpha = MTH_M_xDiv( xDotProduct, xNorm2 ); if( MTH_M_bGreaterEqual ( xAlpha, MTH_M_xNeg( COL_C_Epsilon ) ) && MTH_M_bLessEqual ( xAlpha, MTH_M_xAdd( MTH_C_ONE, COL_C_Epsilon ) ) ) { MTH3D_M_vMulAddVector( &stPointP, xAlpha, &stAB, _p_stPointA ); // P MTH3D_M_vSubVector( &stIP, & stPointP, _p_stPointI ); // IP xNorm2 = MTH3D_M_xSqrVector( &stIP ); if( MTH_M_bLessEqual (xNorm2 , MTH_M_xSqr( COL_C_Epsilon ) ) ) return TRUE; } // segment AC MTH3D_M_vSubVector( &stAB, _p_stPointC, _p_stPointA ); // AC xDotProduct = MTH3D_M_xDotProductVector( &stAI, &stAB ); // AI.AC xNorm2 = MTH3D_M_xSqrVector( &stAB ); // ||AC||² xAlpha = MTH_M_xDiv( xDotProduct, xNorm2 ); if( MTH_M_bGreaterEqual ( xAlpha, MTH_M_xNeg( COL_C_Epsilon ) ) && MTH_M_bLessEqual ( xAlpha, MTH_M_xAdd( MTH_C_ONE, COL_C_Epsilon ) ) ) { MTH3D_M_vMulAddVector( &stPointP, xAlpha, &stAB, _p_stPointA ); // P MTH3D_M_vSubVector( &stIP, & stPointP, _p_stPointI ); // IP xNorm2 = MTH3D_M_xSqrVector( &stIP ); if( MTH_M_bLessEqual (xNorm2 , MTH_M_xSqr( COL_C_Epsilon ) ) ) return TRUE; } // segment BC MTH3D_M_vSubVector( &stAB, _p_stPointC, _p_stPointB ); // BC MTH3D_M_vSubVector( &stAI, _p_stPointI, _p_stPointB ); // BI xDotProduct = MTH3D_M_xDotProductVector( &stAI, &stAB ); // BI.BC xNorm2 = MTH3D_M_xSqrVector( &stAB ); // ||BC||² xAlpha = MTH_M_xDiv( xDotProduct, xNorm2 ); if( MTH_M_bGreaterEqual ( xAlpha, MTH_M_xNeg( COL_C_Epsilon ) ) && MTH_M_bLessEqual ( xAlpha, MTH_M_xAdd( MTH_C_ONE, COL_C_Epsilon ) ) ) { MTH3D_M_vMulAddVector( &stPointP, xAlpha, &stAB, _p_stPointB ); // P MTH3D_M_vSubVector( &stIP, & stPointP, _p_stPointI ); // IP xNorm2 = MTH3D_M_xSqrVector( &stIP ); if( MTH_M_bLessEqual (xNorm2 , MTH_M_xSqr( COL_C_Epsilon ) ) ) return TRUE; } return FALSE; } */ #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */