/*
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 */
 
