/*
0         1         2         3         4         5         6         7
01234567890123456789012345678901234567890123456789012345678901234567890123456789
--------------------------------------------------------------------------------
-- Description : Geometric object 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/IntersGO.h"
 
#ifdef USE_ALTIMAPS
/*.-----------------------------------------------------------------------.*/
/*|                                                                       |*/
/*|  Functions useful for Altimap intersections                           |*/
/*|                                                                       |*/
/*'-----------------------------------------------------------------------'*/
/***********************************************************************************************/
/*  Name        : COL_bSelectAltimapSquare*/
/*  Description : Sets the square coords of the square placed below or above the point*/
/*  Return val. : True if the point is above or below the altimap. False otherwise*/
/*                      0 : On the map*/
/*                      1 : Left*/
/*                      2 : Right*/
/*                      4 : Below*/
/*                      8 : Above*/
/*  Author      : Marc FASCIA*/
/*  Date        : 18/03/98*/
/*  Optimized ? : No*/
/***********************************************************************************************/
unsigned char COL_ucSelectAltimapSquare( GEO_tdstElementAltimap       * p_Altimap,
                                         MTH3D_tdstVector             * p_TestPoint,
                                         ACP_tdxIndex                 * p_xCoordX,
                                         ACP_tdxIndex                 * p_xCoordY )
{
  MTH3D_tdstVector      stVector;
  unsigned char         ucRetCode;
  
  ucRetCode = 0;
 
  /*--- Places the test point and the Altimap at the same origin*/
  MTH3D_M_vSubVector( &stVector, (p_TestPoint), &((p_Altimap)->stOrigin) );
 
  /*--- First, we have to find the right square*/
  *p_xCoordX = (short) MTH_M_xRealToLong( ( stVector.xX / (p_Altimap)->xDeltaX ) );
  *p_xCoordY = (short) MTH_M_xRealToLong( ( stVector.xY / (p_Altimap)->xDeltaY ) );
  
  if( *p_xCoordX < 0 )
    ucRetCode |= 1;       /* On the Left*/
  else
    if( *p_xCoordX > (p_Altimap)->xWidth - 1) 
      ucRetCode |= 2;     /* On the Right*/
    
  if( *p_xCoordY < 0 )
    ucRetCode |= 4;       /* Below*/
  else
    if( *p_xCoordY > (p_Altimap)->xDepth - 1)
      ucRetCode |= 8;     /* Above*/
 
  return ucRetCode;
}
 
 
/***********************************************************************************************/
/*  Name        : COL_ucBuildAltimapSquareTriangle*/
/*  Description : */
/*  Return val. : The type of the next triangle in this square*/
/*  Author      : Marc FASCIA*/
/*  Date        : 18/03/98*/
/*  Optimized ? : No*/
/***********************************************************************************************/
unsigned char COL_ucBuildAltimapSquareTriangle( GEO_tdstElementAltimap       * p_Altimap,           /* The altimap*/
                                                ACP_tdxIndex                 xSx,                   /* Square coord X*/
                                                ACP_tdxIndex                 xSy,                   /* Square coord Y*/
                                                unsigned char                ucTriangle,            /* Which triangle of this square*/
                                                MTH3D_tdstVector             * p_stV1,              /* Triplet of points*/
                                                MTH3D_tdstVector             * p_stV2,              /*         ''*/
                                                MTH3D_tdstVector             * p_stV3,              /*         ''*/
                                                MTH3D_tdstVector             * p_stNormal,          /* Normal vector*/
                                                ACP_tdxIndex                 * p_xFaceIndex )       /* Index of built face*/
{
  ACP_tdxIndex          xSquare, xVertex, xOpposite;
 
  /*--- We compute the square index*/
  xSquare = xSy     * (p_Altimap)->xWidth + xSx;
  /*--- And teh base vertex index of this square*/
  xVertex   = xSquare + ( xSquare / (p_Altimap)->xWidth );
  xOpposite = xVertex + (p_Altimap->xWidth + 1) + 1;
 
  /*--- We need to know how this square is divided*/
  
  /*--------------------------------------------------------------------------------------------------------*/
  if( ucTriangle & GEO_C_xAltiSquareTopRight )
  {
    /*--- 2 points of the diagonal*/
    MTH3D_M_vSetVectorElements( p_stV1, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx+1 ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy ),
                                        p_Altimap->d_xHeight[ xVertex + 1 ] );
    MTH3D_M_vSetVectorElements( p_stV2, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx+1 ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy+1 ),
                                        p_Altimap->d_xHeight[ xOpposite ] );
    MTH3D_M_vSetVectorElements( p_stV3, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy+1 ),
                                        p_Altimap->d_xHeight[ xOpposite - 1 ] );
    *p_xFaceIndex = p_Altimap->d_stSquare[xSquare].xFaceIndex;
    *p_stNormal = p_Altimap->d_stFaces[ *p_xFaceIndex ].stNormal;
    
    return (ucTriangle & ~GEO_C_xAltiSquareTopRight) << 4;
  }
 
  /*--------------------------------------------------------------------------------------------------------*/
  if( ucTriangle & GEO_C_xAltiSquareBottomLeft )
  {
    /*--- 2 points of the diagonal*/
    MTH3D_M_vSetVectorElements( p_stV1, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy ),
                                        p_Altimap->d_xHeight[ xVertex ] );
    MTH3D_M_vSetVectorElements( p_stV2, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx+1 ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy ),
                                        p_Altimap->d_xHeight[ xVertex + 1 ] );
    MTH3D_M_vSetVectorElements( p_stV3, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy+1 ),
                                        p_Altimap->d_xHeight[ xOpposite - 1 ] );
    *p_xFaceIndex = p_Altimap->d_stSquare[xSquare].xFaceIndex;
    *p_stNormal = p_Altimap->d_stFaces[ *p_xFaceIndex ].stNormal;
    
    return 0;
  }
 
  /*--------------------------------------------------------------------------------------------------------*/
  if( (ucTriangle >> 4) & GEO_C_xAltiSquareBottomLeft )
  {
    /*--- 2 points of the diagonal*/
    MTH3D_M_vSetVectorElements( p_stV1, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy ),
                                        p_Altimap->d_xHeight[ xVertex ] );
    MTH3D_M_vSetVectorElements( p_stV2, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx+1 ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy ),
                                        p_Altimap->d_xHeight[ xVertex + 1 ] );
    MTH3D_M_vSetVectorElements( p_stV3, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy+1 ),
                                        p_Altimap->d_xHeight[ xOpposite - 1 ] );
    *p_xFaceIndex = p_Altimap->d_stSquare[xSquare].xFaceIndex + 1;
    *p_stNormal = p_Altimap->d_stFaces[ *p_xFaceIndex ].stNormal;
    
    return 0;
  }
 
  /*--------------------------------------------------------------------------------------------------------*/
  if( ucTriangle & GEO_C_xAltiSquareTopLeft )
  {
    /*--- 2 points of the diagonal*/
    MTH3D_M_vSetVectorElements( p_stV1, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy ),
                                        p_Altimap->d_xHeight[ xVertex ] );
    MTH3D_M_vSetVectorElements( p_stV2, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx+1 ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy+1 ),
                                        p_Altimap->d_xHeight[ xOpposite ] );
    MTH3D_M_vSetVectorElements( p_stV3, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy+1 ),
                                        p_Altimap->d_xHeight[ xOpposite - 1 ] );
    *p_xFaceIndex = p_Altimap->d_stSquare[xSquare].xFaceIndex;
    *p_stNormal = p_Altimap->d_stFaces[ *p_xFaceIndex ].stNormal;
    
    return (ucTriangle & ~GEO_C_xAltiSquareTopLeft) << 4;
  }
 
  /*--------------------------------------------------------------------------------------------------------*/
  if( ucTriangle & GEO_C_xAltiSquareBottomRight )
  {
    /*--- 2 points of the diagonal*/
    MTH3D_M_vSetVectorElements( p_stV1, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy ),
                                        p_Altimap->d_xHeight[ xVertex ] );
    MTH3D_M_vSetVectorElements( p_stV2, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx+1 ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy ),
                                        p_Altimap->d_xHeight[ xVertex + 1 ] );
    MTH3D_M_vSetVectorElements( p_stV3, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx+1 ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy+1 ),
                                        p_Altimap->d_xHeight[ xOpposite] );
    *p_xFaceIndex = p_Altimap->d_stSquare[xSquare].xFaceIndex;
    *p_stNormal = p_Altimap->d_stFaces[ *p_xFaceIndex ].stNormal;
    
    return 0;
  }
 
    /*--------------------------------------------------------------------------------------------------------*/
  if( (ucTriangle >> 4) & GEO_C_xAltiSquareBottomRight )
  {
    /*--- 2 points of the diagonal*/
    MTH3D_M_vSetVectorElements( p_stV1, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy ),
                                        p_Altimap->d_xHeight[ xVertex ] );
    MTH3D_M_vSetVectorElements( p_stV2, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx+1 ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy ),
                                        p_Altimap->d_xHeight[ xVertex + 1 ] );
    MTH3D_M_vSetVectorElements( p_stV3, p_Altimap->stOrigin.xX + p_Altimap->xDeltaX * MTH_M_xLongToReal( xSx+1 ),
                                        p_Altimap->stOrigin.xY + p_Altimap->xDeltaY * MTH_M_xLongToReal( xSy+1 ),
                                        p_Altimap->d_xHeight[ xOpposite] );
    *p_xFaceIndex = p_Altimap->d_stSquare[xSquare].xFaceIndex + 1;
    *p_stNormal = p_Altimap->d_stFaces[ *p_xFaceIndex ].stNormal;
    
    return 0;
  }
 
  return GEO_C_xAltiSquareVoid;
}
 
/*----------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------*/
#endif /*USE_ALTIMAPS*/
 
 
 
/*
--------------------------------------------------------------------------------
-- Description : View and add face in list a data of element
--------------------------------------------------------------------------------
-- Creation date : 18 nov 1996               Author : FPI
--------------------------------------------------------------------------------
*/
 
void INT_fn_vViewAndAddFaceElementInList ( ACP_tdxIndex xNbMaxElements,
                                           ACP_tdxIndex *p_xNbElements,
                                           struct GLI_tdstDataOfElement_ *d_stDataOfElement,
                                           MTH3D_tdstVector *p_stVertexA,
                                           ACP_tdxBool bBack,
                                           MTH3D_tdstVector *p_stHit,
                                           ACP_tdxIndex xElements,
                                           ACP_tdxIndex xDataElementIndex )
{
  ACP_tdxIndex xFaceIndex;
  MTH_tdxReal xDistance;
 
  if ( !(bBack) )
  {
    xDistance = MTH3D_M_xVectorGap ( p_stHit, p_stVertexA );
 
    /* index sur le dernier element */
    xFaceIndex = *p_xNbElements;
    while ( ( 0 < xFaceIndex ) && ( xDistance < d_stDataOfElement[xFaceIndex-1].xDistance ) )
    {
      if ( xFaceIndex < xNbMaxElements )
      {
        /* xFaceIndex <- xFaceIndex - 1 */
        memcpy ( &(d_stDataOfElement[xFaceIndex]), &(d_stDataOfElement[xFaceIndex-1]), sizeof ( struct GLI_tdstDataOfElement_ ) );
      }
      xFaceIndex--;
    }
 
    if ( xFaceIndex < xNbMaxElements )
    {
      /* xFaceIndex */
      MTH3D_M_vCopyVector ( &(d_stDataOfElement[xFaceIndex].stHit), p_stHit );
      d_stDataOfElement[xFaceIndex].xDistance = xDistance;
      d_stDataOfElement[xFaceIndex].xElements = xElements;
      d_stDataOfElement[xFaceIndex].xIndexOfFace = xDataElementIndex;
      if ( (*p_xNbElements) < xNbMaxElements )
        (*p_xNbElements)++;
    }
  }
}
 
/*
--------------------------------------------------------------------------------
-- Description : Segment with face of geometric object intersection test
--------------------------------------------------------------------------------
-- Creation date : 03 nov 1996               Author : FPI
--------------------------------------------------------------------------------
*/
 
/* YLG*/
unsigned long	g_xMask = 0;
/*DONE//*/
 
/* used*/
ACP_tdxBool INT_fn_bIntersectSegmentWithFaceOfGeometricObject ( MTH3D_tdstVector *p_stVertexA,
                                                                MTH3D_tdstVector *p_stVertexB,
                                                                MTH3D_tdstVector *p_stVectAB,
                                                                GEO_tdstGeometricObject *p_stGeomObj,
                                                                ACP_tdxIndex xNbMaxElements,
                                                                ACP_tdxIndex *p_xNbElements,
                                                                struct GLI_tdstDataOfElement_ *d_stDataOfElement )
{
	ACP_tdxIndex                      xElementIndex;
	COL_tdxFaceIndex                  * p_xListIndex;
	GEO_tdstElementIndexedTriangles   * p_stElementIndexedTriangles;
	/*  GEO_tdstElementFaceMapDescriptors * p_stElementFaceMapDescriptors;*/
	/*  GEO_tdstElementTMeshes            * p_stElementTMeshes;*/
	GEO_tdstElementSpheres            * p_stElementSpheres;
	GEO_tdstElementAlignedBoxes       * p_stElementAlignedBoxes;
	
	ACP_tdxIndex                      xDataElementIndex;
	ACP_tdxIndex                      xNodeIndex;
	/*  ACP_tdxIndex                      xAtomIndex;*/
	COL_tdxFaceIndex                  xIndex;
	/*  ACP_tdxBool                       bPointsSpin;*/
	MTH3D_tdstVector                  *p_stVertex1;
	MTH3D_tdstVector                  *p_stVertex2;
	MTH3D_tdstVector                  *p_stVertex3;
	MTH3D_tdstVector                  *p_stNormal;
	MTH_tdxReal xDPlan;
	GEO_tdstIndexedSphere             *p_stIndexedSphere;
	GEO_tdstIndexedAlignedBox         *p_stIndexedAlignedBox;
	MTH3D_tdstVector                  *p_stCenter;
	MTH3D_tdstVector                  *p_stMinPoint;
	MTH3D_tdstVector                  *p_stMaxPoint;
	MTH3D_tdstVector                  stNormal;
	
	ACP_tdxBool bBack = FALSE;
	MTH_tdxReal xT;
	MTH3D_tdstVector stHit;
	
	ACP_tdxIndex					xNumberOfSelectedNodes;
	COL_tdpstOctreeNode				aDEF_pstSelectedNode[COL_C_xMaxSelectedNodes];
	MTH_tdxReal						aDEF_xSelectedT[COL_C_xMaxSelectedNodes];
	ACP_tdxIndex					xNbElements;
  GMT_tdxHandleToGameMaterial		hMaterial = NULL;
  GMT_tdxHandleToCollideMaterial	hCM = NULL;
 
	*p_xNbElements = 0;
	
	if ( p_stGeomObj->p_stOctree == NULL )
	{
		/* pour les elements */
		for ( xElementIndex = 0 ; xElementIndex < p_stGeomObj->xNbElements ; xElementIndex++ )
		{
			switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
			{
			case GEO_C_xElementIndexedTriangles : 
				if ( g_xMask != 0 )
				{
  				GEO_vGetGameMaterialOfIndexedTriangles( p_stGeomObj, xElementIndex, &hMaterial );
					if ( hMaterial != NULL )
					{
						hCM = GMT_fn_hGetCollideMaterial( hMaterial );
						if (hCM != GMT_C_InvalidCollideMaterial)
						{
							/*any bit of NoShadow, Water or Uncollidable cancels shadow projection*/
							if ((GMT_fn_hGetCollideMaterialIdentifier( hCM ) & g_xMask ) == 0x0000 )
								break;
						}
						else
							break;
					}
					else
						break;
				}
 
				p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
				
				/* pour les triangles */
				for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementIndexedTriangles->xNbFaces ; xDataElementIndex++ )
				{
					/* points du triangle statique */
					p_stVertex1 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0];
					p_stVertex2 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1];
					p_stVertex3 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2];
					
					/* calcul de la normale */
					p_stNormal = p_stElementIndexedTriangles->d_stListOfFacesNormals + xDataElementIndex;
					
					/* calcul de d de l equation du plan */
					xDPlan = MTH_M_xNeg ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertex1 ) );
					
					/* intersection segment - triangle */
					if
						(
						INT_fn_bIntersectSegmentWithTriangle ( p_stVertexA, p_stVectAB,
						p_stVertex1, p_stVertex2, p_stVertex3,
						p_stNormal, xDPlan, &xT, &stHit )
						)
					{
						INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
							p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
					}
				}
				break;
				
#ifdef USE_ALTIMAPS
			case GEO_C_xElementAltimap :
				{
					GEO_tdstElementAltimap  * p_stElementAltimap;
					ACP_tdxIndex      xAx, xAy, xBx, xBy, xLoopX, xLoopY, xLoopV, xIndex;
					MTH3D_tdstVector  stV1, stV2, stV3, stNorm;
					ACP_tdxBool       xBoolA, xBoolB;
					
					p_stElementAltimap = (GEO_tdstElementAltimap *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
					xBoolA = COL_ucSelectAltimapSquare( p_stElementAltimap, p_stVertexA, &xAx, &xAy );
					xBoolB = COL_ucSelectAltimapSquare( p_stElementAltimap, p_stVertexB, &xBx, &xBy );
					COL_M_vClipSquareSelection( p_stElementAltimap, xAx, xAy, xBoolA );
					COL_M_vClipSquareSelection( p_stElementAltimap, xBx, xBy, xBoolB );
					
					COL_M_vScanSelectedSquares( xLoopX, xLoopY, xLoopV, p_stElementAltimap->xWidth, xAx, xAy, xBx, xBy )
					{
						unsigned char   ucType;
						
						ucType = p_stElementAltimap->d_stSquare[ xLoopV ].ucType;
						while( ucType )
						{
							ucType = COL_ucBuildAltimapSquareTriangle( p_stElementAltimap, xLoopX, xLoopY, ucType,
								&stV1, &stV2, &stV3, &stNorm, &xIndex );
							
							/*--- Equation of face's plan*/
							xDPlan = MTH_M_xNeg( MTH3D_M_xDotProductVector( &stNorm, &stV1 ) );
							
							if( INT_fn_bIntersectSegmentWithTriangle( p_stVertexA, p_stVectAB, 
								&stV1, &stV2, &stV3,
								&stNorm, xDPlan, &xT, &stHit ) )
								INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
								p_stVertexA, bBack, &stHit, xElementIndex, xIndex );
						}
					}
				}
				break;              
#endif /*USE_ALTIMAPS*/
				
				
			case GEO_C_xElementSpheres :
				p_stElementSpheres = (GEO_tdstElementSpheres *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
				
				/* pour les spheres */
				for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementSpheres->xNbSpheres ; xDataElementIndex++ )
				{
					/* sphere */
					p_stIndexedSphere = p_stElementSpheres->d_stListOfSpheres + xDataElementIndex;
					
					/* centre de la sphere */
					p_stCenter = p_stGeomObj->d_stListOfPoints + p_stIndexedSphere->xCenterPoint;
					
					/* intersection segment - sphere */
					if
						(
						INT_fn_bIntersectSegmentWithSphere ( p_stVertexA, p_stVectAB,
						p_stCenter, p_stIndexedSphere->xRadius,
						&xT, &stHit, &stNormal )
						)
					{
						INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
							p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
					}
				}
				break;
				
			case GEO_C_xElementAlignedBoxes :
				p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
				
				/* pour les boites */
				for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementAlignedBoxes->xNbAlignedBoxes ; xDataElementIndex++ )
				{
					/* boite */
					p_stIndexedAlignedBox = p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex;
					
					/* points de la boite */
					p_stMinPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMinPoint;
					p_stMaxPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMaxPoint;
					
					/* intersection segment - boite */
					if
						(
						INT_fn_bIntersectSegmentWithBox ( p_stVertexA, p_stVertexB, p_stVectAB,
						p_stMinPoint, p_stMaxPoint,
						&xT, &stHit, &stNormal )
						)
					{
						INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
							p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
					}
				}
				break;
				
			default :
				break;
      }
    }
  }
  else
  {
	  COL_fn_vExploreOctreeWithSegment ( p_stGeomObj->p_stOctree, p_stVertexA, p_stVectAB,
		  aDEF_pstSelectedNode, aDEF_xSelectedT, &xNumberOfSelectedNodes );
	  
	  COL_g_lFacesTagCounter++;
	  
	  /* pour les noeuds selectionnes */
	  for ( xNodeIndex = 0 ; xNodeIndex < xNumberOfSelectedNodes ; xNodeIndex++ )
	  {
		  xNbElements  = *((COL_tdxFaceIndexDouble*)aDEF_pstSelectedNode[xNodeIndex]->d_xFaceIndexList);
		  p_xListIndex = (COL_tdxFaceIndex*)(((COL_tdxFaceIndexDouble*)aDEF_pstSelectedNode[xNodeIndex]->d_xFaceIndexList)+1);
		  
		  for (xIndex = 0 ; xIndex < xNbElements ; xIndex++)
		  {
			if ((*p_xListIndex) < COL_C_MaxIndex)
				xElementIndex = (ACP_tdxIndex) (* (p_xListIndex ++));
			else
			{
				ACP_tdxIndex xData;
 
				xData=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData<<=8;
				xData+=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData&=~COL_C_OverflowIndex;
				xElementIndex = xData;
			}
 
			if ((*p_xListIndex) < COL_C_MaxIndex)
				xDataElementIndex = (ACP_tdxIndex) (* (p_xListIndex ++));
			else
			{
				ACP_tdxIndex xData;
 
				xData=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData<<=8;
				xData+=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData&=~COL_C_OverflowIndex;
				xDataElementIndex = xData;
			}
 
			  /* verif tag */
			  if
				  (
				  COL_g_d_lTaggedFacesTable[(p_stGeomObj->p_stOctree)->d_xElementBasesTable[xElementIndex] + xDataElementIndex]
				  != COL_g_lFacesTagCounter
				  )
			  {
				  switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
				  {
				  case GEO_C_xElementIndexedTriangles :
						if (g_xMask != 0)
						{
  							GEO_vGetGameMaterialOfIndexedTriangles( p_stGeomObj, xElementIndex, &hMaterial );
							if ( hMaterial != NULL)
							{
								hCM = GMT_fn_hGetCollideMaterial( hMaterial );
								if (hCM != GMT_C_InvalidCollideMaterial)
								{
									/*any bit of NoShadow, Water or Uncollidable cancels shadow projection*/
									if ((GMT_fn_hGetCollideMaterialIdentifier( hCM ) & g_xMask ) == 0x0000 )
										break;
								}
								else
									break;
							}
							else
								break;
						}
					  p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
					  
					  /* points du triangle statique */
					  p_stVertex1 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0];
					  p_stVertex2 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1];
					  p_stVertex3 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2];
					  
					  /* calcul de la normale */
					  p_stNormal = p_stElementIndexedTriangles->d_stListOfFacesNormals + xDataElementIndex;
					  
					  /* calcul de d de l equation du plan */
					  xDPlan = MTH_M_xNeg ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertex1 ) );
					  
					  /* intersection segment - triangle */
					  if
						  (
						  INT_fn_bIntersectSegmentWithTriangle ( p_stVertexA, p_stVectAB,
						  p_stVertex1, p_stVertex2, p_stVertex3,
						  p_stNormal, xDPlan, &xT, &stHit )
						  )
					  {
						  INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
							  p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
					  }
					  break;
					  
					  
				  case GEO_C_xElementSpheres :
					  p_stElementSpheres = (GEO_tdstElementSpheres *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
					  
					  /* sphere */
					  p_stIndexedSphere = p_stElementSpheres->d_stListOfSpheres + xDataElementIndex;
					  
					  /* centre de la sphere */
					  p_stCenter = p_stGeomObj->d_stListOfPoints + p_stIndexedSphere->xCenterPoint;
					  
					  /* intersection segment - sphere */
					  if
						  (
						  INT_fn_bIntersectSegmentWithSphere ( p_stVertexA, p_stVectAB,
						  p_stCenter, p_stIndexedSphere->xRadius,
						  &xT, &stHit, &stNormal )
						  )
					  {
						  INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
							  p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
					  }
					  break;
					  
				  case GEO_C_xElementAlignedBoxes :
					  p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
					  
					  /* boite */
					  p_stIndexedAlignedBox = p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex;
					  
					  /* points de la boite */
					  p_stMinPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMinPoint;
					  p_stMaxPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMaxPoint;
					  
					  /* intersection segment - boite */
					  if
						  (
						  INT_fn_bIntersectSegmentWithBox ( p_stVertexA, p_stVertexB, p_stVectAB,
						  p_stMinPoint, p_stMaxPoint,
						  &xT, &stHit, &stNormal )
						  )
					  {
						  INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
							  p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
					  }
					  break;
					  
#ifdef USE_ALTIMAPS
				  case GEO_C_xElementAltimap:
#endif /*USE_ALTIMAPS*/
				  default :
					  break;
          }
		  
          COL_g_d_lTaggedFacesTable[(p_stGeomObj->p_stOctree)->d_xElementBasesTable[xElementIndex] + xDataElementIndex]
			  = COL_g_lFacesTagCounter;
        }
      }
    }
  }
  
  return (*p_xNbElements) > 0;
}
 
/*
--------------------------------------------------------------------------------
-- Description : Segment with first face of geometric object intersection test
--------------------------------------------------------------------------------
-- Creation date : 29 may 1997               Author : FPI
--------------------------------------------------------------------------------
*/
/*DONE//*/
 
#ifndef U64
/* used only for complex shadow calculation*/
ACP_tdxBool INT_fn_bIntersectSegmentWithFirstFaceOfGeometricObject ( MTH3D_tdstVector *p_stVertexA,
                                                                     MTH3D_tdstVector *p_stVertexB,
                                                                     MTH3D_tdstVector *p_stVectAB,
                                                                     GEO_tdstGeometricObject *p_stGeomObj,
                                                                     MTH3D_tdstVector *p_stHitPoint,
                                                                     ACP_tdxIndex *p_xElement,
                                                                     ACP_tdxIndex *p_xDataElement )
{
	ACP_tdxIndex                      xElementIndex;
	ACP_tdxIndex xDataElementIndex;
	GEO_tdstElementIndexedTriangles   *p_stElementIndexedTriangles;
	/*  GEO_tdstElementFaceMapDescriptors *p_stElementFaceMapDescriptors;*/
	GEO_tdstElementSpheres            *p_stElementSpheres;
	GEO_tdstElementAlignedBoxes       *p_stElementAlignedBoxes;
	
	MTH3D_tdstVector *p_stVertex1;
	MTH3D_tdstVector *p_stVertex2;
	MTH3D_tdstVector *p_stVertex3;
	MTH3D_tdstVector *p_stNormal;
	MTH_tdxReal xDPlan;
	GEO_tdstIndexedSphere *p_stIndexedSphere;
	GEO_tdstIndexedAlignedBox *p_stIndexedAlignedBox;
	MTH3D_tdstVector *p_stCenter;
	MTH3D_tdstVector *p_stMinPoint;
	MTH3D_tdstVector *p_stMaxPoint;
	MTH3D_tdstVector stNormal;
	
	ACP_tdxBool bFound;
	MTH_tdxReal xT;
	MTH3D_tdstVector stHit;
	MTH_tdxReal xDistance;
	
	COL_tdxFaceIndex *p_xListIndex;
	ACP_tdxIndex xNodeIndex;
	COL_tdxFaceIndex xIndex;
	ACP_tdxIndex xNumberOfSelectedNodes;
	COL_tdpstOctreeNode aDEF_pstSelectedNode[COL_C_xMaxSelectedNodes];
	MTH_tdxReal aDEF_xSelectedT[COL_C_xMaxSelectedNodes];
	ACP_tdxIndex					xNbElements;
	
	bFound = FALSE;
	xDistance = MTH_C_2;
	
	if ( p_stGeomObj->p_stOctree == NULL )
	{
		/* pour les elements */
		for ( xElementIndex = 0 ; xElementIndex < p_stGeomObj->xNbElements ; xElementIndex++ )
		{
			switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
			{
			case GEO_C_xElementIndexedTriangles :
				p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
				
				/* pour les triangles */
				for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementIndexedTriangles->xNbFaces ; xDataElementIndex++ )
				{
					/* points du triangle statique */
					p_stVertex1 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0];
					p_stVertex2 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1];
					p_stVertex3 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2];
					
					/* calcul de la normale */
					p_stNormal = p_stElementIndexedTriangles->d_stListOfFacesNormals + xDataElementIndex;
					
					/* calcul de d de l equation du plan */
					xDPlan = MTH_M_xNeg ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertex1 ) );
					
					/* intersection segment - triangle */
					if
						(
						INT_fn_bIntersectSegmentWithTriangle ( p_stVertexA, p_stVectAB,
						p_stVertex1, p_stVertex2, p_stVertex3,
						p_stNormal, xDPlan, &xT, &stHit )
						)
					{
						if ( MTH_M_bLess ( xT, xDistance ) )
						{
							bFound = TRUE;
							xDistance = xT;
							MTH3D_M_vCopyVector ( p_stHitPoint, &stHit );
							*p_xElement = xElementIndex;
							*p_xDataElement = xDataElementIndex;
						}
					}
				}
				break;
				
#ifdef USE_ALTIMAPS
			case GEO_C_xElementAltimap :
				{
					GEO_tdstElementAltimap *p_stElementAltimap;
					ACP_tdxIndex      xAx, xAy, xBx, xBy, xLoopX, xLoopY, xLoopV, xIndex;
					MTH3D_tdstVector  stV1, stV2, stV3, stNorm;
					ACP_tdxBool       xBoolA, xBoolB;
					
					p_stElementAltimap = (GEO_tdstElementAltimap *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
					xBoolA = COL_ucSelectAltimapSquare( p_stElementAltimap, p_stVertexA, &xAx, &xAy );
					xBoolB = COL_ucSelectAltimapSquare( p_stElementAltimap, p_stVertexB, &xBx, &xBy );
					COL_M_vClipSquareSelection( p_stElementAltimap, xAx, xAy, xBoolA );
					COL_M_vClipSquareSelection( p_stElementAltimap, xBx, xBy, xBoolB );
					
					COL_M_vScanSelectedSquares( xLoopX, xLoopY, xLoopV, p_stElementAltimap->xWidth, xAx, xAy, xBx, xBy )
					{
						unsigned char   ucType;
						
						ucType = p_stElementAltimap->d_stSquare[ xLoopV ].ucType;
						while( ucType )
						{
							ucType = COL_ucBuildAltimapSquareTriangle( p_stElementAltimap, xLoopX, xLoopY, ucType,
								&stV1, &stV2, &stV3, &stNorm, &xIndex );
							
							/*--- Equation of face's plan*/
							xDPlan = MTH_M_xNeg( MTH3D_M_xDotProductVector( &stNorm, &stV1 ) );
							
							if( INT_fn_bIntersectSegmentWithTriangle( p_stVertexA, p_stVectAB, 
								&stV1, &stV2, &stV3,
								&stNorm, xDPlan, &xT, &stHit ) )
								if ( MTH_M_bLess ( xT, xDistance ) )
								{
									bFound = TRUE;
									xDistance = xT;
									MTH3D_M_vCopyVector ( p_stHitPoint, &stHit );
									*p_xElement = xElementIndex;
									*p_xDataElement = xIndex;
								}
						}
					}
				}
				break;              
#endif /*USE_ALTIMAPS*/
				
				
			case GEO_C_xElementSpheres :
				p_stElementSpheres = (GEO_tdstElementSpheres *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
				
				/* pour les spheres */
				for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementSpheres->xNbSpheres ; xDataElementIndex++ )
				{
					/* sphere */
					p_stIndexedSphere = p_stElementSpheres->d_stListOfSpheres + xDataElementIndex;
					
					/* centre de la sphere */
					p_stCenter = p_stGeomObj->d_stListOfPoints + p_stIndexedSphere->xCenterPoint;
					
					/* intersection segment - sphere */
					if
						(
						INT_fn_bIntersectSegmentWithSphere ( p_stVertexA, p_stVectAB,
						p_stCenter, p_stIndexedSphere->xRadius,
						&xT, &stHit, &stNormal )
						)
					{
						if ( MTH_M_bLess ( xT, xDistance ) )
						{
							bFound = TRUE;
							xDistance = xT;
							MTH3D_M_vCopyVector ( p_stHitPoint, &stHit );
							*p_xElement = xElementIndex;
							*p_xDataElement = xDataElementIndex;
						}
					}
				}
				break;
				
			case GEO_C_xElementAlignedBoxes :
				p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
				
				/* pour les boites */
				for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementAlignedBoxes->xNbAlignedBoxes ; xDataElementIndex++ )
				{
					/* boite */
					p_stIndexedAlignedBox = p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex;
					
					/* points de la boite */
					p_stMinPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMinPoint;
					p_stMaxPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMaxPoint;
					
					/* intersection segment - boite */
					if
						(
						INT_fn_bIntersectSegmentWithBox ( p_stVertexA, p_stVertexB, p_stVectAB,
						p_stMinPoint, p_stMaxPoint,
						&xT, &stHit, &stNormal )
						)
					{
						if ( MTH_M_bLess ( xT, xDistance ) )
						{
							bFound = TRUE;
							xDistance = xT;
							MTH3D_M_vCopyVector ( p_stHitPoint, &stHit );
							*p_xElement = xElementIndex;
							*p_xDataElement = xDataElementIndex;
						}
					}
				}
				break;
				
			default :
				break;
      }
    }
  }
  else
  {
	  COL_fn_vExploreOctreeWithSegment ( p_stGeomObj->p_stOctree, p_stVertexA, p_stVectAB,
		  aDEF_pstSelectedNode, aDEF_xSelectedT, &xNumberOfSelectedNodes );
	  
	  COL_g_lFacesTagCounter++;
	  
	  /* pour les noeuds selectionnes */
	  for ( xNodeIndex = 0 ; xNodeIndex < xNumberOfSelectedNodes ; xNodeIndex++ )
	  {
		  xNbElements  = *((COL_tdxFaceIndexDouble*)aDEF_pstSelectedNode[xNodeIndex]->d_xFaceIndexList);
		  p_xListIndex = (COL_tdxFaceIndex*)(((COL_tdxFaceIndexDouble*)aDEF_pstSelectedNode[xNodeIndex]->d_xFaceIndexList)+1);
 
		  for (xIndex = 0 ; xIndex < xNbElements ; xIndex++)
		  {
			if ((*p_xListIndex) < COL_C_MaxIndex)
				xElementIndex = (ACP_tdxIndex) (* (p_xListIndex ++));
			else
			{
				ACP_tdxIndex xData;
 
				xData=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData<<=8;
				xData+=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData&=~COL_C_OverflowIndex;
				xElementIndex = xData;
			}
 
			if ((*p_xListIndex) < COL_C_MaxIndex)
				xDataElementIndex = (ACP_tdxIndex) (* (p_xListIndex ++));
			else
			{
				ACP_tdxIndex xData;
 
				xData=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData<<=8;
				xData+=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData&=~COL_C_OverflowIndex;
				xDataElementIndex = xData;
			}
			  
			  /* verif tag */
			  if
				  (
				  COL_g_d_lTaggedFacesTable[(p_stGeomObj->p_stOctree)->d_xElementBasesTable[xElementIndex] + xDataElementIndex]
				  != COL_g_lFacesTagCounter
				  )
			  {
				  switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
				  {
				  case GEO_C_xElementIndexedTriangles :
					  p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
					  
					  /* points du triangle statique */
					  p_stVertex1 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0];
					  p_stVertex2 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1];
					  p_stVertex3 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2];
					  
					  /* calcul de la normale */
					  p_stNormal = p_stElementIndexedTriangles->d_stListOfFacesNormals + xDataElementIndex;
					  
					  /* calcul de d de l equation du plan */
					  xDPlan = MTH_M_xNeg ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertex1 ) );
					  
					  /* intersection segment - triangle */
					  if
						  (
						  INT_fn_bIntersectSegmentWithTriangle ( p_stVertexA, p_stVectAB,
						  p_stVertex1, p_stVertex2, p_stVertex3,
						  p_stNormal, xDPlan, &xT, &stHit )
						  )
					  {
						  if ( MTH_M_bLess ( xT, xDistance ) )
						  {
							  bFound = TRUE;
							  xDistance = xT;
							  MTH3D_M_vCopyVector ( p_stHitPoint, &stHit );
							  *p_xElement = xElementIndex;
							  *p_xDataElement = xDataElementIndex;
						  }
					  }
					  break;
					  
					  
				  case GEO_C_xElementSpheres :
					  p_stElementSpheres = (GEO_tdstElementSpheres *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
					  
					  /* sphere */
					  p_stIndexedSphere = p_stElementSpheres->d_stListOfSpheres + xDataElementIndex;
					  
					  /* centre de la sphere */
					  p_stCenter = p_stGeomObj->d_stListOfPoints + p_stIndexedSphere->xCenterPoint;
					  
					  /* intersection segment - sphere */
					  if
						  (
						  INT_fn_bIntersectSegmentWithSphere ( p_stVertexA, p_stVectAB,
						  p_stCenter, p_stIndexedSphere->xRadius,
						  &xT, &stHit, &stNormal )
						  )
					  {
						  if ( MTH_M_bLess ( xT, xDistance ) )
						  {
							  bFound = TRUE;
							  xDistance = xT;
							  MTH3D_M_vCopyVector ( p_stHitPoint, &stHit );
							  *p_xElement = xElementIndex;
							  *p_xDataElement = xDataElementIndex;
						  }
					  }
					  break;
					  
				  case GEO_C_xElementAlignedBoxes :
					  p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
					  
					  /* boite */
					  p_stIndexedAlignedBox = p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex;
					  
					  /* points de la boite */
					  p_stMinPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMinPoint;
					  p_stMaxPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMaxPoint;
					  
					  /* intersection segment - boite */
					  if
						  (
						  INT_fn_bIntersectSegmentWithBox ( p_stVertexA, p_stVertexB, p_stVectAB,
						  p_stMinPoint, p_stMaxPoint,
						  &xT, &stHit, &stNormal )
						  )
					  {
						  if ( MTH_M_bLess ( xT, xDistance ) )
						  {
							  bFound = TRUE;
							  xDistance = xT;
							  MTH3D_M_vCopyVector ( p_stHitPoint, &stHit );
							  *p_xElement = xElementIndex;
							  *p_xDataElement = xDataElementIndex;
						  }
					  }
					  break;
					  
#ifdef USE_ALTIMAPS
				  case GEO_C_xElementAltimap:
#endif /*USE_ALTIMAPS*/
				  default :
					  break;
          }
		  
          COL_g_d_lTaggedFacesTable[(p_stGeomObj->p_stOctree)->d_xElementBasesTable[xElementIndex] + xDataElementIndex]
			  = COL_g_lFacesTagCounter;
        }
      }
    }
  }
  
  return bFound;
}
#endif 
 
 
/*
--------------------------------------------------------------------------------
-- Description : Segment with face of geometric object intersection detection
--------------------------------------------------------------------------------
-- Creation date : 15 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*ANNECY CB On prend en compte le matériaux.*/
/*S'il n'est pas collisionnable, on ne tient*/
/*pas compte de ce qu'on pick (le test n'est*/
/*meme pas fait).*/
/*Fonction uniquement utilisée par la caméra*/
/*au moment de la modif (11/02/98)*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
 
/* used */
ACP_tdxBool INT_fn_bDetectIntersectSegmentWithFaceOfGeometricObject
(
	MTH3D_tdstVector		*p_stVertexA,
    MTH3D_tdstVector		*p_stVectAB,
	GEO_tdstGeometricObject *p_stGeomObj
)
{
	ACP_tdxIndex						          xElementIndex;
	ACP_tdxIndex						          xDataElementIndex;
	GEO_tdstElementIndexedTriangles		*p_stElementIndexedTriangles;
/*	GEO_tdstElementFaceMapDescriptors	*p_stElementFaceMapDescriptors;*/
	GEO_tdstElementSpheres				    *p_stElementSpheres;
	GEO_tdstElementAlignedBoxes			  *p_stElementAlignedBoxes;
 
	MTH3D_tdstVector					        *p_stVertex1;
	MTH3D_tdstVector					        *p_stVertex2;
	MTH3D_tdstVector					        *p_stVertex3;
	MTH3D_tdstVector					        *p_stNormal;
/*    MTH3D_tdstVector							stVertexB;*/
	MTH_tdxReal							          xDPlan;
	GEO_tdstIndexedSphere				      *p_stIndexedSphere;
	GEO_tdstIndexedAlignedBox			    *p_stIndexedAlignedBox;
	MTH3D_tdstVector					        *p_stCenter;
	MTH3D_tdstVector					        *p_stMinPoint;
	MTH3D_tdstVector					        *p_stMaxPoint;
	
	COL_tdxFaceIndex					        *p_xListIndex;
	ACP_tdxIndex						          xNodeIndex;
	COL_tdxFaceIndex					        xIndex;
	ACP_tdxIndex						          xNumberOfSelectedNodes;
	COL_tdpstOctreeNode					      aDEF_pstSelectedNode[COL_C_xMaxSelectedNodes];
	MTH_tdxReal							          aDEF_xSelectedT[COL_C_xMaxSelectedNodes];
	GMT_tdxHandleToCollideMaterial		hCollidedCollideMaterial;
	ACP_tdxIndex						xNbElements;
 
	if ( p_stGeomObj->p_stOctree == NULL )
	{
		/* pour les elements */
		for ( xElementIndex = 0 ; xElementIndex < p_stGeomObj->xNbElements ; xElementIndex++ )
		{
			switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
			{
			case GEO_C_xElementIndexedTriangles :
 
				p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
				
				hCollidedCollideMaterial = GMT_fn_hGetCollideMaterial(p_stElementIndexedTriangles->hMaterial);
				if
				(
					(hCollidedCollideMaterial != GMT_C_InvalidCollideMaterial)
				&&	(GMT_fn_hGetCollideMaterialIdentifier(hCollidedCollideMaterial) & 0xC000)
				)
					break;
				
				/* pour les triangles */
				for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementIndexedTriangles->xNbFaces ; xDataElementIndex++ )
				{
					/* points du triangle statique */
					p_stVertex1 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0];
					p_stVertex2 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1];
					p_stVertex3 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2];
					
					/* calcul de la normale */
					p_stNormal = p_stElementIndexedTriangles->d_stListOfFacesNormals + xDataElementIndex;
					
					/* calcul de d de l equation du plan */
					xDPlan = MTH_M_xNeg ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertex1 ) );
					
					/* intersection segment - triangle */
					if
					(
						INT_fn_bDetectIntersectSegmentWithTriangle ( p_stVertexA, p_stVectAB,
						p_stVertex1, p_stVertex2, p_stVertex3,
						p_stNormal, xDPlan )
					)
					{
						return TRUE;
					}
				}
				break;
 
#ifdef USE_ALTIMAPS
      case GEO_C_xElementAltimap :
        {
         	GEO_tdstElementAltimap            *p_stElementAltimap;
          ACP_tdxIndex      xAx, xAy, xBx, xBy, xLoopX, xLoopY, xLoopV, xIndex;
          MTH3D_tdstVector  stV1, stV2, stV3, stNorm;
          ACP_tdxBool       xBoolA, xBoolB;
          
 
          p_stElementAltimap = (GEO_tdstElementAltimap *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
          xBoolA = COL_ucSelectAltimapSquare( p_stElementAltimap, p_stVertexA, &xAx, &xAy );
          xBoolB = COL_ucSelectAltimapSquare( p_stElementAltimap, &stVertexB, &xBx, &xBy );
          COL_M_vClipSquareSelection( p_stElementAltimap, xAx, xAy, xBoolA );
          COL_M_vClipSquareSelection( p_stElementAltimap, xBx, xBy, xBoolB );
          
          COL_M_vScanSelectedSquares( xLoopX, xLoopY, xLoopV, p_stElementAltimap->xWidth, xAx, xAy, xBx, xBy )
          {
            unsigned char   ucType;
            
/*            ucType = p_stElementAltimap->d_stSquare[ xLoopV ].ucType & 0x0000000F;*/
            ucType = p_stElementAltimap->d_stSquare[ xLoopV ].ucType;
            while( ucType )
            {
              ucType = COL_ucBuildAltimapSquareTriangle( p_stElementAltimap, xLoopX, xLoopY, ucType,
                &stV1, &stV2, &stV3, &stNorm, &xIndex );
 
      				hCollidedCollideMaterial = GMT_fn_hGetCollideMaterial( p_stElementAltimap->d_hMaterial[ p_stElementAltimap->d_stFaces[ xIndex ].ucMatIndex ] );
			      	if( (hCollidedCollideMaterial != GMT_C_InvalidCollideMaterial)
				      &&	(GMT_fn_hGetCollideMaterialIdentifier(hCollidedCollideMaterial) & 0xC000) )
					      continue;
              
              /*--- Equation of face's plan*/
                xDPlan = MTH_M_xNeg( MTH3D_M_xDotProductVector( &stNorm, &stV1 ) );
              
              if( INT_fn_bDetectIntersectSegmentWithTriangle ( p_stVertexA, p_stVectAB,
                                                               &stV1, &stV2, &stV3, &stNorm, xDPlan ) )
                return TRUE;
            }
          }
        }
        break;              
#endif /*USE_ALTIMAPS*/
 
				
			case GEO_C_xElementSpheres :
 
				p_stElementSpheres = (GEO_tdstElementSpheres *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
				
				/* pour les spheres */
				for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementSpheres->xNbSpheres ; xDataElementIndex++ )
				{
					/* sphere */
					p_stIndexedSphere = p_stElementSpheres->d_stListOfSpheres + xDataElementIndex;
					
					hCollidedCollideMaterial = GMT_fn_hGetCollideMaterial(p_stIndexedSphere->hMaterial);
					if
					(
						(hCollidedCollideMaterial != GMT_C_InvalidCollideMaterial)
					&&	(GMT_fn_hGetCollideMaterialIdentifier(hCollidedCollideMaterial) & 0xC000)
					)
						continue;
 
					/* centre de la sphere */
					p_stCenter = p_stGeomObj->d_stListOfPoints + p_stIndexedSphere->xCenterPoint;
					
					/* intersection segment - sphere */
					if
					(
						INT_fn_bDetectIntersectSegmentWithSphere 
						(
							p_stVertexA, 
							p_stVectAB,
							p_stCenter, 
							p_stIndexedSphere->xRadius
						)
					)
					{
						return TRUE;
					}
				}
				break;
				
			case GEO_C_xElementAlignedBoxes :
				p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
				
				/* pour les boites */
				for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementAlignedBoxes->xNbAlignedBoxes ; xDataElementIndex++ )
				{
					/* boite */
					p_stIndexedAlignedBox = p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex;
					
					hCollidedCollideMaterial = GMT_fn_hGetCollideMaterial(p_stIndexedAlignedBox->hMaterial);
					if
					(
						(hCollidedCollideMaterial != GMT_C_InvalidCollideMaterial)
					&&	(GMT_fn_hGetCollideMaterialIdentifier(hCollidedCollideMaterial) & 0xC000)
					)
						continue;
 
					/* points de la boite */
					p_stMinPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMinPoint;
					p_stMaxPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMaxPoint;
					
					/* intersection segment - boite */
					if
						(
						INT_fn_bDetectIntersectSegmentWithBox ( p_stVertexA, p_stVectAB,
						p_stMinPoint, p_stMaxPoint, NULL )
						)
					{
						return TRUE;
					}
				}
				break;
				
			default :
				break;
			}
		}
	}
	else
	{
	  COL_fn_vExploreOctreeWithSegment ( p_stGeomObj->p_stOctree, p_stVertexA, p_stVectAB,
		  aDEF_pstSelectedNode, aDEF_xSelectedT, &xNumberOfSelectedNodes );
	  
	  COL_g_lFacesTagCounter++;
	  
	  /* pour les noeuds selectionnes */
	  for ( xNodeIndex = 0 ; xNodeIndex < xNumberOfSelectedNodes ; xNodeIndex++ )
	  {
		  xNbElements  = *((COL_tdxFaceIndexDouble*)aDEF_pstSelectedNode[xNodeIndex]->d_xFaceIndexList);
		  p_xListIndex = (COL_tdxFaceIndex*)(((COL_tdxFaceIndexDouble*)aDEF_pstSelectedNode[xNodeIndex]->d_xFaceIndexList)+1);
		  
		  for (xIndex = 0 ; xIndex < xNbElements ; xIndex++)
		  {
			if ((*p_xListIndex) < COL_C_MaxIndex)
				xElementIndex = (ACP_tdxIndex) (* (p_xListIndex ++));
			else
			{
				ACP_tdxIndex xData;
 
				xData=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData<<=8;
				xData+=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData&=~COL_C_OverflowIndex;
				xElementIndex = xData;
			}
 
			if ((*p_xListIndex) < COL_C_MaxIndex)
				xDataElementIndex = (ACP_tdxIndex) (* (p_xListIndex ++));
			else
			{
				ACP_tdxIndex xData;
 
				xData=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData<<=8;
				xData+=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData&=~COL_C_OverflowIndex;
				xDataElementIndex = xData;
			}
			  
			  /* verif tag */
			  if
				  (
				  COL_g_d_lTaggedFacesTable[(p_stGeomObj->p_stOctree)->d_xElementBasesTable[xElementIndex] + xDataElementIndex]
				  != COL_g_lFacesTagCounter
				  )
			  {
				  switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
				  {
				  case GEO_C_xElementIndexedTriangles :
 
					  p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
					  
						hCollidedCollideMaterial = GMT_fn_hGetCollideMaterial(p_stElementIndexedTriangles->hMaterial);
						if
						(
							(hCollidedCollideMaterial != GMT_C_InvalidCollideMaterial)
						&&	(GMT_fn_hGetCollideMaterialIdentifier(hCollidedCollideMaterial) & 0xC000)
						)
							break;
 
					  /* points du triangle statique */
					  p_stVertex1 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0];
					  p_stVertex2 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1];
					  p_stVertex3 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2];
					  
					  /* calcul de la normale */
					  p_stNormal = p_stElementIndexedTriangles->d_stListOfFacesNormals + xDataElementIndex;
					  
					  /* calcul de d de l equation du plan */
					  xDPlan = MTH_M_xNeg ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertex1 ) );
					  
					  /* intersection segment - triangle */
					  if
						  (
						  INT_fn_bDetectIntersectSegmentWithTriangle ( p_stVertexA, p_stVectAB,
						  p_stVertex1, p_stVertex2, p_stVertex3,
						  p_stNormal, xDPlan )
						  )
					  {
						  return TRUE;
					  }
					  break;
 
					  
				  case GEO_C_xElementSpheres :
					  p_stElementSpheres = (GEO_tdstElementSpheres *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
					  
					  /* sphere */
					  p_stIndexedSphere = p_stElementSpheres->d_stListOfSpheres + xDataElementIndex;
					  
						hCollidedCollideMaterial = GMT_fn_hGetCollideMaterial(p_stIndexedSphere->hMaterial);
						if
						(
							(hCollidedCollideMaterial != GMT_C_InvalidCollideMaterial)
						&&	(GMT_fn_hGetCollideMaterialIdentifier(hCollidedCollideMaterial) & 0xC000)
						)
							break;
 
					  /* centre de la sphere */
					  p_stCenter = p_stGeomObj->d_stListOfPoints + p_stIndexedSphere->xCenterPoint;
					  
					  /* intersection segment - sphere */
					  if
						  (
						  INT_fn_bDetectIntersectSegmentWithSphere ( p_stVertexA, p_stVectAB,
						  p_stCenter, p_stIndexedSphere->xRadius )
						  )
					  {
						  return TRUE;
					  }
					  break;
					  
				  case GEO_C_xElementAlignedBoxes :
					  p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
					  
					  /* boite */
					  p_stIndexedAlignedBox = p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex;
					  
						hCollidedCollideMaterial = GMT_fn_hGetCollideMaterial(p_stIndexedAlignedBox->hMaterial);
						if
						(
							(hCollidedCollideMaterial != GMT_C_InvalidCollideMaterial)
						&&	(GMT_fn_hGetCollideMaterialIdentifier(hCollidedCollideMaterial) & 0xC000)
						)
							break;
 
					  /* points de la boite */
					  p_stMinPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMinPoint;
					  p_stMaxPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMaxPoint;
					  
					  /* intersection segment - boite */
					  if
					  (
						  INT_fn_bDetectIntersectSegmentWithBox ( p_stVertexA, p_stVectAB,
						  p_stMinPoint, p_stMaxPoint, NULL )
					  )
					  {
						  return TRUE;
					  }
					  break;
				
#ifdef USE_ALTIMAPS
          case GEO_C_xElementAltimap:
#endif /*USE_ALTIMAPS*/
				  default :
					  break;
				  }
				  
				  COL_g_d_lTaggedFacesTable[(p_stGeomObj->p_stOctree)->d_xElementBasesTable[xElementIndex] + xDataElementIndex]
					  = COL_g_lFacesTagCounter;
        }
      }
    }
  }
  
  return FALSE;
}
 
/*
--------------------------------------------------------------------------------
-- Description : Semiaxe with face of geometric object intersection test
--------------------------------------------------------------------------------
-- Creation date : 18 nov 1996               Author : FPI
--------------------------------------------------------------------------------
*/
 
 
#if defined(ACTIVE_EDITOR)			
/*active editor only*/
ACP_tdxBool INT_fn_bIntersectSemiAxeWithFaceOfGeometricObject ( MTH3D_tdstVector *p_stVertexA,
                                                                MTH3D_tdstVector *p_stVertexB,
                                                                MTH3D_tdstVector *p_stVectAB,
                                                                GEO_tdstGeometricObject *p_stGeomObj,
                                                                ACP_tdxIndex xNbMaxElements,
                                                                ACP_tdxIndex *p_xNbElements,
                                                                struct GLI_tdstDataOfElement_ *d_stDataOfElement )
{
  ACP_tdxIndex                      xElementIndex;
  COL_tdxFaceIndex                  *p_xListIndex;
  GEO_tdstElementIndexedTriangles   *p_stElementIndexedTriangles;
/*  GEO_tdstElementFaceMapDescriptors *p_stElementFaceMapDescriptors;*/
/*  GEO_tdstElementTMeshes            *p_stElementTMeshes;*/
  GEO_tdstElementSpheres            *p_stElementSpheres;
  GEO_tdstElementAlignedBoxes       *p_stElementAlignedBoxes;
  GEO_tdstElementCones              *p_stElementCones;
 
  ACP_tdxIndex xNodeIndex;
  ACP_tdxIndex xDataElementIndex;
/*  ACP_tdxIndex xAtomIndex;*/
  COL_tdxFaceIndex xIndex;
/*  ACP_tdxBool bPointsSpin;*/
  MTH3D_tdstVector *p_stVertex1;
  MTH3D_tdstVector *p_stVertex2;
  MTH3D_tdstVector *p_stVertex3;
  MTH3D_tdstVector *p_stNormal;
  MTH_tdxReal xDPlan;
  GEO_tdstIndexedSphere *p_stIndexedSphere;
  GEO_tdstIndexedAlignedBox *p_stIndexedAlignedBox;
  GEO_tdstIndexedCone *p_stIndexedCone;
  MTH3D_tdstVector *p_stCenter;
  MTH3D_tdstVector *p_stMinPoint;
  MTH3D_tdstVector *p_stMaxPoint;
  MTH3D_tdstVector *p_stTopPoint;
  MTH3D_tdstVector *p_stBasePoint;
  MTH3D_tdstVector stNormal;
 
  ACP_tdxBool bBack;
  MTH_tdxReal xT;
  MTH3D_tdstVector stHit;
 
  ACP_tdxIndex xNumberOfSelectedNodes;
  COL_tdpstOctreeNode aDEF_pstSelectedNode[COL_C_xMaxSelectedNodes];
  MTH_tdxReal aDEF_xSelectedT[COL_C_xMaxSelectedNodes];
  GMT_tdxHandleToGameMaterial		hMaterial = NULL;
  GMT_tdxHandleToCollideMaterial	hCM = NULL;
  ACP_tdxIndex						xNbElements;
 
  *p_xNbElements = 0;
 
  if ( p_stGeomObj->p_stOctree == NULL )
  {
    /* pour les elements */
    for ( xElementIndex = 0 ; xElementIndex < p_stGeomObj->xNbElements ; xElementIndex++ )
    {
      switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
      {
        case GEO_C_xElementIndexedTriangles :
		  if (g_xMask != 0)
		  {
  				GEO_vGetGameMaterialOfIndexedTriangles( p_stGeomObj, xElementIndex, &hMaterial );
				if ( hMaterial != NULL)
				{
					hCM = GMT_fn_hGetCollideMaterial( hMaterial );
					if (hCM != GMT_C_InvalidCollideMaterial)
					{
						/*any bit of NoShadow, Water or Uncollidable cancels shadow projection*/
						if ((GMT_fn_hGetCollideMaterialIdentifier( hCM ) & g_xMask ) == 0x0000 )
							break;
					}
					else
						break;
				}
				else
					break;
		  }
 
          p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
          /* pour les triangles */
          for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementIndexedTriangles->xNbFaces ; xDataElementIndex++ )
          {
            /* points du triangle statique */
            p_stVertex1 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0];
            p_stVertex2 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1];
            p_stVertex3 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2];
 
            /* calcul de la normale */
            p_stNormal = p_stElementIndexedTriangles->d_stListOfFacesNormals + xDataElementIndex;
 
            /* calcul de d de l equation du plan */
            xDPlan = MTH_M_xNeg ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertex1 ) );
 
            /* intersection semiaxe - triangle */
            if
              (
                INT_fn_bIntersectSemiAxeWithTriangle ( p_stVertexA, p_stVectAB,
                                                       p_stVertex1, p_stVertex2, p_stVertex3,
                                                       p_stNormal, xDPlan, &bBack, &xT, &stHit )
              )
            {
              INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
                                                    p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
            }
          }
        break;
 
#ifdef USE_ALTIMAPS
        case GEO_C_xElementAltimap :
          {
            GEO_tdstElementAltimap            *p_stElementAltimap;
            ACP_tdxIndex      xAx, xAy, xBx, xBy, xLoopX, xLoopY, xLoopV, xIndex;
            MTH3D_tdstVector  stV1, stV2, stV3, stNorm;
            ACP_tdxBool       xBoolA, xBoolB;
 
            p_stElementAltimap = (GEO_tdstElementAltimap *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
            xBoolA = COL_ucSelectAltimapSquare( p_stElementAltimap, p_stVertexA, &xAx, &xAy );
            xBoolB = COL_ucSelectAltimapSquare( p_stElementAltimap, p_stVertexB, &xBx, &xBy );
            COL_M_vClipSquareSelection( p_stElementAltimap, xAx, xAy, xBoolA );
            COL_M_vClipSquareSelection( p_stElementAltimap, xBx, xBy, xBoolB );
 
            COL_M_vSortSquareSelection( xAx, xBx );                                              
            COL_M_vSortSquareSelection( xAy, xBy );
 
            COL_M_vScanSelectedSquares( xLoopX, xLoopY, xLoopV, p_stElementAltimap->xWidth, xAx, xAy, xBx, xBy )
            {
              unsigned char   ucType;
 
              ucType = p_stElementAltimap->d_stSquare[ xLoopV ].ucType;
              while( ucType )
              {
                ucType = COL_ucBuildAltimapSquareTriangle( p_stElementAltimap, xLoopX, xLoopY, ucType,
                                                           &stV1, &stV2, &stV3, &stNorm, &xIndex );
 
                /*--- Equation of face's plan*/
                xDPlan = MTH_M_xNeg( MTH3D_M_xDotProductVector( &stNorm, &stV1 ) );
        
                if( INT_fn_bIntersectSemiAxeWithTriangle( p_stVertexA, p_stVectAB, 
                                                          &stV1, &stV2, &stV3,
                                                          &stNorm, xDPlan, &bBack, &xT, &stHit ) )
                  INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
                                                        p_stVertexA, bBack, &stHit, xElementIndex, xIndex );
              }
            }
          }
          break;              
#endif /*USE_ALTIMAPS*/
 
 
        case GEO_C_xElementSpheres :
          p_stElementSpheres = (GEO_tdstElementSpheres *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
          /* pour les spheres */
          for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementSpheres->xNbSpheres ; xDataElementIndex++ )
          {
            /* sphere */
            p_stIndexedSphere = p_stElementSpheres->d_stListOfSpheres + xDataElementIndex;
 
            /* centre de la sphere */
            p_stCenter = p_stGeomObj->d_stListOfPoints + p_stIndexedSphere->xCenterPoint;
 
            /* intersection semiaxe - sphere */
            if
              (
                INT_fn_bIntersectSemiAxeWithSphere ( p_stVertexA, p_stVectAB,
                                                     p_stCenter, p_stIndexedSphere->xRadius,
                                                     &bBack, &xT, &stHit, &stNormal )
              )
            {
              INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
                                                    p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
            }
          }
        break;
 
        case GEO_C_xElementAlignedBoxes :
          p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
          /* pour les boites */
          for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementAlignedBoxes->xNbAlignedBoxes ; xDataElementIndex++ )
          {
            /* boite */
            p_stIndexedAlignedBox = p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex;
 
            /* points de la boite */
            p_stMinPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMinPoint;
            p_stMaxPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMaxPoint;
 
            /* intersection semiaxe - boite */
            if
              (
                INT_fn_bIntersectSemiAxeWithBox ( p_stVertexA, p_stVertexB, p_stVectAB,
                                                  p_stMinPoint, p_stMaxPoint,
                                                  &bBack, &xT, &stHit, &stNormal )
              )
            {
              INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
                                                    p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
            }
          }
        break;
 
        case GEO_C_xElementCones :
          p_stElementCones = (GEO_tdstElementCones *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
          /* pour les cones */
          for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementCones->xNbCones ; xDataElementIndex++ )
          {
            /* cone */
            p_stIndexedCone = p_stElementCones->d_stListOfCones + xDataElementIndex;
 
            /* points de la boite */
            p_stTopPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedCone->xTopPoint;
            p_stBasePoint = p_stGeomObj->d_stListOfPoints + p_stIndexedCone->xBasePoint;
 
            /* intersection semiaxe - cone */
            if
              (
                INT_fn_bIntersectSemiAxeWithCone ( p_stVertexA, p_stVectAB,
                                                  p_stTopPoint, p_stBasePoint, p_stIndexedCone->xBaseRadius,
                                                  &bBack, &xT, &stHit )
              )
            {
              INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
                                                    p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
            }
          }
        break;
 
        default :
        break;
      }
    }
  }
  else
  {
    COL_fn_vExploreOctreeWithSemiAxe ( p_stGeomObj->p_stOctree, p_stVertexA, p_stVertexB, p_stVectAB,
                                       aDEF_pstSelectedNode, aDEF_xSelectedT, &xNumberOfSelectedNodes );
 
    COL_g_lFacesTagCounter++;
 
    /* pour les noeuds selectionnes */
    for ( xNodeIndex = 0 ; xNodeIndex < xNumberOfSelectedNodes ; xNodeIndex++ )
    {
		  xNbElements  = *((COL_tdxFaceIndexDouble*)aDEF_pstSelectedNode[xNodeIndex]->d_xFaceIndexList);
		  p_xListIndex = (COL_tdxFaceIndex*)(((COL_tdxFaceIndexDouble*)aDEF_pstSelectedNode[xNodeIndex]->d_xFaceIndexList)+1);
		  
		  for (xIndex = 0 ; xIndex < xNbElements ; xIndex++)
		  {
			if ((*p_xListIndex) < COL_C_MaxIndex)
				xElementIndex = (ACP_tdxIndex) (* (p_xListIndex ++));
			else
			{
				ACP_tdxIndex xData;
 
				xData=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData<<=8;
				xData+=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData&=~COL_C_OverflowIndex;
				xElementIndex = xData;
			}
 
			if ((*p_xListIndex) < COL_C_MaxIndex)
				xDataElementIndex = (ACP_tdxIndex) (* (p_xListIndex ++));
			else
			{
				ACP_tdxIndex xData;
 
				xData=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData<<=8;
				xData+=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData&=~COL_C_OverflowIndex;
				xDataElementIndex = xData;
			}
 
        /* verif tag */
        if
          (
            COL_g_d_lTaggedFacesTable[(p_stGeomObj->p_stOctree)->d_xElementBasesTable[xElementIndex] + xDataElementIndex]
            != COL_g_lFacesTagCounter
          )
        {
          switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
          {
            case GEO_C_xElementIndexedTriangles :
			  if (g_xMask != 0)
			  {
  					GEO_vGetGameMaterialOfIndexedTriangles( p_stGeomObj, xElementIndex, &hMaterial );
					if ( hMaterial != NULL)
					{
						hCM = GMT_fn_hGetCollideMaterial( hMaterial );
						if (hCM != GMT_C_InvalidCollideMaterial)
						{
							/*any bit of NoShadow, Water or Uncollidable cancels shadow projection*/
							if ((GMT_fn_hGetCollideMaterialIdentifier( hCM ) & g_xMask ) == 0x0000 )
								break;
						}
						else
							break;
					}
					else
						break;
			  }
              p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
              /* points du triangle statique */
              p_stVertex1 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0];
              p_stVertex2 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1];
              p_stVertex3 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2];
 
              /* calcul de la normale */
              p_stNormal = p_stElementIndexedTriangles->d_stListOfFacesNormals + xDataElementIndex;
 
              /* calcul de d de l equation du plan */
              xDPlan = MTH_M_xNeg ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertex1 ) );
 
              /* intersection segment - triangle */
              if
                (
                  INT_fn_bIntersectSemiAxeWithTriangle ( p_stVertexA, p_stVectAB,
                                                         p_stVertex1, p_stVertex2, p_stVertex3,
                                                         p_stNormal, xDPlan, &bBack, &xT, &stHit )
                )
              {
                INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
                                                      p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
              }
            break;
 
 
            case GEO_C_xElementSpheres :
              p_stElementSpheres = (GEO_tdstElementSpheres *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
              /* sphere */
              p_stIndexedSphere = p_stElementSpheres->d_stListOfSpheres + xDataElementIndex;
 
              /* centre de la sphere */
              p_stCenter = p_stGeomObj->d_stListOfPoints + p_stIndexedSphere->xCenterPoint;
 
              /* intersection segment - sphere */
              if
                (
                  INT_fn_bIntersectSemiAxeWithSphere ( p_stVertexA, p_stVectAB,
                                                       p_stCenter, p_stIndexedSphere->xRadius,
                                                       &bBack, &xT, &stHit, &stNormal )
                )
              {
                INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
                                                      p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
              }
            break;
 
            case GEO_C_xElementAlignedBoxes :
              p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
              /* boite */
              p_stIndexedAlignedBox = p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex;
 
              /* points de la boite */
              p_stMinPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMinPoint;
              p_stMaxPoint = p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMaxPoint;
 
              /* intersection segment - boite */
              if
                (
                  INT_fn_bIntersectSemiAxeWithBox ( p_stVertexA, p_stVertexB, p_stVectAB,
                                                    p_stMinPoint, p_stMaxPoint,
                                                    &bBack, &xT, &stHit, &stNormal )
                )
              {
                INT_fn_vViewAndAddFaceElementInList ( xNbMaxElements, p_xNbElements, d_stDataOfElement,
                                                      p_stVertexA, bBack, &stHit, xElementIndex, xDataElementIndex );
              }
            break;
 
            default :
            break;
          }
 
          COL_g_d_lTaggedFacesTable[(p_stGeomObj->p_stOctree)->d_xElementBasesTable[xElementIndex] + xDataElementIndex]
            = COL_g_lFacesTagCounter;
        }
      }
    }
  }
 
  return (*p_xNbElements) > 0;
}
 
#endif /* ACTIVE_EDITOR*/
 
 
 
/*
--------------------------------------------------------------------------------
-- Description : View and add face in list a data of element
--------------------------------------------------------------------------------
-- Creation date : 18 nov 1996               Author : FPI
--------------------------------------------------------------------------------
*/
#ifndef U64
/* used only for complex shadow calculation*/
void INT_fn_vViewAndAddFaceElementInShadowList ( ACP_tdxIndex xNbMaxElements,
                                                 ACP_tdxIndex *p_xNbElements,
                                                 COL_tdstShadowElement *d_stShadowElement,
/*                                                 MTH_tdxReal xT,*/
												 GEO_tdstGeometricObject *p_stGeomObj,
                                                 ACP_tdxIndex xElementIndex,
                                                 ACP_tdxIndex xDataElementIndex )
{
  ACP_tdxIndex						xFaceIndex;
  GMT_tdxHandleToGameMaterial		hMaterial;
  GMT_tdxHandleToCollideMaterial	hCM;
 
 
  	hMaterial = NULL;
	switch (GEO_xGetElementType( p_stGeomObj, xElementIndex ) )
	{
		case GEO_C_xElementIndexedTriangles:
			{
				GEO_vGetGameMaterialOfIndexedTriangles( p_stGeomObj, xElementIndex, &hMaterial );
				break;
			}
#ifdef USE_ALTIMAPS
    case GEO_C_xElementAltimap:
      {
        GEO_tdstElementAltimap  * p_stAltimap;
        p_stAltimap = (GEO_tdstElementAltimap *) p_stGeomObj->d_stListOfElements[ xElementIndex ];
        hMaterial = p_stAltimap->d_hMaterial[ p_stAltimap->d_stFaces[ xDataElementIndex ].ucMatIndex ];
        break;
      }
#endif /*USE_ALTIMAPS*/
/*
    case GEO_C_xElementFaceMapDescriptors:
			{
				break;
			}
*/
	}
	
	if ( hMaterial != NULL)
	{
 
		hCM = GMT_fn_hGetCollideMaterial( hMaterial );
		if (hCM != GMT_C_InvalidCollideMaterial)
		{
			/*any bit of NoShadow, Water or Uncollidable cancels shadow projection*/
			if ((GMT_fn_hGetCollideMaterialIdentifier( hCM ) & 0xE000 ) != 0x0000 )
				return;
		}
	}
	  /* index sur le dernier element */
	xFaceIndex = *p_xNbElements;
	if ( xFaceIndex < xNbMaxElements )
	{
		/* xFaceIndex */
		d_stShadowElement[xFaceIndex].xElementIndex = xElementIndex;
		d_stShadowElement[xFaceIndex].xDataElementIndex = xDataElementIndex;
		if ( (*p_xNbElements) < xNbMaxElements )
		  (*p_xNbElements)++;
  }
}
 
#endif
/*
--------------------------------------------------------------------------------
-- Description : Semiaxe with shadow face of geometric object intersection test
--------------------------------------------------------------------------------
-- Creation date : 29 may 1997               Author : FPI
--------------------------------------------------------------------------------
*/
#ifndef U64
/* used only for complex shadow calculation*/
ACP_tdxBool INT_fn_bIntersectSegmentWithShadowFaceOfGeometricObject ( MTH3D_tdstVector *p_stVertexA,
                                                                      MTH3D_tdstVector *p_stVertexB,
                                                                      MTH3D_tdstVector *p_stVectAB,
                                                                      GEO_tdstGeometricObject *p_stGeomObj,
                                                                      MTH3D_tdstVector *p_stHit,
                                                                      ACP_tdxIndex *p_xElement,
                                                                      ACP_tdxIndex *p_xDataElements
																	  )
{
  ACP_tdxBool						bIntersect = FALSE;
  GMT_tdxHandleToGameMaterial		hMaterial = NULL;
  GMT_tdxHandleToCollideMaterial	hCM = NULL;
 
  *p_xElement = 0;
 
  if
    (
      INT_fn_bIntersectSegmentWithFirstFaceOfGeometricObject ( p_stVertexA, p_stVertexB, p_stVectAB, p_stGeomObj,
                                                               p_stHit, p_xElement, p_xDataElements )
    )
  {
        switch ( p_stGeomObj->d_xListOfElementsTypes[*p_xElement] )
        {
          case GEO_C_xElementIndexedTriangles :
  				GEO_vGetGameMaterialOfIndexedTriangles( p_stGeomObj, *p_xElement, &hMaterial );
				if ( hMaterial != NULL)
				{
					hCM = GMT_fn_hGetCollideMaterial( hMaterial );
					if (hCM != GMT_C_InvalidCollideMaterial)
					{
/*						//any bit of NoShadow, Water or Uncollidable cancels shadow projection
						if ((GMT_fn_hGetCollideMaterialIdentifier( hCM ) & 0xE000 ) == 0x0000 )
*/
						/*any bit of Water or Uncollidable cancels shadow projection */
						if ((GMT_fn_hGetCollideMaterialIdentifier( hCM ) & 0xA000 ) == 0x0000 )
							bIntersect = TRUE;
					}
					else
						bIntersect = TRUE;
				}
				else
					bIntersect = TRUE;
 
          break;
 
#ifdef USE_ALTIMAPS
        case GEO_C_xElementAltimap :
			bIntersect = TRUE;
          break;              
#endif /*USE_ALTIMAPS*/
 
/*
        case GEO_C_xElementFaceMapDescriptors :
			bIntersect = TRUE;
          break;
*/
 
          default :
          break;
        }
	}
	return 	bIntersect;
 
/*  return (*p_xNbElements) > 0;*/
}
 
#endif
/*
--------------------------------------------------------------------------------
-- Description : Sphere with shadow face of geometric object intersection test
--------------------------------------------------------------------------------
-- Creation date : 05 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
/*DONE//*/
 
#ifndef U64
/* used only for complex shadow calculation*/
ACP_tdxBool INT_fn_bIntersectSphereWithShadowFaceOfGeometricObject ( MTH3D_tdstVector *p_stCenter,
                                                                     MTH_tdxReal _xRadius,
                                                                     GEO_tdstGeometricObject *p_stGeomObj,
                                                                     ACP_tdxIndex xNbMaxElements,
                                                                     ACP_tdxIndex *p_xNbElements,
                                                                     COL_tdstShadowElement *d_stShadowElement,
																	 ACP_tdxBool	*p_bBadMaterial)
{
  ACP_tdxIndex                      xElementIndex;
  ACP_tdxIndex                      xDataElementIndex;
  GEO_tdstElementIndexedTriangles   *p_stElementIndexedTriangles;
/*  GEO_tdstElementFaceMapDescriptors *p_stElementFaceMapDescriptors;*/
 
  MTH3D_tdstVector                  *p_stVertex1;
  MTH3D_tdstVector                  *p_stVertex2;
  MTH3D_tdstVector                  *p_stVertex3;
  MTH3D_tdstVector                  stVect12;
  MTH3D_tdstVector                  stVect23;
  MTH3D_tdstVector                  stVect31;
  MTH3D_tdstVector                  stMinPoint;
  MTH3D_tdstVector                  stMaxPoint;
 
  COL_tdxFaceIndex                  *p_xListIndex;
  ACP_tdxIndex                      xNodeIndex;
  COL_tdxFaceIndex                  xIndex;
  ACP_tdxIndex                      xNumberOfSelectedNodes;
  COL_tdpstOctreeNode               aDEF_pstSelectedNode[COL_C_xMaxSelectedNodes];
  MTH_tdxReal                       xRadius;
  GMT_tdxHandleToGameMaterial		hMaterial = NULL;
  GMT_tdxHandleToCollideMaterial	hCM = NULL;
  ACP_tdxIndex						xNbElements;
 
  *p_xNbElements = 0;
  *p_bBadMaterial = FALSE;
 
  xRadius = MTH_M_xSqr ( _xRadius );
 
  if ( p_stGeomObj->p_stOctree == NULL )
  {
	 /* pour les elements */
    for ( xElementIndex = 0 ; xElementIndex < p_stGeomObj->xNbElements ; xElementIndex++ )
    {
      switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
      {
        case GEO_C_xElementIndexedTriangles :
			GEO_vGetGameMaterialOfIndexedTriangles( p_stGeomObj, xElementIndex, &hMaterial );
			if ( hMaterial != NULL)
			{
				hCM = GMT_fn_hGetCollideMaterial( hMaterial );
				if (hCM != GMT_C_InvalidCollideMaterial)
					/*any bit of NoShadow, Water or Uncollidable cancels shadow projection*/
					if ((GMT_fn_hGetCollideMaterialIdentifier( hCM ) & 0xE000 ) != 0x0000 )
					{
						if ((GMT_fn_hGetCollideMaterialIdentifier( hCM ) & 0x6000 ) != 0x0000 )
							*p_bBadMaterial = TRUE;
						break;
					}
			}
 
 
			p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
			/* pour les triangles */
			for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementIndexedTriangles->xNbFaces ; xDataElementIndex++ )
			{
				/* points du triangle statique */
				p_stVertex1 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0];
				p_stVertex2 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1];
				p_stVertex3 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2];
 
				MTH3D_M_vSubVector ( &stVect12, p_stVertex2, p_stVertex1 );
				MTH3D_M_vSubVector ( &stVect23, p_stVertex3, p_stVertex2 );
				MTH3D_M_vSubVector ( &stVect31, p_stVertex1, p_stVertex3 );
 
				if
				  (
					MTH_M_bLessEqual ( INT_fn_xSqrDistancePointToSegment ( p_stCenter, p_stVertex1, &stVect12 ), xRadius )
					|| MTH_M_bLessEqual ( INT_fn_xSqrDistancePointToSegment ( p_stCenter, p_stVertex2, &stVect23 ), xRadius )
					|| MTH_M_bLessEqual ( INT_fn_xSqrDistancePointToSegment ( p_stCenter, p_stVertex3, &stVect31 ), xRadius )
				  )
				{
				  INT_fn_vViewAndAddFaceElementInShadowList ( xNbMaxElements, p_xNbElements, d_stShadowElement,
															  p_stGeomObj, xElementIndex, xDataElementIndex );
				}
			}
			break;
 
#ifdef USE_ALTIMAPS
        case GEO_C_xElementAltimap :
          {
            GEO_tdstElementAltimap            *p_stElementAltimap;
            ACP_tdxIndex      xAx, xAy, xBx, xBy, xLoopX, xLoopY, xLoopV, xIndex;
            MTH3D_tdstVector  stV1, stV2, stV3, stNorm;
            ACP_tdxBool       xBoolA, xBoolB;
            MTH3D_tdstVector  stVertexA, stVertexB;
 
            MTH3D_M_vSubScalarVector( &stVertexA, _xRadius * MTH_C_Sqrt2, p_stCenter );
            MTH3D_M_vAddScalarVector( &stVertexB, _xRadius * MTH_C_Sqrt2, p_stCenter );
 
            p_stElementAltimap = (GEO_tdstElementAltimap *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
            xBoolA = COL_ucSelectAltimapSquare( p_stElementAltimap, &stVertexA, &xAx, &xAy );
            xBoolB = COL_ucSelectAltimapSquare( p_stElementAltimap, &stVertexB, &xBx, &xBy );
            COL_M_vClipSquareSelection( p_stElementAltimap, xAx, xAy, xBoolA );
            COL_M_vClipSquareSelection( p_stElementAltimap, xBx, xBy, xBoolB );
 
            COL_M_vScanSelectedSquares( xLoopX, xLoopY, xLoopV, p_stElementAltimap->xWidth, xAx, xAy, xBx, xBy )
            {
              unsigned char   ucType;
 
              ucType = p_stElementAltimap->d_stSquare[ xLoopV ].ucType;
              while( ucType )
              {
                ucType = COL_ucBuildAltimapSquareTriangle( p_stElementAltimap, xLoopX, xLoopY, ucType,
                                                           &stV1, &stV2, &stV3, &stNorm, &xIndex );
 
                MTH3D_M_vSubVector ( &stVect12, &stV2, &stV1 );
                MTH3D_M_vSubVector ( &stVect23, &stV3, &stV2 );
                MTH3D_M_vSubVector ( &stVect31, &stV1, &stV3 );
 
                if( MTH_M_bLessEqual ( INT_fn_xSqrDistancePointToSegment ( p_stCenter, &stV1, &stVect12 ), xRadius )
                 || MTH_M_bLessEqual ( INT_fn_xSqrDistancePointToSegment ( p_stCenter, &stV2, &stVect23 ), xRadius )
                 || MTH_M_bLessEqual ( INT_fn_xSqrDistancePointToSegment ( p_stCenter, &stV3, &stVect31 ), xRadius ) )
                {
                  INT_fn_vViewAndAddFaceElementInShadowList ( xNbMaxElements, p_xNbElements, d_stShadowElement,
                                                              p_stGeomObj, xElementIndex, xIndex );
                }
              }
            }
          }
          break;              
#endif /*USE_ALTIMAPS*/
 
        default :
        break;
      }
    }
  }
  else
  {
    COL_fn_vComputeBoundingBoxOfSphere ( &stMinPoint, &stMaxPoint, p_stCenter, _xRadius );
 
    COL_fn_vExploreOctreeWithBox ( p_stGeomObj->p_stOctree, &stMinPoint, &stMaxPoint,
                                   aDEF_pstSelectedNode, &xNumberOfSelectedNodes );
 
    COL_g_lFacesTagCounter++;
 
   /* pour les noeuds selectionnes */
    for ( xNodeIndex = 0 ; xNodeIndex < xNumberOfSelectedNodes ; xNodeIndex++ )
    {
		  xNbElements  = *((COL_tdxFaceIndexDouble*)aDEF_pstSelectedNode[xNodeIndex]->d_xFaceIndexList);
		  p_xListIndex = (COL_tdxFaceIndex*)(((COL_tdxFaceIndexDouble*)aDEF_pstSelectedNode[xNodeIndex]->d_xFaceIndexList)+1);
		  
		  for (xIndex = 0 ; xIndex < xNbElements ; xIndex++)
		  {
			if ((*p_xListIndex) < COL_C_MaxIndex)
				xElementIndex = (ACP_tdxIndex) (* (p_xListIndex ++));
			else
			{
				ACP_tdxIndex xData;
 
				xData=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData<<=8;
				xData+=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData&=~COL_C_OverflowIndex;
				xElementIndex = xData;
			}
 
			if ((*p_xListIndex) < COL_C_MaxIndex)
				xDataElementIndex = (ACP_tdxIndex) (* (p_xListIndex ++));
			else
			{
				ACP_tdxIndex xData;
 
				xData=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData<<=8;
				xData+=(ACP_tdxIndex)(* (p_xListIndex ++));
				xData&=~COL_C_OverflowIndex;
				xDataElementIndex = xData;
			}
 
		/* verif tag */
        if
          (
            COL_g_d_lTaggedFacesTable[(p_stGeomObj->p_stOctree)->d_xElementBasesTable[xElementIndex] + xDataElementIndex]
            != COL_g_lFacesTagCounter
          )
        {
          switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
          {
            case GEO_C_xElementIndexedTriangles :
				GEO_vGetGameMaterialOfIndexedTriangles( p_stGeomObj, xElementIndex, &hMaterial );
				if ( hMaterial != NULL)
				{
					hCM = GMT_fn_hGetCollideMaterial( hMaterial );
					if (hCM != GMT_C_InvalidCollideMaterial)
						/*any bit of NoShadow, Water or Uncollidable cancels shadow projection*/
						if ((GMT_fn_hGetCollideMaterialIdentifier( hCM ) & 0xE000 ) != 0x0000 )
						{
							*p_bBadMaterial = TRUE;
							break;
						}
				}
				p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
				/* points du triangle statique */
				p_stVertex1 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0];
				p_stVertex2 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1];
				p_stVertex3 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2];
 
				MTH3D_M_vSubVector ( &stVect12, p_stVertex2, p_stVertex1 );
				MTH3D_M_vSubVector ( &stVect23, p_stVertex3, p_stVertex2 );
				MTH3D_M_vSubVector ( &stVect31, p_stVertex1, p_stVertex3 );
 
				if
				(
				MTH_M_bLessEqual ( INT_fn_xSqrDistancePointToSegment ( p_stCenter, p_stVertex1, &stVect12 ), xRadius )
				|| MTH_M_bLessEqual ( INT_fn_xSqrDistancePointToSegment ( p_stCenter, p_stVertex2, &stVect23 ), xRadius )
				|| MTH_M_bLessEqual ( INT_fn_xSqrDistancePointToSegment ( p_stCenter, p_stVertex3, &stVect31 ), xRadius )
				)
				{
					INT_fn_vViewAndAddFaceElementInShadowList ( xNbMaxElements, p_xNbElements, d_stShadowElement,
													p_stGeomObj, xElementIndex, xDataElementIndex );
				}
				break;
 
 
#ifdef USE_ALTIMAPS
            case GEO_C_xElementAltimap:
#endif /*USE_ALTIMAPS*/
            default :
            break;
          }
 
          COL_g_d_lTaggedFacesTable[(p_stGeomObj->p_stOctree)->d_xElementBasesTable[xElementIndex] + xDataElementIndex]
            = COL_g_lFacesTagCounter;
        }
      }
    }
  }
 
  return (*p_xNbElements) > 0;
}
 
#endif
 
 
/*
--------------------------------------------------------------------------------
-- Description : Search and replace point in elements
--------------------------------------------------------------------------------
-- Creation date : 18 nov 1996               Author : FPI
--------------------------------------------------------------------------------
*/
#ifdef ACTIVE_EDITOR
/* active editor only*/
void INT_fn_vSearchAndReplacePointInElement ( GEO_tdstGeometricObject *p_stGeomObj,
                                              ACP_tdxIndex xNbElements,
                                              struct GLI_tdstDataOfElement_ *d_stDataOfElement )
{
  ACP_tdxIndex                      xDataList;
  ACP_tdxIndex                      xElementIndex;
  ACP_tdxIndex                      xDataElementIndex;
  GEO_tdstElementIndexedTriangles   *p_stElementIndexedTriangles;
/*  GEO_tdstElementFaceMapDescriptors *p_stElementFaceMapDescriptors;*/
  GEO_tdstElementSpheres            *p_stElementSpheres;
  GEO_tdstElementAlignedBoxes       *p_stElementAlignedBoxes;
  GEO_tdstElementPoints             *p_stElementPoints;
  GEO_tdstElementLines              *p_stElementLines;
 
  ACP_tdxIndex                      xPointIndex;
  GEO_tdstIndexedSphere             *p_stIndexedSphere;
  GEO_tdstIndexedAlignedBox         *p_stIndexedAlignedBox;
 
  for ( xDataList = 0 ; xDataList < xNbElements ; xDataList++ )
  {
    for ( xElementIndex = 0 ; xElementIndex < p_stGeomObj->xNbElements ; xElementIndex++ )
    {
      switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
      {
        case GEO_C_xElementIndexedTriangles :
          p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
          /* pour les triangles */
          for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementIndexedTriangles->xNbFaces ; xDataElementIndex++ )
          {
            /* points du triangle */
            for ( xPointIndex = 0 ; xPointIndex < 3 ; xPointIndex++ )
            {
              if ( (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[xPointIndex] == d_stDataOfElement[xDataList].xIndexOfPoint )
              {
                d_stDataOfElement[xDataList].xElements = xElementIndex;
              }
            }
          }
        break;
 
 
        case GEO_C_xElementSpheres :
          p_stElementSpheres = (GEO_tdstElementSpheres *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
          /* pour les spheres */
          for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementSpheres->xNbSpheres ; xDataElementIndex++ )
          {
            /* sphere */
            p_stIndexedSphere = p_stElementSpheres->d_stListOfSpheres + xDataElementIndex;
 
            /* centre de la sphere */
            if ( p_stIndexedSphere->xCenterPoint == d_stDataOfElement[xDataList].xIndexOfPoint )
            {
              d_stDataOfElement[xDataList].xElements = xElementIndex;
            }
          }
        break;
 
        case GEO_C_xElementAlignedBoxes :
          p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
          /* pour les boites */
          for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementAlignedBoxes->xNbAlignedBoxes ; xDataElementIndex++ )
          {
            /* boite */
            p_stIndexedAlignedBox = p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex;
 
            /* points de la boite */
            if ( p_stIndexedAlignedBox->xMinPoint == d_stDataOfElement[xDataList].xIndexOfPoint )
            {
              d_stDataOfElement[xDataList].xElements = xElementIndex;
            }
            if ( p_stIndexedAlignedBox->xMaxPoint == d_stDataOfElement[xDataList].xIndexOfPoint )
            {
              d_stDataOfElement[xDataList].xElements = xElementIndex;
            }
          }
        break;
 
        case GEO_C_xElementPoints :
          p_stElementPoints = (GEO_tdstElementPoints *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
          /* pour les points */
          for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementPoints->xNbPoints ; xDataElementIndex++ )
          {
            if ( *(p_stElementPoints->d_xListOfPointIndex + xDataElementIndex) == d_stDataOfElement[xDataList].xIndexOfPoint )
            {
              d_stDataOfElement[xDataList].xElements = xElementIndex;
              d_stDataOfElement[xDataList].xIndexOfPoint = xDataElementIndex;
            }
          }
        break;
 
        case GEO_C_xElementLines :
          p_stElementLines = (GEO_tdstElementLines *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
          /* pour les lignes */
          for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementLines->xNbLines ; xDataElementIndex++ )
          {
            /* points de la ligne */
            if ( (p_stElementLines->d_stListOfLineIndex + xDataElementIndex)->a2_xIndex[0] == d_stDataOfElement[xDataList].xIndexOfPoint )
            {
              d_stDataOfElement[xDataList].xElements = xElementIndex;
            }
            if ( (p_stElementLines->d_stListOfLineIndex + xDataElementIndex)->a2_xIndex[1] == d_stDataOfElement[xDataList].xIndexOfPoint )
            {
              d_stDataOfElement[xDataList].xElements = xElementIndex;
            }
          }
        break;
 
        default :
        break;
      }
    }
  }
}
 
#endif
/*
--------------------------------------------------------------------------------
-- Description : Semiaxe with point of geometric object intersection test
--------------------------------------------------------------------------------
-- Creation date : 18 nov 1996               Author : FPI
--------------------------------------------------------------------------------
*/
#if defined(ACTIVE_EDITOR)			
/* active editor only*/
ACP_tdxBool INT_fn_bIntersectSemiAxeWithPointOfGeometricObject ( MTH3D_tdstVector *p_stVertexA,
                                                                 MTH3D_tdstVector *p_stVectAB,
                                                                 GEO_tdstGeometricObject *p_stGeomObj,
                                                                 ACP_tdxIndex xNbMaxElements,
                                                                 ACP_tdxIndex *p_xNbElements,
                                                                 struct GLI_tdstDataOfElement_ *d_stDataOfElement )
{
  ACP_tdxIndex xPointIndex;
  MTH3D_tdstVector *p_stPoint;
  MTH_tdxReal xDistance;
  MTH_tdxReal xT;
  MTH3D_tdstVector stHit;
  ACP_tdxIndex xPointListIndex;
 
  *p_xNbElements = 0;
  /* pour les points */
  for ( xPointIndex = 0 ; xPointIndex < p_stGeomObj->xNbPoints ; xPointIndex++ )
  {
    p_stPoint = p_stGeomObj->d_stListOfPoints + xPointIndex;
 
    /* distance demi-axe point */
    xDistance = INT_fn_xDistancePointToLine ( p_stPoint, p_stVertexA, p_stVectAB, &xT, &stHit );
 
    if ( MTH_M_bGreaterZero ( xT ) )
    {
      /* index sur le dernier element */
      xPointListIndex = *p_xNbElements;
      while ( ( 0 < xPointListIndex ) && ( xDistance < d_stDataOfElement[xPointListIndex-1].xDistance ) )
      {
        if ( xPointListIndex < xNbMaxElements )
        {
          /* xPointListIndex <- xPointListIndex - 1 */
          memcpy ( &(d_stDataOfElement[xPointListIndex]), &(d_stDataOfElement[xPointListIndex-1]), sizeof ( struct GLI_tdstDataOfElement_ ) );
        }
        xPointListIndex--;
      }
 
      if ( xPointListIndex < xNbMaxElements )
      {
        /* xPointListIndex */
        MTH3D_M_vCopyVector ( &(d_stDataOfElement[xPointListIndex].stHit), &stHit );
        d_stDataOfElement[xPointListIndex].xDistance = xDistance;
        d_stDataOfElement[xPointListIndex].xElements = xPointIndex;
        d_stDataOfElement[xPointListIndex].xIndexOfPoint = xPointIndex;
        if ( (*p_xNbElements) < xNbMaxElements )
          (*p_xNbElements)++;
      }
    }
  }
 
  INT_fn_vSearchAndReplacePointInElement ( p_stGeomObj, *p_xNbElements, d_stDataOfElement );
 
  return (*p_xNbElements) > 0;
}
#endif ACTIVE_EDITOR
/*
--------------------------------------------------------------------------------
-- Description : Edge part of a triangle
--------------------------------------------------------------------------------
-- Creation date : 18 nov 1996               Author : FPI
--------------------------------------------------------------------------------
*/
#ifdef ACTIVE_EDITOR
/* active editor only*/
ACP_tdxBool INT_fn_bEdgePartOfTriangle ( ACP_tdxIndex xEdge1,
                                         ACP_tdxIndex xEdge2,
                                         ACP_tdxIndex xPoint1,
                                         ACP_tdxIndex xPoint2,
                                         ACP_tdxIndex xPoint3 )
{
  return ( ( xEdge1 == xPoint1 ) || ( xEdge1 == xPoint2 ) || ( xEdge1 == xPoint3 ) ) &&
         ( ( xEdge2 == xPoint1 ) || ( xEdge2 == xPoint2 ) || ( xEdge2 == xPoint3 ) );
}
 
#endif
 
/*
--------------------------------------------------------------------------------
-- Description : Search and replace edge in elements
--------------------------------------------------------------------------------
-- Creation date : 18 nov 1996               Author : FPI
--------------------------------------------------------------------------------
*/
#ifdef ACTIVE_EDITOR
/* active editor only*/
void INT_fn_vSearchAndReplaceEdgeInElement ( GEO_tdstGeometricObject *p_stGeomObj,
                                             ACP_tdxIndex xNbElements,
                                             struct GLI_tdstDataOfElement_ *d_stDataOfElement )
{
  ACP_tdxIndex xDataList;
  ACP_tdxIndex xElementIndex;
  ACP_tdxIndex xDataElementIndex;
  GEO_tdstElementIndexedTriangles *p_stElementIndexedTriangles;
/*  GEO_tdstElementFaceMapDescriptors *p_stElementFaceMapDescriptors;*/
/*  GEO_tdstElementLines *p_stElementLines;*/
 
  for ( xDataList = 0 ; xDataList < xNbElements ; xDataList++ )
  {
    d_stDataOfElement[xDataList].xElements = GEO_C_xElementNULL;
 
    for ( xElementIndex = 0 ; xElementIndex < p_stGeomObj->xNbElements ; xElementIndex++ )
    {
      switch ( *(p_stGeomObj->d_xListOfElementsTypes + xElementIndex) )
      {
        case GEO_C_xElementIndexedTriangles :
          p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(*(p_stGeomObj->d_stListOfElements + xElementIndex));
 
          /* pour les triangles */
          for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementIndexedTriangles->xNbFaces ; xDataElementIndex++ )
          {
            if
              (
                INT_fn_bEdgePartOfTriangle ( p_stGeomObj->d_stListOfEdges[d_stDataOfElement[xDataList].xIndexOfEdge].a2_xIndex[0],
                                             p_stGeomObj->d_stListOfEdges[d_stDataOfElement[xDataList].xIndexOfEdge].a2_xIndex[1],
                                             (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0],
                                             (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1],
                                             (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2] )
              )
            {
              d_stDataOfElement[xDataList].xElements = xElementIndex;
            }
          }
        break;
 
        default :
        break;
      }
    }
  }
}
 
#endif
/*
--------------------------------------------------------------------------------
-- Description : Semiaxe with edge of geometric object intersection test
--------------------------------------------------------------------------------
-- Creation date : 18 nov 1996               Author : FPI
--------------------------------------------------------------------------------
*/
#if defined(ACTIVE_EDITOR)			
/* active editor only*/
ACP_tdxBool INT_fn_bIntersectSemiAxeWithEdgeOfGeometricObject ( MTH3D_tdstVector *p_stVertexA,
                                                                MTH3D_tdstVector *p_stVectAB,
                                                                GEO_tdstGeometricObject *p_stGeomObj,
                                                                ACP_tdxIndex xNbMaxElements,
                                                                ACP_tdxIndex *p_xNbElements,
                                                                struct GLI_tdstDataOfElement_ *d_stDataOfElement )
{
  ACP_tdxIndex xEdgeIndex;
  MTH3D_tdstVector *p_stVertex1;
  MTH3D_tdstVector *p_stVertex2;
  MTH3D_tdstVector stVect12;
  MTH3D_tdstVector stSegmentPoint;
  MTH_tdxReal xDistance;
  MTH_tdxReal xT;
  MTH3D_tdstVector stHit;
  ACP_tdxIndex xEdgeListIndex;
 
  *p_xNbElements = 0;
  /* pour les points */
  for ( xEdgeIndex = 0 ; xEdgeIndex < p_stGeomObj->xNbEdges ; xEdgeIndex++ )
  {
    p_stVertex1 = p_stGeomObj->d_stListOfPoints + p_stGeomObj->d_stListOfEdges[xEdgeIndex].a2_xIndex[0];
    p_stVertex2 = p_stGeomObj->d_stListOfPoints + p_stGeomObj->d_stListOfEdges[xEdgeIndex].a2_xIndex[1];
 
    MTH3D_M_vSubVector ( &stVect12, p_stVertex2, p_stVertex1 );
 
    /* distance demi-axe segment */
    xDistance = INT_fn_xDistanceSegmentToLine ( p_stVertex1, &stVect12, p_stVertexA, p_stVectAB, &xT, &stSegmentPoint, &stHit );
 
    if ( MTH_M_bGreaterZero ( xT ) )
    {
      /* index sur le dernier element */
      xEdgeListIndex = *p_xNbElements;
      while ( ( 0 <= xEdgeListIndex ) && ( xDistance < d_stDataOfElement[xEdgeListIndex].xDistance ) )
      {
        if ( xEdgeListIndex < xNbMaxElements )
        {
          /* xEdgeListIndex <- xEdgeListIndex - 1 */
          memcpy ( &(d_stDataOfElement[xEdgeListIndex]), &(d_stDataOfElement[xEdgeListIndex-1]), sizeof ( struct GLI_tdstDataOfElement_ ) );
        }
        xEdgeListIndex--;
      }
 
      if ( xEdgeListIndex < xNbMaxElements )
      {
        /* xEdgeListIndex */
        MTH3D_M_vCopyVector ( &(d_stDataOfElement[xEdgeListIndex].stHit), &stHit );
        d_stDataOfElement[xEdgeListIndex].xDistance = xDistance;
        d_stDataOfElement[xEdgeListIndex].xElements = xEdgeIndex;
        d_stDataOfElement[xEdgeListIndex].xIndexOfPoint = xEdgeIndex;
        if ( (*p_xNbElements) < xNbMaxElements )
          (*p_xNbElements)++;
      }
    }
  }
 
  INT_fn_vSearchAndReplaceEdgeInElement ( p_stGeomObj, *p_xNbElements, d_stDataOfElement );
 
  return (*p_xNbElements) > 0;
}
 
#endif /*ACTIVE_EDITOR*/
/*
--------------------------------------------------------------------------------
-- Description : Get inclusion of a point in a geometric object
--------------------------------------------------------------------------------
-- Creation date : 17 jan 1997               Author : FPI-OLJ
--------------------------------------------------------------------------------
*/
/* usefull*/
ACP_tdxBool INT_fn_bGetInclusionPointInGeometricObject ( MTH3D_tdstVector *p_stPoint,
                                                         GEO_tdstGeometricObject *p_stGeomObj )
{
  ACP_tdxIndex                    xElementIndex;
  ACP_tdxIndex                    xDataElementIndex;
 
  GEO_tdstElementIndexedTriangles *p_stElementIndexedTriangles;
  GEO_tdstElementSpheres          *p_stElementSpheres;
  GEO_tdstElementAlignedBoxes     *p_stElementAlignedBoxes;
  GEO_tdstElementCones            *p_stElementCones;
 
  GEO_tdstIndexedSphere           *p_stIndexedSphere;
  GEO_tdstIndexedAlignedBox       *p_stIndexedAlignedBox;
  GEO_tdstIndexedCone             *p_stIndexedCone;
 
  MTH3D_tdstVector                *p_stVertex1;
  MTH3D_tdstVector                *p_stVertex2;
  MTH3D_tdstVector                *p_stVertex3;
  MTH3D_tdstVector                *p_stNormal;
  MTH_tdxReal                     xDPlan;
 
  MTH_tdxReal                     xT;
  MTH3D_tdstVector                stHit;
 
  MTH3D_tdstVector stZNormal = { MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE };
 
  ACP_tdxIndex xNbIntersect;
 
  for ( xElementIndex = 0 ; xElementIndex < p_stGeomObj->xNbElements ; xElementIndex++ )
  {
    switch ( p_stGeomObj->d_xListOfElementsTypes[xElementIndex] )
    {
      case GEO_C_xElementIndexedTriangles :
        p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
        xNbIntersect = 0;
 
        /* pour les triangles */
        for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementIndexedTriangles->xNbFaces ; xDataElementIndex++ )
        {
          /* points du triangle statique */
          p_stVertex1 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[0];
          p_stVertex2 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[1];
          p_stVertex3 = p_stGeomObj->d_stListOfPoints + (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[2];
 
          /* calcul de la normale */
          p_stNormal = p_stElementIndexedTriangles->d_stListOfFacesNormals + xDataElementIndex;
 
          /* calcul de d de l equation du plan */
          xDPlan = MTH_M_xNeg ( MTH3D_M_xDotProductVector ( p_stNormal, p_stVertex1 ) );
 
          if
            (
              INT_fn_bIntersectSegmentWithTriangle ( p_stPoint, &stZNormal,
                                                     p_stVertex1, p_stVertex2, p_stVertex3,
                                                     p_stNormal, xDPlan, &xT, &stHit )
            )
          {
            xNbIntersect ++;
          }
        }
 
        if ( (xNbIntersect % 2) != 0 )
        {
          return TRUE;
        }
      break;
 
#ifdef USE_ALTIMAPS
        case GEO_C_xElementAltimap :
          {
            GEO_tdstElementAltimap          *p_stElementAltimap;
            ACP_tdxIndex      xAx, xAy, xLoopX, xLoopY, xLoopV, xIndex;
            MTH3D_tdstVector  stV1, stV2, stV3, stNorm;
            ACP_tdxBool       xBoolA;
 
            p_stElementAltimap = (GEO_tdstElementAltimap *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
            xBoolA = COL_ucSelectAltimapSquare( p_stElementAltimap, p_stPoint, &xAx, &xAy );
            COL_M_vClipSquareSelection( p_stElementAltimap, xAx, xAy, xBoolA );
 
            COL_M_vScanSelectedSquares( xLoopX, xLoopY, xLoopV, p_stElementAltimap->xWidth, xAx, xAy, xAx, xAy )
            {
              unsigned char   ucType;
 
              ucType = p_stElementAltimap->d_stSquare[ xLoopV ].ucType;
              while( ucType )
              {
                ucType = COL_ucBuildAltimapSquareTriangle( p_stElementAltimap, xLoopX, xLoopY, ucType,
                                                           &stV1, &stV2, &stV3, &stNorm, &xIndex );
 
                /*--- Equation of face's plan*/
                xDPlan = MTH_M_xNeg( MTH3D_M_xDotProductVector( &stNorm, &stV1 ) );
        
                if( INT_fn_bIntersectSegmentWithTriangle( p_stPoint, &stZNormal, 
                                                          &stV1, &stV2, &stV3,
                                                          &stNorm, xDPlan, &xT, &stHit ) )
                  xNbIntersect ++;
              }
            }
            if ( (xNbIntersect % 2) != 0 )
              return TRUE;
          }
          break;              
#endif /*USE_ALTIMAPS*/
 
      case GEO_C_xElementSpheres :
        p_stElementSpheres = (GEO_tdstElementSpheres *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
        /* pour les spheres */
        for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementSpheres->xNbSpheres ; xDataElementIndex++ )
        {
          /* sphere */
          p_stIndexedSphere = p_stElementSpheres->d_stListOfSpheres + xDataElementIndex;
 
          if ( INT_fn_bGetInclusionPointInSphere ( p_stPoint, p_stGeomObj->d_stListOfPoints + p_stIndexedSphere->xCenterPoint,
                                                   p_stIndexedSphere->xRadius ) )
          {
            return TRUE;
          }
        }
      break;
 
      case GEO_C_xElementAlignedBoxes :
        p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
        /* pour les boites */
        for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementAlignedBoxes->xNbAlignedBoxes ; xDataElementIndex++ )
        {
          /* boite */
          p_stIndexedAlignedBox = p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex;
 
          if ( INT_fn_bGetInclusionPointInBox ( p_stPoint, p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMinPoint,
                                                p_stGeomObj->d_stListOfPoints + p_stIndexedAlignedBox->xMaxPoint ) )
          {
            return TRUE;
          }
        }
      break;
 
      case GEO_C_xElementCones :
        p_stElementCones = (GEO_tdstElementCones *)(p_stGeomObj->d_stListOfElements[xElementIndex]);
 
        /* pour les cones */
        for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementCones->xNbCones ; xDataElementIndex++ )
        {
          /* cone */
          p_stIndexedCone = p_stElementCones->d_stListOfCones + xDataElementIndex;
 
          if ( INT_fn_bGetInclusionPointInCone ( p_stPoint, p_stGeomObj->d_stListOfPoints + p_stIndexedCone->xTopPoint,
                                                 p_stGeomObj->d_stListOfPoints + p_stIndexedCone->xBasePoint,
                                                 p_stIndexedCone->xBaseRadius ) )
          {
            return TRUE;
          }
        }
      break;
 
      default :
      break;
    }
  }
 
  return FALSE;
}
 
/*
--------------------------------------------------------------------------------
-- Description : Two geometric objects intersection detection (sphere and box )
--------------------------------------------------------------------------------
-- Creation date : 29 apr 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
/* useful*/
ACP_tdxBool INT_fn_bDetectIntersectGeomObjWithGeomObj ( GEO_tdstGeometricObject *p_stGeomObj1,
                                                        POS_tdstCompletePosition *_p_stMatrix1,
                                                        GEO_tdstGeometricObject *p_stGeomObj2,
                                                        POS_tdstCompletePosition *_p_stMatrix2,
                                                        GMT_tdxHandleToGameMaterial *_p_hMat1,
                                                        GMT_tdxHandleToGameMaterial *_p_hMat2 )
{
  POS_tdstCompletePosition stInvMatrix2;
  POS_tdstCompletePosition st12TransformMatrix;
  POS_tdstCompletePosition st21TransformMatrix;
  MTH_tdxReal xScale1;
  MTH_tdxReal xScale2;
 
  ACP_tdxIndex xElementIndex1;
  ACP_tdxIndex xDataElementIndex1;
  GEO_tdstElementSpheres *p_stElementSpheres1;
  GEO_tdstElementAlignedBoxes *p_stElementAlignedBoxes1;
  GEO_tdstIndexedSphere *p_stIndexedSphere1;
  GEO_tdstIndexedAlignedBox *p_stIndexedAlignedBox1;
  ACP_tdxIndex xElementIndex2;
  ACP_tdxIndex xDataElementIndex2;
  GEO_tdstElementSpheres *p_stElementSpheres2;
  GEO_tdstElementAlignedBoxes *p_stElementAlignedBoxes2;
  GEO_tdstIndexedSphere *p_stIndexedSphere2;
  GEO_tdstIndexedAlignedBox *p_stIndexedAlignedBox2;
 
  MTH3D_tdstVector stCenter1in2;
  MTH3D_tdstVector stCenter2in1;
  MTH3D_tdstVector stCenter1 , stCenter2;
 
  COL_tda8st8VerticesBox a8_st8VBox2;
  COL_tda8st8VerticesBox a8_st8VBox2in1;
  COL_tda8st8VerticesBox a8_st8VBox1;
  COL_tda8st8VerticesBox a8_st8VBox1in2;
  MTH3D_tdstVector stEdgeVector;
  ACP_tdxIndex xVertexIndex;
  ACP_tdxIndex xEdgeIndex;
 
  xScale1 = POS_fn_xGetMaxScale ( _p_stMatrix1 );
  xScale2 = POS_fn_xGetMaxScale ( _p_stMatrix2 );
 
  for ( xElementIndex1 = 0 ; xElementIndex1 < p_stGeomObj1->xNbElements ; xElementIndex1++ )
  {
    switch ( p_stGeomObj1->d_xListOfElementsTypes[xElementIndex1] )
    {
      case GEO_C_xElementSpheres :
        p_stElementSpheres1 = (GEO_tdstElementSpheres *)(p_stGeomObj1->d_stListOfElements[xElementIndex1]);
 
        /* pour les spheres */
        for ( xDataElementIndex1 = 0 ; xDataElementIndex1 < p_stElementSpheres1->xNbSpheres ; xDataElementIndex1++ )
        {
          /* sphere */
          p_stIndexedSphere1 = p_stElementSpheres1->d_stListOfSpheres + xDataElementIndex1;
 
          /* Get the coordinate of the center in the global axis*/
          POS_fn_vMulMatrixVertex (& stCenter1 , _p_stMatrix1 , p_stGeomObj1 -> d_stListOfPoints + p_stIndexedSphere1 -> xCenterPoint);
 
          for ( xElementIndex2 = 0 ; xElementIndex2 < p_stGeomObj2->xNbElements ; xElementIndex2++ )
          {
            switch ( p_stGeomObj2->d_xListOfElementsTypes[xElementIndex2] )
            {
              case GEO_C_xElementSpheres :
                p_stElementSpheres2 = (GEO_tdstElementSpheres *)(p_stGeomObj2->d_stListOfElements[xElementIndex2]);
 
                /* pour les spheres */
                for ( xDataElementIndex2 = 0 ; xDataElementIndex2 < p_stElementSpheres2->xNbSpheres ; xDataElementIndex2++ )
                {
                  /* sphere */
                  p_stIndexedSphere2 = p_stElementSpheres2->d_stListOfSpheres + xDataElementIndex2;
 
                  /* Get the coordinate of the center in the global axis*/
                  POS_fn_vMulMatrixVertex (& stCenter2 , _p_stMatrix2 , p_stGeomObj2 -> d_stListOfPoints + p_stIndexedSphere2 -> xCenterPoint);
 
                  if (INT_fn_bIntersectSphereWithSphere (& stCenter1 , MTH_M_xMul (p_stIndexedSphere1 -> xRadius , xScale1) ,
                                                         & stCenter2 , MTH_M_xMul (p_stIndexedSphere2 -> xRadius , xScale2)))
                  {
                    *_p_hMat1 = p_stIndexedSphere1->hMaterial;
                    *_p_hMat2 = p_stIndexedSphere2->hMaterial;
                    return TRUE;
                  }
                }
              break;
 
              case GEO_C_xElementAlignedBoxes :
               {
                  /* inversion de la matrice statique */
                POS_fn_vInvertMatrix( &stInvMatrix2, _p_stMatrix2 );
                  /* calcul de la matrice de passage entre 1 et 2 */
                POS_fn_vMulMatrixMatrix( &st12TransformMatrix, &stInvMatrix2, _p_stMatrix1 );
                  /* inversion de la matrice statique */
/*                POS_fn_vInvertMatrix( &st21TransformMatrix, &st12TransformMatrix );    Not used anymore*/
 
                  /* transformation du centre1 ds repere 2*/
                POS_fn_vMulMatrixVertex ( &stCenter1in2, &st12TransformMatrix, p_stGeomObj1->d_stListOfPoints + p_stIndexedSphere1->xCenterPoint );
 
                p_stElementAlignedBoxes2 = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj2->d_stListOfElements[xElementIndex2]);
 
                /* pour les boites*/
                for ( xDataElementIndex2 = 0 ; xDataElementIndex2 < p_stElementAlignedBoxes2->xNbAlignedBoxes ; xDataElementIndex2++ )
                {
                  /* boite*/
                  p_stIndexedAlignedBox2 = p_stElementAlignedBoxes2->d_stListOfAlignedBoxes + xDataElementIndex2;
 
                  if (INT_fn_bIntersectSphereWithBox ( &stCenter1in2, MTH_M_xDiv ( MTH_M_xMul ( p_stIndexedSphere1->xRadius, xScale1 ), xScale2 ),
                                                       p_stGeomObj2->d_stListOfPoints + p_stIndexedAlignedBox2->xMinPoint,
                                                       p_stGeomObj2->d_stListOfPoints + p_stIndexedAlignedBox2->xMaxPoint ) )
                  {
                    *_p_hMat1 = p_stIndexedSphere1->hMaterial;
                    *_p_hMat2 = p_stIndexedAlignedBox2->hMaterial;
                    return TRUE;
                  }
                }
               }
              break;
 
              default :
              break;
            }
          }
        }
      break;
 
      case GEO_C_xElementAlignedBoxes :
       {
          /* inversion de la matrice statique */
        POS_fn_vInvertMatrix( &stInvMatrix2, _p_stMatrix2 );
          /* calcul de la matrice de passage entre 1 et 2 */
        POS_fn_vMulMatrixMatrix( &st12TransformMatrix, &stInvMatrix2, _p_stMatrix1 );
          /* inversion de la matrice statique */
        POS_fn_vInvertMatrix( &st21TransformMatrix, &st12TransformMatrix );
 
        p_stElementAlignedBoxes1 = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj1->d_stListOfElements[xElementIndex1]);
 
        /* pour les boites*/
        for ( xDataElementIndex1 = 0 ; xDataElementIndex1 < p_stElementAlignedBoxes1->xNbAlignedBoxes ; xDataElementIndex1++ )
        {
          /* boite*/
          p_stIndexedAlignedBox1 = p_stElementAlignedBoxes1->d_stListOfAlignedBoxes + xDataElementIndex1;
 
          for ( xElementIndex2 = 0 ; xElementIndex2 < p_stGeomObj2->xNbElements ; xElementIndex2++ )
          {
            switch ( p_stGeomObj2->d_xListOfElementsTypes[xElementIndex2] )
            {
              case GEO_C_xElementSpheres :
                p_stElementSpheres2 = (GEO_tdstElementSpheres *)(p_stGeomObj2->d_stListOfElements[xElementIndex2]);
 
                /* pour les spheres*/
                for ( xDataElementIndex2 = 0 ; xDataElementIndex2 < p_stElementSpheres2->xNbSpheres ; xDataElementIndex2++ )
                {
                  /* sphere*/
                  p_stIndexedSphere2 = p_stElementSpheres2->d_stListOfSpheres + xDataElementIndex2;
 
                  /* transformation du centre2 ds repere 1*/
                  POS_fn_vMulMatrixVertex ( &stCenter2in1, &st21TransformMatrix, p_stGeomObj2->d_stListOfPoints + p_stIndexedSphere2->xCenterPoint );
 
                  if (INT_fn_bIntersectSphereWithBox ( &stCenter2in1, MTH_M_xDiv ( MTH_M_xMul ( p_stIndexedSphere2->xRadius, xScale2 ), xScale1 ),
                                                       p_stGeomObj1->d_stListOfPoints + p_stIndexedAlignedBox1->xMinPoint,
                                                       p_stGeomObj1->d_stListOfPoints + p_stIndexedAlignedBox1->xMaxPoint ) )
                  {
                    *_p_hMat1 = p_stIndexedAlignedBox1->hMaterial;
                    *_p_hMat2 = p_stIndexedSphere2->hMaterial;
                    return TRUE;
                  }
                }
              break;
 
              case GEO_C_xElementAlignedBoxes :
                p_stElementAlignedBoxes2 = (GEO_tdstElementAlignedBoxes *)(p_stGeomObj2->d_stListOfElements[xElementIndex2]);
 
                /* pour les boites*/
                for ( xDataElementIndex2 = 0 ; xDataElementIndex2 < p_stElementAlignedBoxes2->xNbAlignedBoxes ; xDataElementIndex2++ )
                {
                  /* boite*/
                  p_stIndexedAlignedBox2 = p_stElementAlignedBoxes2->d_stListOfAlignedBoxes + xDataElementIndex2;
 
                  /* transformation de la boite2 ds repere 1*/
                  /* decompression de la boite dynamique*/
                  COL_fn_vMinMaxBox2VerticesBox ( a8_st8VBox2, p_stGeomObj2->d_stListOfPoints + p_stIndexedAlignedBox2->xMinPoint,
                                                               p_stGeomObj2->d_stListOfPoints + p_stIndexedAlignedBox2->xMaxPoint );
 
                  /* trajectoires des points de la boite dynamique dans statique*/
                  for ( xVertexIndex = 0 ; xVertexIndex < COL_C_xNbVerticesPerBox ; xVertexIndex++ )
                  {
                    /* calcul des trajectoires des points de dynamique dans statique*/
                    POS_fn_vMulMatrixVertex ( &(a8_st8VBox2in1[xVertexIndex]), &st21TransformMatrix, &(a8_st8VBox2[xVertexIndex]) );
                  }
 
                  for ( xEdgeIndex = 0 ; xEdgeIndex < COL_C_xNbEdgesPerBox ; xEdgeIndex++ )
                  {
                    MTH3D_M_vSubVector ( &stEdgeVector, &(a8_st8VBox2in1[COL_g_a12_stBoxEdges[xEdgeIndex].a2_xIndex[1]]),
                                                        &(a8_st8VBox2in1[COL_g_a12_stBoxEdges[xEdgeIndex].a2_xIndex[0]]) );
 
                    if ( INT_fn_bDetectIntersectSegmentWithBox ( &(a8_st8VBox2in1[COL_g_a12_stBoxEdges[xEdgeIndex].a2_xIndex[0]]),
                                                                    &stEdgeVector,
                                                                    p_stGeomObj1->d_stListOfPoints + p_stIndexedAlignedBox1->xMinPoint,
                                                                    p_stGeomObj1->d_stListOfPoints + p_stIndexedAlignedBox1->xMaxPoint, NULL ) )
                    {
                      *_p_hMat1 = p_stIndexedAlignedBox1->hMaterial;
                      *_p_hMat2 = p_stIndexedAlignedBox2->hMaterial;
                      return TRUE;
                    }
                  }
 
                  /* transformation de la boite1 ds repere 2*/
                  /* decompression de la boite dynamique*/
                  COL_fn_vMinMaxBox2VerticesBox ( a8_st8VBox1, p_stGeomObj1->d_stListOfPoints + p_stIndexedAlignedBox1->xMinPoint,
                                                               p_stGeomObj1->d_stListOfPoints + p_stIndexedAlignedBox1->xMaxPoint );
 
                  /* trajectoires des points de la boite dynamique dans statique*/
                  for ( xVertexIndex = 0 ; xVertexIndex < COL_C_xNbVerticesPerBox ; xVertexIndex++ )
                  {
                    /* calcul des trajectoires des points de dynamique dans statique*/
                    POS_fn_vMulMatrixVertex ( &(a8_st8VBox1in2[xVertexIndex]), &st12TransformMatrix, &(a8_st8VBox1[xVertexIndex]) );
                  }
 
                  for ( xEdgeIndex = 0 ; xEdgeIndex < COL_C_xNbEdgesPerBox ; xEdgeIndex++ )
                  {
                    MTH3D_M_vSubVector ( &stEdgeVector, &(a8_st8VBox1in2[COL_g_a12_stBoxEdges[xEdgeIndex].a2_xIndex[1]]),
                                                        &(a8_st8VBox1in2[COL_g_a12_stBoxEdges[xEdgeIndex].a2_xIndex[0]]) );
 
                    if ( INT_fn_bDetectIntersectSegmentWithBox ( &(a8_st8VBox1in2[COL_g_a12_stBoxEdges[xEdgeIndex].a2_xIndex[0]]),
                                                                    &stEdgeVector,
                                                                    p_stGeomObj2->d_stListOfPoints + p_stIndexedAlignedBox2->xMinPoint,
                                                                    p_stGeomObj2->d_stListOfPoints + p_stIndexedAlignedBox2->xMaxPoint, NULL ) )
                    {
                      *_p_hMat1 = p_stIndexedAlignedBox1->hMaterial;
                      *_p_hMat2 = p_stIndexedAlignedBox2->hMaterial;
                      return TRUE;
                    }
                  }
                }
              break;
 
              default :
              break;
            }
          }
        }
       }
      break;
 
      default :
      break;
    }
  }
 
  return FALSE;
}
