/**********************************************************************************************/
/* Name: GeoObj.c*/
/* Code: Philippe Vimont*/
/* Modif : 30 May 1997 - Guenaele - remove old D3D*/
/**********************************************************************************************/
#include <assert.h>
#include "cpa_std.h"
 
#include "acp_base.h"
 
#include "mth.h"
#include "GEO.h"
#include "gmt.h"
#include "mec.h"
#include "Col\OctreeGO.h"

// FBF N64-format pour coords, et logfile dans x:\exe\geodump.log{
#ifdef U64CONVERTETLOG
extern BOOL g_bLoadMap;
extern FILE *dump;

#endif //U64CONVERTLOG
// } fin N64-format
/**********************************************************************************************/
/* Name: GEO_xComputeNormalWeightedBySurf*/
/* Goal: the Normals of triangle is weighted by surf (See computer graphics, gouraud shading)*/
/* Code: Philippe Vimont*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_xComputeNormalWeightedBySurf ( MTH3D_tdstVector *p_stPResult, MTH3D_tdstVector *p_stPA, MTH3D_tdstVector *p_stPB, MTH3D_tdstVector *p_stPC )
{
	MTH3D_tdstVector stEdgeAB, stEdgeAC;
 
	MTH3D_M_vSubVector ( &stEdgeAB, p_stPB, p_stPA );
	MTH3D_M_vSubVector ( &stEdgeAC, p_stPC, p_stPA );
 
	MTH3D_M_vCrossProductVectorWithoutBuffer( p_stPResult, &stEdgeAB, &stEdgeAC );
}
 
/**********************************************************************************************/
/* Name: GEO_xCreateObjectPointNormals*/
/* Goal: Create the point Normals of object*/
/* Code: Frederic Philippe*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/

#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC 07/06/99 */
void GEO_xCreateObjectPointNormals ( GEO_tdstGeometricObject *p_stObj )
{
	MTH3D_tdstVector *p_stVertex, *p_stLastVertex;
 
	if ( p_stObj->xNbPoints == 0 )
	    return;
 
	if ( p_stObj->d_stListOfPointsNormals != NULL )
		return;
 
	MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypePointsNormals , 0 );
	GEO_M_CPAMalloc ( p_stObj->d_stListOfPointsNormals, MTH3D_tdstVector *, sizeof(MTH3D_tdstVector)*p_stObj->xNbPoints, E_uwGEONotEnoughtMemory );
 
	p_stLastVertex = p_stObj->d_stListOfPointsNormals + p_stObj->xNbPoints;
	for ( p_stVertex = p_stObj->d_stListOfPointsNormals; p_stVertex < p_stLastVertex; p_stVertex ++ )
	{
		MTH3D_M_vNullVector ( p_stVertex );
	}
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC 07/06/99 */

 
/**********************************************************************************************/
/* Name: GEO_xComputeAltimapObjectNormals*/
/* Goal: Create and compute the Normals of object*/
/* Code: Marc Fascia*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
#ifdef USE_ALTIMAPS
void GEO_xComputeAltimapObjectNormals( GEO_tdstGeometricObject *p_stObj )
{
	GEO_tdstElementAltimap  *p_stAltimap;
	ACP_tdxIndex            xI, xJ, xK, xL, xA, xB, xC, xSquareBLVertex;
	MTH3D_tdstVector        *d_stPoints, stOriginNoZ;
	GEO_tdstAltimapSquare   *stSquare;
	unsigned char           ucType;
 
	p_stAltimap = (GEO_tdstElementAltimap *) p_stObj->d_stListOfElements[0];
 
	/*--- d_stpoints : Array of Vertices of the Altimap*/
	GEO_M_CPAMalloc( d_stPoints, MTH3D_tdstVector *, ( p_stAltimap->xWidth+1 ) * ( p_stAltimap->xDepth+1 ) * sizeof( MTH3D_tdstVector ), E_uwGEONotEnoughtMemory );
 
	/*--- xI : Width*/
	/*--- xJ : Height*/
	/*--- xK : xJ * (Width+1) + xI*/
	MTH3D_M_vSetVectorElements( &stOriginNoZ, p_stAltimap->stOrigin.xX, p_stAltimap->stOrigin.xY, MTH_C_ZERO );
	for(xJ = 0, xK = 0; xJ < p_stAltimap->xDepth+1; xJ++)
		for(xI = 0 ; xI< p_stAltimap->xWidth+1; xI++, xK ++)
		{
			/*--- For each Vertex, sets the coordinates in its super object axis system*/
			MTH3D_M_vNullVector(p_stAltimap->d_stPointNormals + xK);
			(d_stPoints + xK) -> xX = MTH_M_xRealToLong(xI) * p_stAltimap->xDeltaX;
			(d_stPoints + xK) -> xY = MTH_M_xRealToLong(xJ) * p_stAltimap->xDeltaY;
			(d_stPoints + xK) -> xZ = p_stAltimap->d_xHeight[xK];
			MTH3D_M_vAddVector(d_stPoints + xK, d_stPoints + xK, &stOriginNoZ);
		}
 
	for(xJ = 0, xK = 0 ; xJ < p_stAltimap->xDepth ; xJ++)
		for(xI = 0 ; xI < p_stAltimap->xWidth; xI++, xK++)
		{
			stSquare        = (p_stAltimap->d_stSquare) + xK;
			xL              = stSquare->xFaceIndex;
			ucType          = stSquare->ucType;
			xSquareBLVertex = xJ * (p_stAltimap->xWidth + 1) + xI;
 
			while( ucType )
			{
				if( ucType & GEO_C_xAltiSquareTopRight )
				{
					xA = xSquareBLVertex + 1;
					xB = xSquareBLVertex + 1 + p_stAltimap->xWidth + 1;
					xC = xSquareBLVertex + p_stAltimap->xWidth + 1;
					ucType &= ~GEO_C_xAltiSquareTopRight;
					ucType <<= 4;
				}
				else if( ucType & GEO_C_xAltiSquareBottomLeft )
				{
					xA = xSquareBLVertex;
					xB = xSquareBLVertex + 1;
					xC = xSquareBLVertex + p_stAltimap->xWidth + 1;
					ucType = 0;
				}
				else if( (ucType >> 4) & GEO_C_xAltiSquareBottomLeft )
				{
					xA = xSquareBLVertex;
					xB = xSquareBLVertex + 1;
					xC = xSquareBLVertex + p_stAltimap->xWidth + 1;
					ucType = 0;
					xL++;
				}
				else if( ucType & GEO_C_xAltiSquareTopLeft )
				{
					xA = xSquareBLVertex;
					xB = xSquareBLVertex + 1 + p_stAltimap->xWidth + 1;
					xC = xSquareBLVertex + p_stAltimap->xWidth + 1;
					ucType &= ~GEO_C_xAltiSquareTopLeft;
					ucType <<= 4;
				}
				else if( ucType & GEO_C_xAltiSquareBottomRight )
				{
					xA = xSquareBLVertex;
					xB = xSquareBLVertex + 1;
					xC = xSquareBLVertex + 1 + p_stAltimap->xWidth + 1;
					ucType = 0;
				}
				else if( (ucType >> 4) & GEO_C_xAltiSquareBottomRight )
				{
					xA = xSquareBLVertex;
					xB = xSquareBLVertex + 1;
					xC = xSquareBLVertex + 1 + p_stAltimap->xWidth + 1;
					ucType = 0;
					xL++;
				}
				else
					break;
 
				GEO_xComputeNormalWeightedBySurf( &(p_stAltimap->d_stFaces[xL].stNormal), d_stPoints + xA, d_stPoints + xB, d_stPoints + xC );
				MTH3D_M_vAddVector( p_stAltimap->d_stPointNormals + xA, p_stAltimap->d_stPointNormals + xA, &(p_stAltimap->d_stFaces[xL].stNormal) );
				MTH3D_M_vAddVector( p_stAltimap->d_stPointNormals + xB, p_stAltimap->d_stPointNormals + xB, &(p_stAltimap->d_stFaces[xL].stNormal) );
				MTH3D_M_vAddVector( p_stAltimap->d_stPointNormals + xC, p_stAltimap->d_stPointNormals + xC, &(p_stAltimap->d_stFaces[xL].stNormal) );
 
				MTH3D_M_vNormalizeVector ( &(p_stAltimap->d_stFaces[xL].stNormal), &(p_stAltimap->d_stFaces[xL].stNormal) );
			}
		}
 
		for(xJ = 0, xK = 0; xJ < p_stAltimap->xDepth+1; xJ++)
			for(xI = 0; xI< p_stAltimap->xWidth+1; xI++, xK++)
			{
				if( MTH_M_bEqualZero( MTH3D_M_xNormVector( p_stAltimap->d_stPointNormals + xK ) ) )
					MTH3D_M_vSetVectorElements( p_stAltimap->d_stPointNormals + xK, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE )
				else
					MTH3D_M_vNormalizeVector( p_stAltimap->d_stPointNormals + xK, p_stAltimap->d_stPointNormals + xK )
			}
		GEO_M_CPAFree(d_stPoints);
	return;
}
#endif /*USE_ALTIMAPS*/
 
/**********************************************************************************************/
/* Name: GEO_xComputeObjectNormals*/
/* Goal: Create and compute the Normals of object*/
/* Code: Philippe Vimont*/
/* Modification: Frederic Philippe*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_xComputeObjectNormals( GEO_tdstGeometricObject *p_stObj )
{
	MTH3D_tdstVector					*p_stVertex, *p_stLastVertex, stNormalResult;
	GEO_tdstTripledIndex				*p_stITStart, *p_stITLast;
	GEO_tdstElementIndexedTriangles		*p_stLocalElement;
//XB99/04/27
#ifndef U64
	GEO_tdstFaceMapTriangle				*p_stITStartFMD, *p_stITLastFMD;
	GEO_tdstElementFaceMapDescriptors	*p_stLocalElementFMD;
#endif U64
//End XB99/04/27
	ACP_tdxIndex						xIndex, xTriangleIndex;
 
 
	#ifdef USE_ALTIMAPS
	if ( p_stObj->d_xListOfElementsTypes[0] == GEO_C_xElementAltimap )
		GEO_xComputeAltimapObjectNormals( p_stObj );
	#endif
 
	if ( p_stObj->xNbPoints == 0 )
		return;
 
	if ( p_stObj->d_stListOfPointsNormals == NULL )
	{
		MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypePointsNormals , 0 );
		GEO_M_CPAMalloc ( p_stObj->d_stListOfPointsNormals, MTH3D_tdstVector *, sizeof(MTH3D_tdstVector)*p_stObj->xNbPoints, E_uwGEONotEnoughtMemory );
	}
 
	p_stVertex = p_stObj->d_stListOfPointsNormals;
	p_stLastVertex = p_stVertex + p_stObj->xNbPoints;
	for ( ; p_stVertex < p_stLastVertex ; p_stVertex ++ )
	{
		MTH3D_M_vNullVector ( p_stVertex );
	}
 
	for ( xIndex = 0 ; xIndex < p_stObj->xNbElements ; xIndex ++ )
	{
// FBF N64-format pour coords, et logfile dans x:\exe\geodump.log{
#ifdef U64CONVERTETLOG
		if (g_bLoadMap)
		{
			fprintf (dump,"------- compute face normal for element %03d\n",xIndex,p_stVertex->xX,p_stVertex->xY,p_stVertex->xZ);
			fflush(dump);
		}

#endif //U64CONVERTLOG
// } fin N64-format


		if ( p_stObj->d_xListOfElementsTypes[xIndex] == GEO_C_xElementIndexedTriangles )
		{
			p_stLocalElement = ((GEO_tdstElementIndexedTriangles *)p_stObj->d_stListOfElements[xIndex]);
 
			p_stITStart = p_stLocalElement->d_stListOfFacesTripled;
			p_stITLast = p_stITStart + p_stLocalElement->xNbFaces;
			for ( xTriangleIndex = 0 ; p_stITStart < p_stITLast ; p_stITStart ++ , xTriangleIndex ++ )
			{
				GEO_xComputeNormalWeightedBySurf ( &stNormalResult, p_stObj->d_stListOfPoints + p_stITStart->a3_xIndex[0], p_stObj->d_stListOfPoints + p_stITStart->a3_xIndex[1], p_stObj->d_stListOfPoints + p_stITStart->a3_xIndex[2] );
				p_stLocalElement->d_stListOfFacesNormals[xTriangleIndex] = stNormalResult;
 
				if ( !MTH3D_M_bIsNullVector( &stNormalResult ) )
				{
					MTH3D_M_vAddVector ( p_stObj->d_stListOfPointsNormals + p_stITStart->a3_xIndex[0], p_stObj->d_stListOfPointsNormals + p_stITStart->a3_xIndex[0], &stNormalResult );
					MTH3D_M_vAddVector ( p_stObj->d_stListOfPointsNormals + p_stITStart->a3_xIndex[1], p_stObj->d_stListOfPointsNormals + p_stITStart->a3_xIndex[1], &stNormalResult );
					MTH3D_M_vAddVector ( p_stObj->d_stListOfPointsNormals + p_stITStart->a3_xIndex[2], p_stObj->d_stListOfPointsNormals + p_stITStart->a3_xIndex[2], &stNormalResult );
					MTH3D_M_vNormalizeVector ( &p_stLocalElement->d_stListOfFacesNormals[xTriangleIndex], &p_stLocalElement->d_stListOfFacesNormals[xTriangleIndex] );
				}
// FBF N64-format pour coords, et logfile dans x:\exe\geodump.log{
#ifdef U64CONVERTETLOG
				if (g_bLoadMap)
				{
					fprintf (dump,"face normal %03d : x=%f,y=%f,z=%f\n",xTriangleIndex,p_stLocalElement->d_stListOfFacesNormals[xTriangleIndex].xX,p_stLocalElement->d_stListOfFacesNormals[xTriangleIndex].xY,p_stLocalElement->d_stListOfFacesNormals[xTriangleIndex].xZ);
					fflush(dump);
				}

#endif //U64CONVERTLOG
// } fin N64-format
 
			}
		}
//XB99/04/27
#ifndef U64
		else if ( p_stObj->d_xListOfElementsTypes[xIndex] == GEO_C_xElementFaceMapDescriptors )
		{
			p_stLocalElementFMD = ((GEO_tdstElementFaceMapDescriptors *)p_stObj->d_stListOfElements[xIndex]);
 
			p_stITStartFMD = p_stLocalElementFMD->d_stListOfFacesQuadrupled;
			p_stITLastFMD = p_stITStartFMD + p_stLocalElementFMD->xNbFaces;
			for ( xTriangleIndex=0 ; p_stITStartFMD < p_stITLastFMD ; p_stITStartFMD ++ , xTriangleIndex ++ )
			{
				GEO_xComputeNormalWeightedBySurf
					(
						&stNormalResult,
						p_stObj->d_stListOfPoints + p_stITStartFMD->stFaceTripled.a3_xIndex[0],
						p_stObj->d_stListOfPoints + p_stITStartFMD->stFaceTripled.a3_xIndex[1],
                        p_stObj->d_stListOfPoints + p_stITStartFMD->stFaceTripled.a3_xIndex[2]
					);
				p_stLocalElementFMD->d_stListOfFacesNormals[xTriangleIndex] = stNormalResult;
 
				if ( !MTH3D_M_bIsNullVector( &stNormalResult ) )
				{
					MTH3D_M_vAddVector ( p_stObj->d_stListOfPointsNormals + p_stITStartFMD->stFaceTripled.a3_xIndex[0], p_stObj->d_stListOfPointsNormals + p_stITStartFMD->stFaceTripled.a3_xIndex[0], &stNormalResult );
					MTH3D_M_vAddVector ( p_stObj->d_stListOfPointsNormals + p_stITStartFMD->stFaceTripled.a3_xIndex[1], p_stObj->d_stListOfPointsNormals + p_stITStartFMD->stFaceTripled.a3_xIndex[1], &stNormalResult );
					MTH3D_M_vAddVector ( p_stObj->d_stListOfPointsNormals + p_stITStartFMD->stFaceTripled.a3_xIndex[2], p_stObj->d_stListOfPointsNormals + p_stITStartFMD->stFaceTripled.a3_xIndex[2], &stNormalResult );
					MTH3D_M_vNormalizeVector ( &p_stLocalElementFMD->d_stListOfFacesNormals[xTriangleIndex], &p_stLocalElementFMD->d_stListOfFacesNormals[xTriangleIndex] );
				}
			}
		}
#endif U64
//End XB99/04/27
	}
 
	p_stVertex = p_stObj->d_stListOfPointsNormals;
	p_stLastVertex = p_stVertex + p_stObj->xNbPoints;
	for ( ; p_stVertex < p_stLastVertex ; p_stVertex ++ )
	{
		if ( MTH3D_M_bIsNullVector( p_stVertex ) )
		{
			MTH3D_M_vSetVectorElements ( p_stVertex, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE );
		}
		else
		{
			MTH3D_M_vNormalizeVector ( p_stVertex, p_stVertex );
		}
	}
}
 
/**********************************************************************************************/
/* Name: GEO_xComputeObjectNormals2*/
/* Goal: Compute the Normals of object*/
/* Code: Frederic Philippe*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_xComputeObjectNormals2 ( GEO_tdstGeometricObject *p_stObj )
{
	if ( p_stObj->d_stListOfPointsNormals == NULL )
		return;
 
	GEO_xComputeObjectNormals( p_stObj );
}
 
/**********************************************************************************************/
/* Name: GEO_xComputeIndexUsedByElements*/
/* Goal:*/
/* Code:*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_xComputeIndexUsedByElements ( GEO_tdstGeometricObject *p_stObj )
{
    GEO_tdstElementIndexedTriangles *p_stLocalElement;
    ACP_tdxIndex xIndex, xTriangleIndex;
    unsigned long xObjIndex,xIndexCounter;
    unsigned char aDEF_ulCountBuffer [ (( C_lMaxVertexPerObject + 7 ) >> 3 ) ];
 
	if ( p_stObj->xNbElements == 1 )
		return;
 
    for ( xIndex = 0 ; xIndex < p_stObj->xNbElements ; xIndex ++ )
    {
        if ( p_stObj->d_xListOfElementsTypes[xIndex] == GEO_C_xElementIndexedTriangles )
        {
            p_stLocalElement = ((GEO_tdstElementIndexedTriangles *)p_stObj->d_stListOfElements[xIndex]);
 
            /* Clear CountBuffer */
            memset( (unsigned char *)aDEF_ulCountBuffer , 0 , ((p_stObj->xNbPoints+7) >> 3) );
 
            /* Tagging idex in Countbuffer */
            for (xTriangleIndex = 0; xTriangleIndex < p_stLocalElement->xNbFaces; xTriangleIndex++ )
            {
                xObjIndex = (p_stLocalElement->d_stListOfFacesTripled + xTriangleIndex)->a3_xIndex[0];
                *(aDEF_ulCountBuffer + (xObjIndex >> 3)) |= (1 << (xObjIndex & 0x00000007));
                xObjIndex = (p_stLocalElement->d_stListOfFacesTripled + xTriangleIndex)->a3_xIndex[1];
                *(aDEF_ulCountBuffer + (xObjIndex >> 3)) |= (1 << (xObjIndex & 0x00000007));
                xObjIndex = (p_stLocalElement->d_stListOfFacesTripled + xTriangleIndex)->a3_xIndex[2];
                *(aDEF_ulCountBuffer + (xObjIndex >> 3)) |= (1 << (xObjIndex & 0x00000007));
            }
 
            /* Counting Number of Indexes used */
            p_stLocalElement->xNumberOfIndexsUsed = 0;
            for (xObjIndex = 0; xObjIndex < (((unsigned long)p_stObj->xNbPoints)+7) >> 3; xObjIndex ++ )
            {
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x01) p_stLocalElement->xNumberOfIndexsUsed++;
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x02) p_stLocalElement->xNumberOfIndexsUsed++;
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x04) p_stLocalElement->xNumberOfIndexsUsed++;
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x08) p_stLocalElement->xNumberOfIndexsUsed++;
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x10) p_stLocalElement->xNumberOfIndexsUsed++;
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x20) p_stLocalElement->xNumberOfIndexsUsed++;
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x40) p_stLocalElement->xNumberOfIndexsUsed++;
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x80) p_stLocalElement->xNumberOfIndexsUsed++;
            }
 
			if (p_stLocalElement->xNumberOfIndexsUsed == p_stObj->xNbPoints)
				continue;
 
 
            /* allocate d_stListOfIndexUsedByThisElement */
			MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeIndexUsedByElement , 0 );
            GEO_M_CPAMalloc ( p_stLocalElement->d_stListOfIndexUsedByThisElement,
                ACP_tdxIndex *,
                sizeof(ACP_tdxIndex)*p_stLocalElement->xNumberOfIndexsUsed,
                E_uwGEONotEnoughtMemory );
 
            /* Building  d_stListOfIndexUsedByThisElement */
            xIndexCounter = 0;
            for (xObjIndex = 0; xObjIndex < (((unsigned long)p_stObj->xNbPoints)+7) >> 3; xObjIndex ++ )
            {
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x01) p_stLocalElement->d_stListOfIndexUsedByThisElement[xIndexCounter++] = (ACP_tdxIndex)(xObjIndex*8 + 0);
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x02) p_stLocalElement->d_stListOfIndexUsedByThisElement[xIndexCounter++] = (ACP_tdxIndex)(xObjIndex*8 + 1);
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x04) p_stLocalElement->d_stListOfIndexUsedByThisElement[xIndexCounter++] = (ACP_tdxIndex)(xObjIndex*8 + 2);
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x08) p_stLocalElement->d_stListOfIndexUsedByThisElement[xIndexCounter++] = (ACP_tdxIndex)(xObjIndex*8 + 3);
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x10) p_stLocalElement->d_stListOfIndexUsedByThisElement[xIndexCounter++] = (ACP_tdxIndex)(xObjIndex*8 + 4);
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x20) p_stLocalElement->d_stListOfIndexUsedByThisElement[xIndexCounter++] = (ACP_tdxIndex)(xObjIndex*8 + 5);
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x40) p_stLocalElement->d_stListOfIndexUsedByThisElement[xIndexCounter++] = (ACP_tdxIndex)(xObjIndex*8 + 6);
                if (*(aDEF_ulCountBuffer + xObjIndex) & 0x80) p_stLocalElement->d_stListOfIndexUsedByThisElement[xIndexCounter++] = (ACP_tdxIndex)(xObjIndex*8 + 7);
            }
        }
    }
}
 
/**********************************************************************************************/
/* Name: GEO_xComputeObjectSphereBox*/
/* Goal: Compute the spherebox of object*/
/* Code: by ??*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
#ifndef _FIRE_DEADCODE_U64_
void
GEO_xComputeObjectSphereBox ( GEO_tdstGeometricObject *p_stObj )
{
}
#endif /* _FIRE_DEADCODE_U64_ */
 
 
/* Cette information est demandé par le super objet*/
#ifndef _FIRE_DEADCODE_U64_
void GLI_vGetMinMaxObject
	(
		GEO_tdstGeometricObject *p_stObj,
        MTH_tdxReal *xMinX,MTH_tdxReal *xMaxX,
        MTH_tdxReal *xMinY,MTH_tdxReal *xMaxY,
        MTH_tdxReal *xMinZ,MTH_tdxReal *xMaxZ
	)
{
}
#endif /* _FIRE_DEADCODE_U64_ */
 
 
 
/* ********************************************************************************************/
/* NEW FUNCTIONS STARTS HERE*/
/* ********************************************************************************************/
 
/**********************************************************************************************/
/* NAME : GEO_hAllocGeometricObject*/
/* Goal: alloc a geometric objetc on the GEO static bloc*/
/* Code: Marc trabucato 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
ACP_tdxHandleOfObject GEO_hAllocGeometricObject( ACP_tdxIndex xNbPoints , ACP_tdxIndex xNbElements )
{
	GEO_tdstGeometricObject *p_stObjectToCreate;
 
	/* alloc Main struct*/
	MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeMainObject , 0 );
	GEO_M_CPAMalloc (p_stObjectToCreate , GEO_tdstGeometricObject * , sizeof ( GEO_tdstGeometricObject), E_uwGEONotEnoughtMemory );
 
	p_stObjectToCreate->xNbElements = xNbElements;
	p_stObjectToCreate->xNbPoints = xNbPoints;
 
	/* alloc Array of Element Type*/
	MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeListOfElementType , 0 );
	GEO_M_CPAMalloc (p_stObjectToCreate->d_xListOfElementsTypes , ACP_tdxIndex * , sizeof ( ACP_tdxIndex ) * xNbElements , E_uwGEONotEnoughtMemory );
	/* alloc Array of Element*/
	MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeListOfElement , 0 );
	GEO_M_CPAMalloc (p_stObjectToCreate->d_stListOfElements , void ** , sizeof ( void * ) * xNbElements , E_uwGEONotEnoughtMemory );
 
	/* alloc Array of Points*/
	MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeListOfPoint , 0 );
	GEO_M_CPAMalloc (p_stObjectToCreate->d_stListOfPoints , MTH3D_tdstVector *  , sizeof ( MTH3D_tdstVector ) * xNbPoints , E_uwGEONotEnoughtMemory );
 
    /* alloc Array of Normals*/
	MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypePointsNormals , 0 );
	GEO_M_CPAMalloc (p_stObjectToCreate->d_stListOfPointsNormals ,MTH3D_tdstVector * , sizeof ( MTH3D_tdstVector ) * xNbPoints , E_uwGEONotEnoughtMemory );
 
	return (ACP_tdxHandleOfObject)p_stObjectToCreate;
}
 
/**********************************************************************************************/
/* NAME : GEO_hAllocTMPGeometricObject*/
/* Goal: alloc a geometric objetc on the TMP static bloc*/
/* Code: Marc trabucato 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
ACP_tdxHandleOfObject GEO_hAllocTMPGeometricObject( ACP_tdxIndex xNbPoints , ACP_tdxIndex xNbElements )
{
	GEO_tdstGeometricObject *p_stObjectToCreate;
 
	/* alloc Main struct*/
	GEO_M_TMPMalloc (p_stObjectToCreate , GEO_tdstGeometricObject * , sizeof ( GEO_tdstGeometricObject) );
 
	p_stObjectToCreate->xNbElements = xNbElements;
	p_stObjectToCreate->xNbPoints = xNbPoints;
 
	/* alloc Array of Element Type*/
	GEO_M_TMPMalloc (p_stObjectToCreate->d_xListOfElementsTypes , ACP_tdxIndex * , sizeof ( ACP_tdxIndex ) * xNbElements );
	/* alloc Array of Element*/
	GEO_M_TMPMalloc (p_stObjectToCreate->d_stListOfElements , void ** , sizeof ( void * ) * xNbElements );
 
	/* alloc Array of Points*/
	GEO_M_TMPMalloc (p_stObjectToCreate->d_stListOfPoints , MTH3D_tdstVector *  , sizeof ( MTH3D_tdstVector ) * xNbPoints );
    /* alloc Array of Normals*/
	GEO_M_TMPMalloc (p_stObjectToCreate->d_stListOfPointsNormals , MTH3D_tdstVector * , sizeof ( MTH3D_tdstVector ) * xNbPoints );
 
	return (ACP_tdxHandleOfObject)p_stObjectToCreate;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/**********************************************************************************************/
/* NAME : GEO_vCreateGeometricObject*/
/* Goal: init a geometric object*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_vInitGeometricObject(  GEO_tdstGeometricObject *p_stObjectToCreate , ACP_tdxIndex xNbPoints , ACP_tdxIndex xNbElements )
{
	ACP_tdxIndex				xInitCount;
 
	for (xInitCount=0;xInitCount<xNbElements;xInitCount++)
		p_stObjectToCreate->d_xListOfElementsTypes[xInitCount]=GEO_C_xElementNULL;
 
	p_stObjectToCreate->p_stOctree = NULL;
 
	p_stObjectToCreate -> xNbParallelBoxes       = 0;
	p_stObjectToCreate -> d_stListOfParallelBoxes = NULL;
 
	p_stObjectToCreate->ulType = GEO_C_NotALookAt ;
 
#if defined(U64)
	p_stObjectToCreate->fScale = 1.0;
	p_stObjectToCreate->fRadius = 16384.0;
	p_stObjectToCreate->uwRliFlag = 0;
#endif /* U64 */
}
 
/**********************************************************************************************/
/* NAME : GEO_vCreateGeometricObject*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_vCreateGeometricObject( ACP_tdxHandleOfObject *p_hObject , ACP_tdxIndex xNbPoints , ACP_tdxIndex xNbElements )
{
	*p_hObject = GEO_hAllocGeometricObject( xNbPoints, xNbElements );
	GEO_vInitGeometricObject( (GEO_tdstGeometricObject *) *p_hObject, xNbPoints, xNbElements );
}
 
/**********************************************************************************************/
/* NAME : GEO_vCreateTMPGeometricObject*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void GEO_vCreateTMPGeometricObject ( ACP_tdxHandleOfObject *p_hObject , ACP_tdxIndex xNbPoints , ACP_tdxIndex xNbElements )
{
	*p_hObject = GEO_hAllocTMPGeometricObject( xNbPoints, xNbElements );
	GEO_vInitGeometricObject( (GEO_tdstGeometricObject *) *p_hObject, xNbPoints, xNbElements );
}
 
/**********************************************************************************************/
/* NAME : GEO_vDeleteGeometricObject*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_vDeleteGeometricObject ( ACP_tdxHandleOfObject *p_hObj )
{
	long					lElementCounter;
	GEO_tdstGeometricObject *p_hObject ;
 
	p_hObject= *(GEO_tdstGeometricObject **)p_hObj ;
 
	for (lElementCounter = 0 ; lElementCounter < p_hObject -> xNbElements; lElementCounter ++ )
		switch (p_hObject -> d_xListOfElementsTypes [lElementCounter ] )
        {
			case GEO_C_xElementNULL:
				break;
			case GEO_C_xElementPoints:
				GEO_M_CPAFree( ((GEO_tdstElementPoints * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_xListOfPointIndex);
				GEO_M_CPAFree( p_hObject -> d_stListOfElements[lElementCounter ] );
				break;
			case GEO_C_xElementLines:
				GEO_M_CPAFree( ((GEO_tdstElementLines * )(p_hObject -> d_stListOfElements[lElementCounter ]))  -> d_stListOfLineIndex);
				GEO_M_CPAFree( ((GEO_tdstElementLines * )(p_hObject -> d_stListOfElements[lElementCounter ]))  -> d_hListOfLinesMaterial);
				GEO_M_CPAFree( ((GEO_tdstElementLines * )(p_hObject -> d_stListOfElements[lElementCounter ]))  -> d_stListOfLinesReceivedLightIntensity);
				GEO_M_CPAFree( ((GEO_tdstElementLines * )(p_hObject -> d_stListOfElements[lElementCounter ])) );
		        break;
			case GEO_C_xElementFaceMapDescriptors :
				GEO_M_CPAFree( ((GEO_tdstElementFaceMapDescriptors * )(p_hObject -> d_stListOfElements[lElementCounter ]))  -> d_stListOfFacesNormals);
				GEO_M_CPAFree( ((GEO_tdstElementFaceMapDescriptors * )(p_hObject -> d_stListOfElements[lElementCounter ]))  -> d_stListOfFacesQuadrupled);
				GEO_M_CPAFree( ((GEO_tdstElementFaceMapDescriptors * )(p_hObject -> d_stListOfElements[lElementCounter ]))  );
                break;
			case GEO_C_xElementSprites:
				GEO_M_CPAFree( ((GEO_tdstElementSprite * )(p_hObject -> d_stListOfElements[lElementCounter ]))  -> d_stListOfSprites);
				GEO_M_CPAFree( ((GEO_tdstElementSprite * )(p_hObject -> d_stListOfElements[lElementCounter ]))  );
                break;
			case GEO_C_xElementSpheres:
				GEO_M_CPAFree( ((GEO_tdstElementSpheres * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfSpheres );
				GEO_M_CPAFree( ((GEO_tdstElementSpheres * )(p_hObject -> d_stListOfElements[lElementCounter ])) );
                break;
			case GEO_C_xElementAlignedBoxes:
				GEO_M_CPAFree( ((GEO_tdstElementAlignedBoxes * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfAlignedBoxes);
				GEO_M_CPAFree( ((GEO_tdstElementAlignedBoxes * )(p_hObject -> d_stListOfElements[lElementCounter ])) );
                break;
			case GEO_C_xElementCones:
				GEO_M_CPAFree( ((GEO_tdstElementCones * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfCones);
				GEO_M_CPAFree( ((GEO_tdstElementCones * )(p_hObject -> d_stListOfElements[lElementCounter ])) );
                break;
			case GEO_C_xElementTMeshes:
				GEO_M_CPAFree( ((GEO_tdstElementTMeshes * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfMeshAtoms);
				GEO_M_CPAFree( ((GEO_tdstElementTMeshes * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfFacesNormals);
				GEO_M_CPAFree( ((GEO_tdstElementTMeshes * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfElementUV);
				GEO_M_CPAFree( ((GEO_tdstElementTMeshes * )(p_hObject -> d_stListOfElements[lElementCounter ])) );
                break;
			case GEO_C_xElementIndexedTriangles :
				GEO_M_CPAFree( ((GEO_tdstElementIndexedTriangles * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfFacesTripled);
				GEO_M_CPAFree( ((GEO_tdstElementIndexedTriangles * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfFacesTripledIndexUV);
				GEO_M_CPAFree( ((GEO_tdstElementIndexedTriangles * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfFacesNormals);
				GEO_M_CPAFree( ((GEO_tdstElementIndexedTriangles * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfElementUV);
				GEO_M_CPAFree( ((GEO_tdstElementIndexedTriangles * )(p_hObject -> d_stListOfElements[lElementCounter ])) );
                break;
		} /* Element switch*/
		GEO_M_CPAFree( p_hObject -> d_stListOfPoints);
		GEO_M_CPAFree( p_hObject -> d_stListOfPointsNormals);
 
		if ( p_hObject -> d_hListOfPointsMaterial )
			GEO_M_CPAFree( p_hObject -> d_hListOfPointsMaterial);
 
		if ( p_hObject -> d_stListOfEdges)
			GEO_M_CPAFree( p_hObject -> d_stListOfEdges);
		if ( p_hObject -> d_hListOfEdgesMaterial)
			GEO_M_CPAFree( p_hObject -> d_hListOfEdgesMaterial);
		if ( p_hObject -> d_xListOfElementsTypes)
			GEO_M_CPAFree( p_hObject -> d_xListOfElementsTypes);
		if( p_hObject -> d_stListOfElements)
			GEO_M_CPAFree( p_hObject -> d_stListOfElements);
		if ( p_hObject -> d_stListOfParallelBoxes)
			GEO_M_CPAFree( p_hObject -> d_stListOfParallelBoxes  );
		GEO_M_CPAFree( p_hObject );
		*p_hObj = NULL;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/**********************************************************************************************/
/* NAME : GEO_vRecursiveReinitGamesMaterials*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
/* fbolefeysot - 01/10/98*/
/* remove init values in GMT{*/
/*
void GEO_vRecursiveReinitGamesMaterials (    ACP_tdxHandleOfObject *p_hObj )
{
	long						lElementCounter;
    long						lPartOfElementCounter;
	GEO_tdstGeometricObject		*p_hObject ;
 
	p_hObject= *(GEO_tdstGeometricObject **)p_hObj ;
 
	for (lElementCounter = 0 ; lElementCounter < p_hObject -> xNbElements; lElementCounter ++ )
		switch (p_hObject -> d_xListOfElementsTypes [lElementCounter ] )
        {
			case GEO_C_xElementNULL:
				break;
			case GEO_C_xElementPoints:
				GMT_fn_vReInitializeGameMaterial(((GEO_tdstElementPoints * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> hMaterial);
				break;
			case GEO_C_xElementLines:
				for ( lPartOfElementCounter = 0 ;lPartOfElementCounter < ((GEO_tdstElementLines * )(p_hObject -> d_stListOfElements[lElementCounter ]))->xNbLines; lPartOfElementCounter++)
					GMT_fn_vReInitializeGameMaterial(((GEO_tdstElementLines * )(p_hObject -> d_stListOfElements[lElementCounter ]))  -> d_hListOfLinesMaterial[lPartOfElementCounter]);
		        break;
			case GEO_C_xElementFaceMapDescriptors :
				for (lPartOfElementCounter = 0 ;lPartOfElementCounter < ((GEO_tdstElementFaceMapDescriptors * )(p_hObject -> d_stListOfElements[lElementCounter ]))  -> xNbFaces;lPartOfElementCounter++)
					GMT_fn_vReInitializeGameMaterial(((GEO_tdstElementFaceMapDescriptors * )(p_hObject -> d_stListOfElements[lElementCounter ]))  -> d_stListOfFacesQuadrupled[lPartOfElementCounter].hFaceMapDescriptor->hMaterial);
                break;
			case GEO_C_xElementSprites:
				for (lPartOfElementCounter = 0 ;lPartOfElementCounter < ((GEO_tdstElementSprite * )(p_hObject -> d_stListOfElements[lElementCounter ]))  -> xNbSprites;lPartOfElementCounter++)
					GMT_fn_vReInitializeGameMaterial(*((GEO_tdstElementSprite * )(p_hObject -> d_stListOfElements[lElementCounter ]))  -> d_stListOfSprites[lPartOfElementCounter].hSprite->d_hMaterial);
				break;
			case GEO_C_xElementSpheres:
				for (lPartOfElementCounter = 0 ;lPartOfElementCounter < ((GEO_tdstElementSpheres * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> xNbSpheres;lPartOfElementCounter++)
					GMT_fn_vReInitializeGameMaterial(((GEO_tdstElementSpheres * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfSpheres[lPartOfElementCounter].hMaterial);
                break;
			case GEO_C_xElementAlignedBoxes:
				for (lPartOfElementCounter = 0 ;lPartOfElementCounter < ((GEO_tdstElementAlignedBoxes * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> xNbAlignedBoxes;lPartOfElementCounter++)
					GMT_fn_vReInitializeGameMaterial(((GEO_tdstElementAlignedBoxes * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfAlignedBoxes[lPartOfElementCounter].hMaterial);
                break;
			case GEO_C_xElementCones:
				for (lPartOfElementCounter = 0 ;lPartOfElementCounter < ((GEO_tdstElementCones * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> xNbCones;lPartOfElementCounter++)
					GMT_fn_vReInitializeGameMaterial(((GEO_tdstElementCones * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> d_stListOfCones[lPartOfElementCounter].hMaterial);
				break;
			case GEO_C_xElementTMeshes:
				GMT_fn_vReInitializeGameMaterial(((GEO_tdstElementTMeshes * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> hMaterial);
                break;
			case GEO_C_xElementIndexedTriangles :
				GMT_fn_vReInitializeGameMaterial(((GEO_tdstElementIndexedTriangles * )(p_hObject -> d_stListOfElements[lElementCounter ])) -> hMaterial);
                break;
		} // Element switch
}
*/
/*END fbolefeysot}*/
 
ACP_tdxIndex GEO_xGetGeometricObjectNumberOfPoints ( ACP_tdxHandleOfObject hObject )
{
	return hObject->xNbPoints;
}
 
#ifndef _FIRE_DEADCODE_U64_
ACP_tdxIndex GEO_xGetGeometricObjectNumberOfEdges ( ACP_tdxHandleOfObject hObject )
{
	return hObject->xNbEdges;
}
#endif /* _FIRE_DEADCODE_U64_ */
 
 
 
/**********************************************************************************************/
/* NAME : GEO_vSetPointOfObject*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_vSetPointOfObject ( ACP_tdxHandleOfObject hObject , MTH3D_tdstVector *p_stPoint , ACP_tdxIndex xIndexOfPoint)
{
	*(hObject -> d_stListOfPoints + xIndexOfPoint) = *p_stPoint ;
}
 
/**********************************************************************************************/
/* NAME : GEO_vSetListOfPointsOfObject*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
#ifndef _FIRE_DEADCODE_U64_
void GEO_vSetListOfPointsOfObject (  ACP_tdxHandleOfObject hObject , MTH3D_tdstVector *p_stPoint , ACP_tdxIndex xNbPoints , ACP_tdxIndex xIndexOfFirstPoint)
{
	memcpy( hObject-> d_stListOfPoints + xIndexOfFirstPoint, p_stPoint, sizeof(MTH3D_tdstVector) * xNbPoints);
}
#endif /* _FIRE_DEADCODE_U64_ */
 
/**********************************************************************************************/
/* NAME : GEO_vGetPointOfObject*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_vGetPointOfObject( ACP_tdxHandleOfObject hObject , MTH3D_tdstVector *p_stPoint , ACP_tdxIndex xIndexOfPoint)
{
	*p_stPoint = *(hObject -> d_stListOfPoints + xIndexOfPoint) ;
}
 
/**********************************************************************************************/
/* NAME : GEO_vGetListOfPointsOfObject*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
#ifndef _FIRE_DEADCODE_U64_
void GEO_vGetListOfPointsOfObject (  ACP_tdxHandleOfObject hObject , MTH3D_tdstVector *p_stPoint , ACP_tdxIndex xNbPoints , ACP_tdxIndex xIndexOfFirstPoint)
{
	memcpy( p_stPoint, hObject->d_stListOfPoints + xIndexOfFirstPoint, sizeof(MTH3D_tdstVector) * xNbPoints);
}
#endif /* _FIRE_DEADCODE_U64_ */
 
/**********************************************************************************************/
/* NAME : GEO_vSetPointReceivedLightIntensityOfObject*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void GEO_vSetPointReceivedLightIntensityOfObject ( ACP_tdxHandleOfObject hObject , GEO_tdstColor *p_stColor , ACP_tdxIndex xIndexOfPoint)
{
}
 
/**********************************************************************************************/
/* NAME : GEO_vGetPointReceivedLightIntensityOfObject*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_vGetPointReceivedLightIntensityOfObject ( ACP_tdxHandleOfObject hObject , GEO_tdstColor *p_xColor , ACP_tdxIndex xIndexOfPoint)
{
}
 
/**********************************************************************************************/
/* NAME : GEO_vSetNormalOfPointOfObject*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_vSetNormalOfPointOfObject ( ACP_tdxHandleOfObject hObject , MTH3D_tdstVector *p_stNormal , ACP_tdxIndex xIndexOfPoint)
{
	*(hObject ->d_stListOfPointsNormals + xIndexOfPoint) = *p_stNormal ;
}
 
/**********************************************************************************************/
/* NAME : GEO_vGetNormalOfPointOfObject*/
/* Goal:*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_vGetNormalOfPointOfObject ( ACP_tdxHandleOfObject hObject , MTH3D_tdstVector *p_stNormal , ACP_tdxIndex xIndexOfPoint)
{
	*p_stNormal = *(hObject->d_stListOfPointsNormals + xIndexOfPoint) ;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
 
/**********************************************************************************************/
/* Compute Edges*/
/* Goal: Compute the liste of edge of geometric object*/
/* Code by philippe Vimont*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
long GEO_fbIsNotLinked(ACP_tdxIndex *aDEF_xLinkTable, ACP_tdxIndex *p_xLinkToCreate, ACP_tdxIndex xLinkToTest)
{
	ACP_tdxIndex xLinkCounterLocal;
	for (xLinkCounterLocal = 0 ; xLinkCounterLocal < *p_xLinkToCreate; xLinkCounterLocal ++ )
		if (aDEF_xLinkTable[xLinkCounterLocal] == xLinkToTest)
			return(0);
 
	aDEF_xLinkTable[*p_xLinkToCreate] = xLinkToTest;
	(*p_xLinkToCreate) ++;
 
	return 1;
}
 
void GEO_xCreateObjectListOfEdges ( GEO_tdstGeometricObject *p_stObj )
{
  GEO_tdstTripledIndex *p_stITStart , *p_stITLast ;
  GEO_tdstElementIndexedTriangles *p_stLocalElement;
//XB99/04/27
#ifndef U64
  GEO_tdstFaceMapTriangle       *p_stITStartFMD , *p_stITLastFMD ;
  GEO_tdstElementFaceMapDescriptors *p_stLocalElementFMD;
#endif U64
//End XB99/04/27
  GEO_tdstElementLines *p_stElementLines;
  GEO_tdstDoubledIndex *p_stLineStart , *p_stLineLast ;
  ACP_tdxIndex xIndex,xIndexVertices,xNbEdges;
  ACP_tdxIndex aDEF_xLinkTable[300],xLinkToCreate;
  /*300 , cause the maximum of linked edge ever seen is 30*/
  /*so 300 is a real extremist possibility*/
 
  if ( p_stObj->d_stListOfEdges != NULL )
    return;
 
  xNbEdges = 0;
  /* compute nbedges*/
  for(xIndexVertices=0 ; xIndexVertices<p_stObj->xNbPoints ; xIndexVertices++)
  {
    xLinkToCreate = 0;
    for(xIndex=0 ; xIndex<p_stObj->xNbElements ; xIndex++)
    {
      if(p_stObj->d_xListOfElementsTypes[xIndex] == GEO_C_xElementIndexedTriangles)
      {
        p_stLocalElement =
                ((GEO_tdstElementIndexedTriangles *) p_stObj  -> d_stListOfElements[xIndex]);
        p_stITLast = p_stLocalElement -> d_stListOfFacesTripled
                     + p_stLocalElement -> xNbFaces ;
 
        for (p_stITStart = p_stLocalElement -> d_stListOfFacesTripled ;
             p_stITStart  <  p_stITLast ;
             p_stITStart ++)
        {
          if (p_stITStart -> a3_xIndex[0] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[1] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[1] ))
              xNbEdges++;
            if ((p_stITStart -> a3_xIndex[2] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[2] ))
              xNbEdges++;
          } else
          if (p_stITStart -> a3_xIndex[1] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[2] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[2] ))
              xNbEdges++;
            if ((p_stITStart -> a3_xIndex[0] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[0] ))
              xNbEdges++;
          } else
          if (p_stITStart -> a3_xIndex[2] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[1] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[1] ))
              xNbEdges++;
            if ((p_stITStart -> a3_xIndex[0] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[0] ))
              xNbEdges++;
          }
        }
      }
//XB99/04/27
#ifndef U64
      else
      if(p_stObj->d_xListOfElementsTypes[xIndex] == GEO_C_xElementFaceMapDescriptors )
      {
        p_stLocalElementFMD =
                ((GEO_tdstElementFaceMapDescriptors *) p_stObj  -> d_stListOfElements[xIndex]);
 
        p_stITLastFMD = p_stLocalElementFMD -> d_stListOfFacesQuadrupled
                     + p_stLocalElementFMD -> xNbFaces ;
 
        for (p_stITStartFMD = p_stLocalElementFMD -> d_stListOfFacesQuadrupled ;
             p_stITStartFMD  <  p_stITLastFMD ;
             p_stITStartFMD ++)
        {
          p_stITStart = &p_stITStartFMD -> stFaceTripled ;
          if (p_stITStart -> a3_xIndex[0] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[1] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[1] ))
              xNbEdges++;
            if ((p_stITStart -> a3_xIndex[2] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[2] ))
              xNbEdges++;
          } else
          if (p_stITStart -> a3_xIndex[1] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[2] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[2] ))
              xNbEdges++;
            if ((p_stITStart -> a3_xIndex[0] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[0] ))
              xNbEdges++;
          } else
          if (p_stITStart -> a3_xIndex[2] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[1] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[1] ))
              xNbEdges++;
            if ((p_stITStart -> a3_xIndex[0] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[0] ))
              xNbEdges++;
          }
        }
      }
#endif U64
//End XB99/04/27
      else
      if(p_stObj->d_xListOfElementsTypes[xIndex] == GEO_C_xElementLines )
      {
        p_stElementLines = (GEO_tdstElementLines *)(*(p_stObj->d_stListOfElements + xIndex));
 
        p_stLineLast = p_stElementLines -> d_stListOfLineIndex
                     + p_stElementLines -> xNbLines ;
 
        for (p_stLineStart = p_stElementLines -> d_stListOfLineIndex ;
             p_stLineStart  <  p_stLineLast ;
             p_stLineStart ++)
        {
          if (p_stLineStart -> a2_xIndex[0] == xIndexVertices)
          {
            if ((p_stLineStart -> a2_xIndex[1] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stLineStart -> a2_xIndex[1] ))
              xNbEdges++;
          } else
          if (p_stLineStart -> a2_xIndex[1] == xIndexVertices)
          {
            if ((p_stLineStart -> a2_xIndex[0] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stLineStart -> a2_xIndex[0] ))
              xNbEdges++;
          }
        }
      }
    }
  }
  MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeListOfEdge , 0 );
  /* Create EDGE TABLE*/
  GEO_M_CPAMalloc (
    p_stObj->d_stListOfEdges ,
    GEO_tdstDoubledIndex * ,
    sizeof (GEO_tdstDoubledIndex) * xNbEdges,
    E_uwGEONotEnoughtMemory );
 
  MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeListOfEdgeMaterial , 0 );
  GEO_M_CPAMalloc (
    p_stObj->d_hListOfEdgesMaterial ,
    /*ACP_tdxHandleOfMaterial*/ GMT_tdxHandleToGameMaterial * ,
    sizeof (/*ACP_tdxHandleOfMaterial*/ GMT_tdxHandleToGameMaterial) * xNbEdges,
    E_uwGEONotEnoughtMemory );
 
  p_stObj -> xNbEdges = xNbEdges;
}
 
/**********************************************************************************************/
/* Compute Edges*/
/* Goal: Compute the liste of edge of geometric object*/
/* Code by philippe Vimont*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void
GEO_xComputeObjectListOfEdges ( GEO_tdstGeometricObject *p_stObj )
{
  GEO_tdstTripledIndex *p_stITStart , *p_stITLast ;
  GEO_tdstDoubledIndex *p_stEdgeToBuild;
  GEO_tdstElementIndexedTriangles *p_stLocalElement;
//XB99/04/27
#ifndef U64
  GEO_tdstFaceMapTriangle       *p_stITStartFMD , *p_stITLastFMD ;
  GEO_tdstElementFaceMapDescriptors *p_stLocalElementFMD;
#endif U64
//End XB99/04/27
  GEO_tdstElementLines *p_stElementLines;
  GEO_tdstDoubledIndex *p_stLineStart , *p_stLineLast ;
  GMT_tdxHandleToGameMaterial *p_hEdgeMaterialToBuild;
//XB99/04/27
#ifndef U64
  GMT_tdxHandleToGameMaterial hMaterial;
#endif U64
//End XB99/04/27
  GMT_tdxHandleToGameMaterial *p_hLineMaterial;
  ACP_tdxIndex xIndex,xIndexVertices;
  ACP_tdxIndex aDEF_xLinkTable[300],xLinkToCreate;
  /*300 , cause the maximum of linked edge ever seen is 30*/
  /*so 300 is a real extremist possibility*/
 
  p_stEdgeToBuild = p_stObj->d_stListOfEdges ;
  p_hEdgeMaterialToBuild = p_stObj->d_hListOfEdgesMaterial ;
 
  for(xIndexVertices=0 ; xIndexVertices<p_stObj->xNbPoints ; xIndexVertices++)
  {
    xLinkToCreate = 0;
    for(xIndex=0 ; xIndex<p_stObj->xNbElements ; xIndex++)
    {
      if(p_stObj->d_xListOfElementsTypes[xIndex] == GEO_C_xElementIndexedTriangles)
      {
        p_stLocalElement =
                ((GEO_tdstElementIndexedTriangles *) p_stObj  -> d_stListOfElements[xIndex]);
 
        p_stITLast = p_stLocalElement -> d_stListOfFacesTripled
                     + p_stLocalElement -> xNbFaces ;
 
        for (p_stITStart = p_stLocalElement -> d_stListOfFacesTripled ;
             p_stITStart  <  p_stITLast ;
             p_stITStart ++)
        {
          if (p_stITStart -> a3_xIndex[0] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[1] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[1] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[1];
              *p_hEdgeMaterialToBuild = p_stLocalElement->hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
            if ((p_stITStart -> a3_xIndex[2] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[2] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[2];
              *p_hEdgeMaterialToBuild = p_stLocalElement->hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
          } else
          if (p_stITStart -> a3_xIndex[1] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[2] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[2] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[2];
              *p_hEdgeMaterialToBuild = p_stLocalElement->hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
            if ((p_stITStart -> a3_xIndex[0] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[0] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[0];
              *p_hEdgeMaterialToBuild = p_stLocalElement->hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
          } else
          if (p_stITStart -> a3_xIndex[2] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[1] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[1] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[1];
              *p_hEdgeMaterialToBuild = p_stLocalElement->hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
            if ((p_stITStart -> a3_xIndex[0] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[0] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[0];
              *p_hEdgeMaterialToBuild = p_stLocalElement->hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
          }
        }
      }
//XB99/04/27
#ifndef U64
      else
      if(p_stObj->d_xListOfElementsTypes[xIndex] == GEO_C_xElementFaceMapDescriptors )
      {
        p_stLocalElementFMD =
                ((GEO_tdstElementFaceMapDescriptors *) p_stObj  -> d_stListOfElements[xIndex]);
 
        p_stITLastFMD = p_stLocalElementFMD -> d_stListOfFacesQuadrupled
                     + p_stLocalElementFMD -> xNbFaces ;
 
        for (p_stITStartFMD = p_stLocalElementFMD -> d_stListOfFacesQuadrupled ;
             p_stITStartFMD  <  p_stITLastFMD ;
             p_stITStartFMD ++)
        {
          p_stITStart = &p_stITStartFMD -> stFaceTripled ;
          GEO_xGetFaceMapDescriptorGameMaterial ( p_stITStartFMD->hFaceMapDescriptor, &hMaterial );
 
          if (p_stITStart -> a3_xIndex[0] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[1] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[1] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[1];
              *p_hEdgeMaterialToBuild = hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
            if ((p_stITStart -> a3_xIndex[2] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[2] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[2];
              *p_hEdgeMaterialToBuild = hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
          } else
          if (p_stITStart -> a3_xIndex[1] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[2] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[2] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[2];
              *p_hEdgeMaterialToBuild = hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
            if ((p_stITStart -> a3_xIndex[0] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[0] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[0];
              *p_hEdgeMaterialToBuild = hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
          } else
          if (p_stITStart -> a3_xIndex[2] == xIndexVertices)
          {
            if ((p_stITStart -> a3_xIndex[1] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[1] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[1];
              *p_hEdgeMaterialToBuild = hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
            if ((p_stITStart -> a3_xIndex[0] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stITStart -> a3_xIndex[0] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stITStart -> a3_xIndex[0];
              *p_hEdgeMaterialToBuild = hMaterial;
              p_hEdgeMaterialToBuild ++;
            }
          }
        }
      }
#endif U64
//End XB99/04/27
     else
     if(p_stObj->d_xListOfElementsTypes[xIndex] == GEO_C_xElementLines )
      {
        p_stElementLines = (GEO_tdstElementLines *)(*(p_stObj->d_stListOfElements + xIndex));
 
        p_stLineLast = p_stElementLines -> d_stListOfLineIndex
                     + p_stElementLines -> xNbLines ;
 
        p_hLineMaterial = p_stElementLines->d_hListOfLinesMaterial;
 
        for (p_stLineStart = p_stElementLines -> d_stListOfLineIndex ;
             p_stLineStart  <  p_stLineLast ;
             p_stLineStart ++, p_hLineMaterial++ )
        {
          if (p_stLineStart -> a2_xIndex[0] == xIndexVertices)
          {
            if ((p_stLineStart -> a2_xIndex[1] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stLineStart -> a2_xIndex[1] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stLineStart -> a2_xIndex[1];
              *p_hEdgeMaterialToBuild = *p_hLineMaterial;
              p_hEdgeMaterialToBuild ++;
            }
          } else
          if (p_stLineStart -> a2_xIndex[1] == xIndexVertices)
          {
            if ((p_stLineStart -> a2_xIndex[0] > xIndexVertices) && GEO_fbIsNotLinked(aDEF_xLinkTable,&xLinkToCreate,p_stLineStart -> a2_xIndex[0] ))
            {
              p_stEdgeToBuild -> a2_xIndex[0] = xIndexVertices;
              (p_stEdgeToBuild++) -> a2_xIndex[1] = p_stLineStart -> a2_xIndex[0];
              *p_hEdgeMaterialToBuild = *p_hLineMaterial;
              p_hEdgeMaterialToBuild ++;
            }
          }
        }
      }
    }
  }
}
 
/**********************************************************************************************/
/* Name: GEO_xDuplicateObject*/
/* Goal: Duplicate an object without common table (vertices, ...)*/
/* Code: Marc Villemain (indispensable for D3D)*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
#ifndef _FIRE_DEADCODE_U64_
GEO_tdstGeometricObject *GEO_xDuplicateVisualObject ( GEO_tdstGeometricObject *p_stObj )
{
  return ( p_stObj );
}
#endif /* _FIRE_DEADCODE_U64_ */
 
/**********************************************************************************************/
/* Name: GEO_lGetGeometricObjectNumberOfElements*/
/* Goal: return's the number of elements of a geometric object*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
long GEO_lGetGeometricObjectNumberOfElements ( ACP_tdxHandleOfObject hObject )
{
	return hObject->xNbElements ;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/**********************************************************************************************/
/* Name: GEO_vResetGeometricObjectElements*/
/* Goal: reset an element (can be use in real time, it is not a delete)*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
#ifndef _FIRE_DEADCODE_U64_
void GEO_vResetGeometricObjectElements (ACP_tdxHandleOfObject hObject , ACP_tdxHandleOfElement hElement )
{
	hObject->d_xListOfElementsTypes[hElement] = GEO_C_xElementNULL;
}
 
/**********************************************************************************************/
/* Name: GEO_xDuplicateGeometricObject*/
/* Goal: Duplicate an object without common table (vertices, ...)*/
/* Code: Philippe Vimont 1.0 (duplicate.doc)*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
ACP_tdxHandleOfObject GEO_xDuplicateGeometricObject( ACP_tdxHandleOfObject hObject , ACP_tdxIndex xNewNumberOfElement)
{
	GEO_tdstGeometricObject		*p_stObjTmp;
	ACP_tdxHandleOfObject		hObjectRet;
	ACP_tdxIndex				xElementCounter;
 
	if(hObject == NULL)
		return NULL;
 
	if (xNewNumberOfElement == 0)
		xNewNumberOfElement = hObject->xNbElements;
 
	MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeMainObject , 0 );
	GEO_M_CPAMalloc ( p_stObjTmp , GEO_tdstGeometricObject*, sizeof(GEO_tdstGeometricObject), E_uwGEONotEnoughtMemory );
 
	if(p_stObjTmp == NULL)
		return(NULL);
 
	*p_stObjTmp = *hObject;
	p_stObjTmp->xNbElements = xNewNumberOfElement;
 
	MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeListOfElementType , 0 );
	GEO_M_CPAMalloc ( p_stObjTmp -> d_xListOfElementsTypes , ACP_tdxIndex  * , sizeof ( ACP_tdxIndex ) * xNewNumberOfElement , E_uwGEONotEnoughtMemory );
	MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeListOfElement , 0 );
	GEO_M_CPAMalloc ( p_stObjTmp -> d_stListOfElements , void ** , sizeof ( void * ) * xNewNumberOfElement , E_uwGEONotEnoughtMemory );
 
	if ((p_stObjTmp -> d_stListOfElements == NULL) || (p_stObjTmp -> d_xListOfElementsTypes == NULL ))
          return NULL;
 
	for (xElementCounter = 0; xElementCounter < xNewNumberOfElement; xElementCounter ++)
		p_stObjTmp -> d_xListOfElementsTypes[xNewNumberOfElement] = GEO_C_xElementNULL;
 
	if (xNewNumberOfElement >= hObject -> xNbElements)
	{
		memcpy(p_stObjTmp -> d_stListOfElements, hObject -> d_stListOfElements, sizeof(void *) * hObject -> xNbElements);
		memcpy(p_stObjTmp -> d_xListOfElementsTypes, hObject -> d_xListOfElementsTypes, sizeof(ACP_tdxIndex) * hObject -> xNbElements);
	}
 
	hObjectRet = p_stObjTmp;
	return ( hObjectRet );
}
#endif /* _FIRE_DEADCODE_U64_ */
 
/**********************************************************************************************/
/* Name: GEO_xGetElementType*/
/* Goal: get ... (duplicate.doc)*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
ACP_tdxIndex GEO_xGetElementType ( ACP_tdxHandleOfObject hObject , ACP_tdxIndex xElement )
{
	return (hObject -> d_xListOfElementsTypes [xElement]);
}
 
/**********************************************************************************************/
/* Name: GEO_xGetGeometricObjectNumberOfElements*/
/* Goal: get ... (duplicate.doc)*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/

#ifdef USE_PROFILER
ACP_tdxIndex GEO_xGetGeometricObjectNumberOfElements( ACP_tdxHandleOfObject hObject )
{
	ACP_tdxIndex xI,xNumberOfElement;
 
	xNumberOfElement = 0;
    for (xI = 0 ; xI < hObject -> xNbElements ; xI ++ )
		if (hObject -> d_xListOfElementsTypes [xI] != GEO_C_xElementNULL)
			xNumberOfElement++;
	return (xNumberOfElement);
}
#endif 
 
 
/**********************************************************************************************/
/* Name: GEO_xGetGeometricObjectNumberOfElementsMax*/
/* Goal: get ...(duplicate.doc)*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
ACP_tdxIndex GEO_xGetGeometricObjectNumberOfElementsMax( ACP_tdxHandleOfObject hObject )
{
	return(hObject -> xNbElements);
}
 
#ifndef _FIRE_DEADCODE_U64_
/**********************************************************************************************/
/* Name: GEO_xDuplicateGeometricObjectCommonData*/
/* Goal: duplicate vertice, vertice normals or vertices colors .... (duplicate.doc)*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_xDuplicateGeometricObjectCommonData ( ACP_tdxHandleOfObject hObject1 , ACP_tdxHandleOfObject hObject2 , long lWhatIsDuplicate )
{
	if (hObject1 == hObject2)
		return;
 
	if (lWhatIsDuplicate & GEO_C_lDuplicateVertices)
	{
		MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeListOfPoint , 0 );
		GEO_M_CPAMalloc ( hObject2->d_stListOfPoints  , MTH3D_tdstVector *  , sizeof ( MTH3D_tdstVector) * hObject1->xNbPoints , E_uwGEONotEnoughtMemory );
		memcpy( hObject2->d_stListOfPoints, hObject1->d_stListOfPoints, sizeof ( MTH3D_tdstVector) * hObject1->xNbPoints  );
	}
	if (lWhatIsDuplicate & GEO_C_lDuplicateVerticesNormals )
	{
		MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypePointsNormals , 0 );
		GEO_M_CPAMalloc ( hObject2->d_stListOfPointsNormals , MTH3D_tdstVector *  , sizeof ( MTH3D_tdstVector) * hObject1->xNbPoints, E_uwGEONotEnoughtMemory );
		memcpy( hObject2->d_stListOfPointsNormals   , hObject1->d_stListOfPointsNormals   , sizeof ( MTH3D_tdstVector) * hObject1->xNbPoints);
	}
	/*
	if (lWhatIsDuplicate & GEO_C_lDuplicateColideInformation)
	{
	}
	*/
}
#endif /* _FIRE_DEADCODE_U64_ */
 
/**********************************************************************************************/
/* Name: GEO_bDuplicateGeometricObjectElement*/
/* Goal: duplicate an element (duplicate.doc)*/
/*       example for an indextriangle, duplicate the element without duplicate the faces*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
#define GEO_M_DuplicateElement( Elem ) \
     GEO_M_CPAMalloc (\
			hObject2 -> d_stListOfElements [*p_xElementCounter] ,\
			void *,\
			sizeof( Elem ) ,\
			E_uwGEONotEnoughtMemory );\
     if (hObject2 -> d_stListOfElements [*p_xElementCounter] == NULL) return(FALSE);\
     hObject2 -> d_xListOfElementsTypes [*p_xElementCounter] = hObject1 -> d_xListOfElementsTypes [hElement];\
         memcpy(                                      \
           hObject2->d_stListOfElements [*p_xElementCounter]  , \
           hObject1->d_stListOfElements [hElement]  , \
           sizeof ( Elem ) )
 
 
#ifndef _FIRE_DEADCODE_U64_
long GEO_bDuplicateGeometricObjectElement ( ACP_tdxHandleOfObject hObject1 , ACP_tdxHandleOfObject hObject2 , ACP_tdxHandleOfElement hElement , ACP_tdxHandleOfElement *p_xElementCounter)
{
	for (*p_xElementCounter = 0; *p_xElementCounter < hObject2 -> xNbElements; (*p_xElementCounter) ++)
		if (hObject2 -> d_xListOfElementsTypes[*p_xElementCounter] == GEO_C_xElementNULL)
			break;
	if ( *p_xElementCounter == hObject2 -> xNbElements )
		return(FALSE);
 
	switch (hObject1 -> d_xListOfElementsTypes [hElement])
	{
		 case GEO_C_xElementNULL:
			break;
		case GEO_C_xElementPoints:
			GEO_M_DuplicateElement( GEO_tdstElementPoints ) ;
            break;
		case GEO_C_xElementLines:
			GEO_M_DuplicateElement( GEO_tdstElementLines ) ;
            break;
		case GEO_C_xElementFaceMapDescriptors :
			GEO_M_DuplicateElement( GEO_tdstElementFaceMapDescriptors  ) ;
            break;
		case GEO_C_xElementSprites:
			GEO_M_DuplicateElement( GEO_tdstElementSprite ) ;
            break;
		case GEO_C_xElementSpheres:
			GEO_M_DuplicateElement( GEO_tdstElementSpheres ) ;
		    break;
		case GEO_C_xElementAlignedBoxes:
			GEO_M_DuplicateElement( GEO_tdstElementAlignedBoxes ) ;
		    break;
		case GEO_C_xElementCones:
			GEO_M_DuplicateElement( GEO_tdstIndexedCone ) ;
		    break;
		case GEO_C_xElementTMeshes:
			GEO_M_DuplicateElement( GEO_tdstElementTMeshes ) ;
            break;
		case GEO_C_xElementIndexedTriangles :
			GEO_M_DuplicateElement( GEO_tdstElementIndexedTriangles ) ;
            break;
	} /* Element switch*/
	return(TRUE);
}
 
 
/**********************************************************************************************/
/* Name: GEO_bCopyingGeometricObjectElement*/
/* Goal: copying an element (duplicate.doc)*/
/* Code: Philippe Vimont 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
long GEO_bCopyingGeometricObjectElement
	(
        ACP_tdxHandleOfObject hObject1 ,
        ACP_tdxHandleOfObject hObject2 ,
        ACP_tdxIndex xElementNumberInFirstObject  ,
        ACP_tdxIndex *p_xNewElementNumberInSecondObject
	)
{
  for (*p_xNewElementNumberInSecondObject = 0;
       *p_xNewElementNumberInSecondObject < hObject2 -> xNbElements;
       (*p_xNewElementNumberInSecondObject) ++)
    if (hObject2 -> d_xListOfElementsTypes[*p_xNewElementNumberInSecondObject] == GEO_C_xElementNULL)
          break;
  if ( *p_xNewElementNumberInSecondObject == hObject2 -> xNbElements ) return(FALSE);
  hObject2 -> d_xListOfElementsTypes [ *p_xNewElementNumberInSecondObject ] =
    hObject1 -> d_xListOfElementsTypes [ xElementNumberInFirstObject ];
  hObject2 -> d_stListOfElements [ *p_xNewElementNumberInSecondObject ] =
    hObject1 -> d_stListOfElements [ xElementNumberInFirstObject ];
  return TRUE;
}
#endif /* _FIRE_DEADCODE_U64_ */
 
/**********************************************************************************************/
/* Name: GEO_vCreateObjectListOfPointsMaterial*/
/* Goal: create the list of point materials*/
/* Code: Frederic Philippe 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void
GEO_vCreateObjectListOfPointsMaterial
(
        ACP_tdxHandleOfObject hObject
)
{
  if ( hObject->d_hListOfPointsMaterial != NULL )
    return;
 
  MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypePointsMaterial , 0 );
  GEO_M_CPAMalloc (
        hObject->d_hListOfPointsMaterial ,
		/*ACP_tdxHandleOfMaterial*/ GMT_tdxHandleToGameMaterial *,
	    (hObject->xNbPoints)*sizeof( /*ACP_tdxHandleOfMaterial*/ GMT_tdxHandleToGameMaterial ) ,
		E_uwGEONotEnoughtMemory );
}
 
/**********************************************************************************************/
/* Name: GEO_vComputeObjectListOfPointsMaterial*/
/* Goal: compute the list of point materials*/
/* Code: Frederic Philippe 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void
GEO_vComputeObjectListOfPointsMaterial
(
        ACP_tdxHandleOfObject hObject
)
{
  ACP_tdxIndex xElementIndex;
  ACP_tdxIndex xDataElementIndex;
  GEO_tdstElementIndexedTriangles *p_stElementIndexedTriangles;
//XB99/04/27
#ifndef U64
  GEO_tdstElementFaceMapDescriptors *p_stElementFaceMapDescriptors;
#endif U64
//End XB99/04/27
  GEO_tdstElementSpheres *p_stElementSpheres;
  GEO_tdstElementAlignedBoxes *p_stElementAlignedBoxes;
  GEO_tdstElementPoints *p_stElementPoints;
  GEO_tdstElementLines *p_stElementLines;
 
  ACP_tdxIndex xPointIndex;
  ACP_tdxIndex xGlobalPointIndex;
  /*ACP_tdxHandleOfMaterial hMaterial;*/
//XB99/04/27
#ifndef U64
  GMT_tdxHandleToGameMaterial hMaterial;
#endif U64
//End XB99/04/27
  GEO_tdstIndexedSphere *p_stIndexedSphere;
  GEO_tdstIndexedAlignedBox *p_stIndexedAlignedBox;
 
  for ( xElementIndex = 0 ; xElementIndex < hObject->xNbElements ; xElementIndex++ )
  {
    switch ( *(hObject->d_xListOfElementsTypes + xElementIndex) )
    {
      case GEO_C_xElementIndexedTriangles :
        p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(*(hObject->d_stListOfElements + xElementIndex));
 
        /* pour les triangles */
        for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementIndexedTriangles->xNbFaces ; xDataElementIndex++ )
        {
          /* points du triangle */
          for ( xPointIndex = 0 ; xPointIndex < 3 ; xPointIndex++ )
          {
            xGlobalPointIndex = (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[xPointIndex];
						if ( hObject->d_hListOfPointsMaterial )
							*(hObject->d_hListOfPointsMaterial + xGlobalPointIndex) = p_stElementIndexedTriangles->hMaterial;
          }
        }
      break;
 
//XB99/04/27
#ifndef U64
      case GEO_C_xElementFaceMapDescriptors :
        p_stElementFaceMapDescriptors = (GEO_tdstElementFaceMapDescriptors *)(*(hObject->d_stListOfElements + xElementIndex));
 
        /* pour les triangles */
        for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementFaceMapDescriptors->xNbFaces ; xDataElementIndex++ )
        {
          GEO_xGetFaceMapDescriptorGameMaterial ( (p_stElementFaceMapDescriptors->d_stListOfFacesQuadrupled + xDataElementIndex)->hFaceMapDescriptor,
                                                  &hMaterial);
          /* points du triangle */
          for ( xPointIndex = 0 ; xPointIndex < 3 ; xPointIndex++ )
          {
            xGlobalPointIndex = (p_stElementFaceMapDescriptors->d_stListOfFacesQuadrupled + xDataElementIndex)->stFaceTripled.a3_xIndex[xPointIndex];
						if ( hObject->d_hListOfPointsMaterial )
							*(hObject->d_hListOfPointsMaterial + xGlobalPointIndex) = hMaterial;
          }
        }
      break;
#endif U64
//End XB99/04/27
 
      case GEO_C_xElementSpheres :
        p_stElementSpheres = (GEO_tdstElementSpheres *)(*(hObject->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 */
          xGlobalPointIndex = p_stIndexedSphere->xCenterPoint;
					if ( hObject->d_hListOfPointsMaterial )
						*(hObject->d_hListOfPointsMaterial + xGlobalPointIndex) = p_stIndexedSphere->hMaterial;
        }
      break;
 
      case GEO_C_xElementAlignedBoxes :
        p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(*(hObject->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 */
          xGlobalPointIndex = p_stIndexedAlignedBox->xMinPoint;
					if ( hObject->d_hListOfPointsMaterial )
						*(hObject->d_hListOfPointsMaterial + xGlobalPointIndex) = p_stIndexedAlignedBox->hMaterial;
          xGlobalPointIndex = p_stIndexedAlignedBox->xMaxPoint;
					if ( hObject->d_hListOfPointsMaterial )
						*(hObject->d_hListOfPointsMaterial + xGlobalPointIndex) = p_stIndexedAlignedBox->hMaterial;
        }
      break;
 
      case GEO_C_xElementPoints :
        p_stElementPoints = (GEO_tdstElementPoints *)(*(hObject->d_stListOfElements + xElementIndex));
 
        /* pour les points */
        for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementPoints->xNbPoints ; xDataElementIndex++ )
        {
          xGlobalPointIndex = *(p_stElementPoints->d_xListOfPointIndex + xDataElementIndex);
					if ( hObject->d_hListOfPointsMaterial )
						*(hObject->d_hListOfPointsMaterial + xGlobalPointIndex) = p_stElementPoints->hMaterial;
        }
      break;
 
      case GEO_C_xElementLines :
        p_stElementLines = (GEO_tdstElementLines *)(*(hObject->d_stListOfElements + xElementIndex));
 
        /* pour les lignes */
        for ( xDataElementIndex = 0 ; xDataElementIndex < p_stElementLines->xNbLines ; xDataElementIndex++ )
        {
          /* points de la ligne */
          xGlobalPointIndex = (p_stElementLines->d_stListOfLineIndex + xDataElementIndex)->a2_xIndex[0];
					if ( hObject->d_hListOfPointsMaterial )
						*(hObject->d_hListOfPointsMaterial + xGlobalPointIndex) = *(p_stElementLines->d_hListOfLinesMaterial + xDataElementIndex);
          xGlobalPointIndex = (p_stElementLines->d_stListOfLineIndex + xDataElementIndex)->a2_xIndex[1];
					if ( hObject->d_hListOfPointsMaterial )
						*(hObject->d_hListOfPointsMaterial + xGlobalPointIndex) = *(p_stElementLines->d_hListOfLinesMaterial + xDataElementIndex);
        }
      break;
    }
  }
}
 
/**********************************************************************************************/
/* Name: GEO_vEndModifyObject*/
/* Goal: end the modify*/
/* Code: Marc Villemain 1.1*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_vEndModifyObject(ACP_tdxHandleOfObject hObject)
{
	GEO_xComputeObjectNormals(hObject);
	GEO_xComputeIndexUsedByElements ( hObject );
	GEO_vComputeObjectListOfParallelBox ( hObject );
 
    /*VLNEWGLI*/
#ifndef U64
	hObject->xBoudingSphereCenter = *(hObject->d_stListOfPoints);
	hObject->xBoudingSphereRadius = 0.0f;
    GEO_fn_vAddObjectToSphere( hObject , &hObject->xBoudingSphereCenter , &hObject->xBoudingSphereRadius );
#endif /*U64*/
	/*EVL*/
 
}
 
/**********************************************************************************************/
/* Name: GEO_vEndCreateObject*/
/* Goal: end the creation*/
/* Code: Frederic Philippe 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/

#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC 04/06/99 */
void GEO_vEndCreateObject(ACP_tdxHandleOfObject hObject)
{
	GEO_xCreateObjectPointNormals ( hObject );
	GEO_vCreateObjectListOfParallelBox ( hObject, hObject -> xNbParallelBoxes );
	GEO_xComputeObjectNormals2(hObject);
	GEO_vComputeObjectListOfParallelBox ( hObject );
 
    /*VLNEWGLI*/
#ifndef U64
	hObject->xBoudingSphereCenter = *(hObject->d_stListOfPoints);
	hObject->xBoudingSphereRadius = 0.0f;
    GEO_fn_vAddObjectToSphere( hObject , &hObject->xBoudingSphereCenter , &hObject->xBoudingSphereRadius );
#endif /*U64*/
	/*EVL*/
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC 04/06/99 */
 
 
/**********************************************************************************************/
/* Name: GEO_vEndModifyObject2*/
/* Goal: end the modify*/
/* Code: Frederic Philippe 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GEO_vEndModifyObject2(ACP_tdxHandleOfObject hObject)
{
	GEO_xComputeObjectNormals2(hObject);
	GEO_vComputeObjectListOfParallelBox ( hObject );
 
    /*VLNEWGLI*/
#ifndef U64
	hObject->xBoudingSphereCenter = *(hObject->d_stListOfPoints);
	hObject->xBoudingSphereRadius = 0.0f;
    GEO_fn_vAddObjectToSphere( hObject , &hObject->xBoudingSphereCenter , &hObject->xBoudingSphereRadius );
#endif /*U64*/
	/*EVL*/
 
}
 
/**********************************************************************************************/
/* Name: GEO_vEndModifyGoThroughObject*/
/* Goal: end the modify*/
/* Code: Marc Villemain 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void GEO_vEndModifyGoThroughObject(ACP_tdxHandleOfObject hObject)
{
	GEO_xComputeObjectNormals(hObject);
	GEO_vComputeObjectListOfParallelBox ( hObject );
 
    /*VLNEWGLI*/
#ifndef U64
	hObject->xBoudingSphereCenter = *(hObject->d_stListOfPoints);
	hObject->xBoudingSphereRadius = 0.0f;
    GEO_fn_vAddObjectToSphere( hObject , &hObject->xBoudingSphereCenter , &hObject->xBoudingSphereRadius );
#endif /*U64*/
	/*EVL*/
 
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
/**********************************************************************************************/
/* Name: GEO_vEndModifyObjectWithoutComputingNormal*/
/* Goal: same as GEO_vEndModifyObject by do not compute the normals*/
/* Code: Alexis Vaisse*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/

#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC 04/06/99 */
void GEO_vEndModifyObjectWithoutComputingNormal (ACP_tdxHandleOfObject hObject)
{
	GEO_xComputeIndexUsedByElements ( hObject );
	GEO_vComputeObjectListOfParallelBox ( hObject );
 
    /*VLNEWGLI*/
#ifndef U64
	hObject->xBoudingSphereCenter = *(hObject->d_stListOfPoints);
	hObject->xBoudingSphereRadius = 0.0f;
    GEO_fn_vAddObjectToSphere( hObject , &hObject->xBoudingSphereCenter , &hObject->xBoudingSphereRadius );
#endif /*U64*/
	/*EVL*/
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC 04/06/99 */

 
/**********************************************************************************************/
/* Name: GEO_vGetNormalOfGeometricObjectElement*/
/* Goal: get the normal of an element (IT and FMD)*/
/* Code: Frederic Philippe 1.0*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void
GEO_vGetNormalOfGeometricObjectElement
(
        ACP_tdxHandleOfObject hObject,
        ACP_tdxIndex xElementIndex,
        ACP_tdxIndex xDataElementIndex,
        MTH3D_tdstVector *p_stNormal
)
{
  GEO_tdstElementIndexedTriangles *p_stElementIndexedTriangles;
//XB99/04/27
#ifndef U64
  GEO_tdstElementFaceMapDescriptors *p_stElementFaceMapDescriptors;
#endif U64
//End XB99/04/27
 
  MTH3D_M_vNullVector ( p_stNormal );
 
  switch ( hObject->d_xListOfElementsTypes[xElementIndex] )
  {
    case GEO_C_xElementIndexedTriangles :
      p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(hObject->d_stListOfElements[xElementIndex]);
 
      MTH3D_M_vCopyVector ( p_stNormal, (p_stElementIndexedTriangles->d_stListOfFacesNormals + xDataElementIndex) );
    break;
 
//XB99/04/27
#ifndef U64
    case GEO_C_xElementFaceMapDescriptors :
      p_stElementFaceMapDescriptors = (GEO_tdstElementFaceMapDescriptors *)(hObject->d_stListOfElements[xElementIndex]);
 
      MTH3D_M_vCopyVector ( p_stNormal, (p_stElementFaceMapDescriptors->d_stListOfFacesNormals + xDataElementIndex) );
    break;
#endif U64
//End XB99/04/27
  }
}
 
/*
--------------------------------------------------------------------------------
-- Description : Get the material of geometric object element
--------------------------------------------------------------------------------
-- Creation date : 19 feb 1997               Author : FPI
--------------------------------------------------------------------------------
-- Modification : Use GMT
-- Modification date : Mar 97				Author : A.R.
--------------------------------------------------------------------------------
*/
 
#ifndef _FIRE_DEADCODE_U64_
ACP_tdxHandleOfMaterial
GEO_hGetMaterialOfGeometricObjectElement ( ACP_tdxHandleOfObject hObject,
                                           ACP_tdxIndex xElementIndex,
                                           ACP_tdxIndex xDataElementIndex )
{
  GEO_tdstElementIndexedTriangles *p_stElementIndexedTriangles;
  GEO_tdstElementFaceMapDescriptors *p_stElementFaceMapDescriptors;
  GEO_tdstElementSpheres *p_stElementSpheres;
  GEO_tdstElementAlignedBoxes *p_stElementAlignedBoxes;
 
  ACP_tdxHandleOfMaterial hMaterial;
 
  switch ( hObject->d_xListOfElementsTypes[xElementIndex] )
  {
    case GEO_C_xElementIndexedTriangles :
      p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(hObject->d_stListOfElements[xElementIndex]);
 
      return GMT_fn_hGetVisualMaterial(p_stElementIndexedTriangles->hMaterial);
    break;
 
    case GEO_C_xElementFaceMapDescriptors :
      p_stElementFaceMapDescriptors = (GEO_tdstElementFaceMapDescriptors *)(hObject->d_stListOfElements[xElementIndex]);
 
      GEO_xGetFaceMapDescriptorMaterial ( (p_stElementFaceMapDescriptors->d_stListOfFacesQuadrupled + xDataElementIndex)->hFaceMapDescriptor, &hMaterial );
      return hMaterial;
    break;
 
    case GEO_C_xElementSpheres :
      p_stElementSpheres = (GEO_tdstElementSpheres *)(hObject->d_stListOfElements[xElementIndex]);
 
      return GMT_fn_hGetVisualMaterial((p_stElementSpheres->d_stListOfSpheres + xDataElementIndex)->hMaterial);
    break;
 
    case GEO_C_xElementAlignedBoxes :
      p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(hObject->d_stListOfElements[xElementIndex]);
 
      return GMT_fn_hGetVisualMaterial((p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex)->hMaterial);
    break;
 
    default :
    break;
  }
 
  return NULL;
}
#endif /* _FIRE_DEADCODE_U64_ */
 
/*
--------------------------------------------------------------------------------
-- Description : Get the game material of geometric object element
--------------------------------------------------------------------------------
-- Creation date : Mar 97               Author : A.R.
--------------------------------------------------------------------------------
-- Modification :
-- Modification date :					Author :
--------------------------------------------------------------------------------
*/
 
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
GMT_tdxHandleToGameMaterial
GEO_fn_hGetGameMaterialOfGeometricObjectElement ( ACP_tdxHandleOfObject hObject,
					                              ACP_tdxIndex xElementIndex,
						                          ACP_tdxIndex xDataElementIndex )
{
  GEO_tdstElementIndexedTriangles *p_stElementIndexedTriangles;
  GEO_tdstElementFaceMapDescriptors *p_stElementFaceMapDescriptors;
  GEO_tdstElementSpheres *p_stElementSpheres;
  GEO_tdstElementAlignedBoxes *p_stElementAlignedBoxes;
 
  GMT_tdxHandleToGameMaterial hMaterial;
 
  switch ( hObject->d_xListOfElementsTypes[xElementIndex] )
  {
    case GEO_C_xElementIndexedTriangles :
      p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(hObject->d_stListOfElements[xElementIndex]);
 
      return p_stElementIndexedTriangles->hMaterial;
    break;
 
    case GEO_C_xElementFaceMapDescriptors :
      p_stElementFaceMapDescriptors = (GEO_tdstElementFaceMapDescriptors *)(hObject->d_stListOfElements[xElementIndex]);
 
      GEO_xGetFaceMapDescriptorGameMaterial ( (p_stElementFaceMapDescriptors->d_stListOfFacesQuadrupled + xDataElementIndex)->hFaceMapDescriptor, &hMaterial );
      return hMaterial;
    break;
 
    case GEO_C_xElementSpheres :
      p_stElementSpheres = (GEO_tdstElementSpheres *)(hObject->d_stListOfElements[xElementIndex]);
 
      return (p_stElementSpheres->d_stListOfSpheres + xDataElementIndex)->hMaterial;
    break;
 
    case GEO_C_xElementAlignedBoxes :
      p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(hObject->d_stListOfElements[xElementIndex]);
 
      return (p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex)->hMaterial;
    break;
 
    default :
    break;
  }
 
  return NULL;
}
 
/*
--------------------------------------------------------------------------------
-- Description : Edge part of an edge
--------------------------------------------------------------------------------
-- Creation date : 18 nov 1996               Author : FPI
--------------------------------------------------------------------------------
*/
 
ACP_tdxBool GEO_bEdgePartOfEdge ( ACP_tdxIndex xEdge1,
                                  ACP_tdxIndex xEdge2,
                                  ACP_tdxIndex xPoint1,
                                  ACP_tdxIndex xPoint2 )
{
  return ( ( xEdge1 == xPoint1 ) && ( xEdge2 == xPoint2 ) ) ||
         ( ( xEdge1 == xPoint2 ) && ( xEdge2 == xPoint1 ) );
}
 
/*
--------------------------------------------------------------------------------
-- Description : Set an edge material
--------------------------------------------------------------------------------
-- Creation date : 10 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void
GEO_vSetEdgeMaterial
(
        ACP_tdxHandleOfObject hObject,
        ACP_tdxIndex xPoint1,
        ACP_tdxIndex xPoint2,
        GMT_tdxHandleToGameMaterial hMaterial
)
{
  ACP_tdxIndex xEdgeIndex;
 
  /* on cherche le edge */
  for ( xEdgeIndex = 0 ; xEdgeIndex < hObject->xNbEdges ; xEdgeIndex ++ )
  {
    if
      (
        GEO_bEdgePartOfEdge ( (hObject->d_stListOfEdges + xEdgeIndex)->a2_xIndex[0],
                              (hObject->d_stListOfEdges + xEdgeIndex)->a2_xIndex[1],
                              xPoint1, xPoint2 )
      )
    {
      hObject->d_hListOfEdgesMaterial[xEdgeIndex] = hMaterial;
      return;
    }
  }
}
 
/*
--------------------------------------------------------------------------------
-- Description : Compute the material modification of an element
--------------------------------------------------------------------------------
-- Creation date : 10 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void
GEO_vComputeElementMaterial
(
        ACP_tdxHandleOfObject hObject,
        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;
  ACP_tdxIndex xGlobalPointIndex;
  GEO_tdstIndexedSphere *p_stIndexedSphere;
  GEO_tdstIndexedAlignedBox *p_stIndexedAlignedBox;
  GMT_tdxHandleToGameMaterial hMaterial;
 
  switch ( hObject->d_xListOfElementsTypes[xElementIndex] )
  {
    case GEO_C_xElementIndexedTriangles :
      p_stElementIndexedTriangles = (GEO_tdstElementIndexedTriangles *)(hObject->d_stListOfElements[xElementIndex]);
 
      /* points du triangle */
      for ( xPointIndex = 0 ; xPointIndex < 3 ; xPointIndex++ )
      {
        xGlobalPointIndex = (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[xPointIndex];
        GEO_vSetEdgeMaterial ( hObject, xGlobalPointIndex,
                               (p_stElementIndexedTriangles->d_stListOfFacesTripled + xDataElementIndex)->a3_xIndex[(xPointIndex+1)%3],
                               p_stElementIndexedTriangles->hMaterial );
        if (hObject->d_hListOfPointsMaterial)
			hObject->d_hListOfPointsMaterial[xGlobalPointIndex] = p_stElementIndexedTriangles->hMaterial;
      }
    break;
 
    case GEO_C_xElementFaceMapDescriptors :
      p_stElementFaceMapDescriptors = (GEO_tdstElementFaceMapDescriptors *)(hObject->d_stListOfElements[xElementIndex]);
 
      GEO_xGetFaceMapDescriptorGameMaterial ( (p_stElementFaceMapDescriptors->d_stListOfFacesQuadrupled + xDataElementIndex)->hFaceMapDescriptor,
                                              &hMaterial);
      /* points du triangle */
      for ( xPointIndex = 0 ; xPointIndex < 3 ; xPointIndex++ )
      {
        xGlobalPointIndex = (p_stElementFaceMapDescriptors->d_stListOfFacesQuadrupled + xDataElementIndex)->stFaceTripled.a3_xIndex[xPointIndex];
        GEO_vSetEdgeMaterial ( hObject, xGlobalPointIndex,
                               (p_stElementFaceMapDescriptors->d_stListOfFacesQuadrupled + xDataElementIndex)->stFaceTripled.a3_xIndex[(xPointIndex+1)%3],
                               hMaterial );
        if (hObject->d_hListOfPointsMaterial)
			hObject->d_hListOfPointsMaterial[xGlobalPointIndex] = hMaterial;
      }
    break;
 
    case GEO_C_xElementSpheres :
      p_stElementSpheres = (GEO_tdstElementSpheres *)(hObject->d_stListOfElements[xElementIndex]);
 
      /* sphere */
      p_stIndexedSphere = p_stElementSpheres->d_stListOfSpheres + xDataElementIndex;
 
      /* centre de la sphere */
      xGlobalPointIndex = p_stIndexedSphere->xCenterPoint;
	  if (hObject->d_hListOfPointsMaterial)
		  hObject->d_hListOfPointsMaterial[xGlobalPointIndex] = p_stIndexedSphere->hMaterial;
    break;
 
    case GEO_C_xElementAlignedBoxes :
      p_stElementAlignedBoxes = (GEO_tdstElementAlignedBoxes *)(hObject->d_stListOfElements[xElementIndex]);
 
      /* boite */
      p_stIndexedAlignedBox = p_stElementAlignedBoxes->d_stListOfAlignedBoxes + xDataElementIndex;
 
      /* points de la boite */
      xGlobalPointIndex = p_stIndexedAlignedBox->xMinPoint;
	  if (hObject->d_hListOfPointsMaterial)
		  hObject->d_hListOfPointsMaterial[xGlobalPointIndex] = p_stIndexedAlignedBox->hMaterial;
      xGlobalPointIndex = p_stIndexedAlignedBox->xMaxPoint;
	  if (hObject->d_hListOfPointsMaterial)
		  hObject->d_hListOfPointsMaterial[xGlobalPointIndex] = p_stIndexedAlignedBox->hMaterial;
      GEO_vSetEdgeMaterial ( hObject, p_stIndexedAlignedBox->xMinPoint,
                             xGlobalPointIndex,
                             p_stIndexedAlignedBox->hMaterial );
    break;
 
    case GEO_C_xElementPoints :
      p_stElementPoints = (GEO_tdstElementPoints *)(hObject->d_stListOfElements[xElementIndex]);
 
      xGlobalPointIndex = p_stElementPoints->d_xListOfPointIndex[xDataElementIndex];
	  if (hObject->d_hListOfPointsMaterial)
		  hObject->d_hListOfPointsMaterial[xGlobalPointIndex] = p_stElementPoints->hMaterial;
    break;
 
    case GEO_C_xElementLines :
      p_stElementLines = (GEO_tdstElementLines *)(hObject->d_stListOfElements[xElementIndex]);
 
      /* points de la ligne */
      xGlobalPointIndex = (p_stElementLines->d_stListOfLineIndex + xDataElementIndex)->a2_xIndex[0];
	  if (hObject->d_hListOfPointsMaterial)
		  hObject->d_hListOfPointsMaterial[xGlobalPointIndex] = p_stElementLines->d_hListOfLinesMaterial[xDataElementIndex];
      xGlobalPointIndex = (p_stElementLines->d_stListOfLineIndex + xDataElementIndex)->a2_xIndex[1];
	  if (hObject->d_hListOfPointsMaterial)
		  hObject->d_hListOfPointsMaterial[xGlobalPointIndex] = p_stElementLines->d_hListOfLinesMaterial[xDataElementIndex];
      GEO_vSetEdgeMaterial ( hObject, (p_stElementLines->d_stListOfLineIndex + xDataElementIndex)->a2_xIndex[0],
                             xGlobalPointIndex,
                             p_stElementLines->d_hListOfLinesMaterial[xDataElementIndex] );
    break;
 
    default :
    break;
  }
}
 
/*------------------------------------------------------------------
 * Well, this function will make one Geometric Object from a table
 * of Geometric Objects.
 * For now on, deals only with spheres, boxes, points and cones.
 *------------------------------------------------------------------*/
void GEO_fn_vClearObjectForGAM(ACP_tdxHandleOfObject _hGeoObj)
{
   ACP_tdxIndex xIndex;
 
   _hGeoObj->xNbPoints = 0;
   for( xIndex=0; xIndex<_hGeoObj->xNbElements; xIndex++ )
   {
      switch( GEO_xGetElementType(_hGeoObj,xIndex) )
      {
      case GEO_C_xElementIndexedTriangles:
         break;
      case GEO_C_xElementSpheres:
         ((GEO_tdstElementSpheres *)(_hGeoObj->d_stListOfElements[xIndex]))->xNbSpheres = 0;
         break;
      case GEO_C_xElementAlignedBoxes:
         ((GEO_tdstElementAlignedBoxes *)(_hGeoObj->d_stListOfElements[xIndex]))->xNbAlignedBoxes = 0;
         break;
      case GEO_C_xElementCones:
         ((GEO_tdstElementCones *)(_hGeoObj->d_stListOfElements[xIndex]))->xNbCones = 0;
         break;
      case GEO_C_xElementNULL:
         break;
      case GEO_C_xElementFaceMapDescriptors:
         break;
      case GEO_C_xElementSprites:
         break;
      case GEO_C_xElementTMeshes:
         break;
      case GEO_C_xElementPoints:
         ((GEO_tdstElementPoints *)(_hGeoObj->d_stListOfElements[xIndex]))->xNbPoints = 0;
         break;
      case GEO_C_xElementLines:
         break;
      default:
         break;
      }
   }
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
ACP_tdxHandleOfObject GEO_fn_hTransformTableOfObjectInOneObjectForGAM(
   ACP_tdxHandleOfObject _hGeoObj,
   ACP_tdxHandleOfObject * a_hTableOfGeoObj,
   ACP_tdxIndex xNbOfgEOoBJ)
{
    ACP_tdxIndex                        xNbPoints,xNbP;
    GEO_tdstElementPoints               * p_stEPSource,* p_stEPTarget;
    ACP_tdxIndex                        * p_xIPSource ,* p_xIPTarget, *p_xIPSourceEnd;
    GEO_tdstElementSpheres              * p_stESSource,* p_stESTarget;
    GEO_tdstIndexedSphere               * p_stISSource,* p_stISTarget, *p_stISSourceEnd;
    GEO_tdstElementAlignedBoxes         * p_stEBSource,* p_stEBTarget;
    GEO_tdstIndexedAlignedBox           * p_stIBSource,* p_stIBTarget, *p_stIBSourceEnd;
    GEO_tdstElementCones                * p_stECSource,* p_stECTarget;
    GEO_tdstIndexedCone                 * p_stICSource,* p_stICTarget, *p_stICSourceEnd;
    ACP_tdxHandleOfObject               *p_hGeoObjInTableAtIndex, *p_hGeoObjInTableEnd;
    void                                **p_hCurrentElementTarget, **p_hCurrentElementTargetEnd;
    ACP_tdxIndex                        xNbSubElt, *p_xCurrentElementTypeTarget;
    unsigned long                       ulSize, ulSizeVector, ulSizeCone, ulSizeSphere, ulSizeBox;
 
    p_hCurrentElementTarget = _hGeoObj->d_stListOfElements;
    p_stESSource    = (GEO_tdstElementSpheres *)*p_hCurrentElementTarget++;
    p_stEBSource    = (GEO_tdstElementAlignedBoxes *)*p_hCurrentElementTarget++;
    p_stECSource    = (GEO_tdstElementCones *)*p_hCurrentElementTarget++;
    p_stEPSource    = (GEO_tdstElementPoints *)*p_hCurrentElementTarget;
 
    p_stISSource    = p_stESSource -> d_stListOfSpheres;
    p_stIBSource    = p_stEBSource -> d_stListOfAlignedBoxes;
    p_stICSource    = p_stECSource -> d_stListOfCones;
    p_xIPSource     = p_stEPSource -> d_xListOfPointIndex;
 
    xNbPoints       = 0;
    p_stESSource -> xNbSpheres      = 0;
    p_stEBSource -> xNbAlignedBoxes = 0;
    p_stECSource -> xNbCones        = 0;
    p_stEPSource -> xNbPoints       = 0;
 
    ulSizeVector = sizeof(MTH3D_tdstVector);
    ulSizeSphere = sizeof( GEO_tdstIndexedSphere );
    ulSizeCone   = sizeof( GEO_tdstIndexedCone);
    ulSizeBox    = sizeof( GEO_tdstIndexedAlignedBox );
 
    p_hGeoObjInTableAtIndex = a_hTableOfGeoObj;
    p_hGeoObjInTableEnd     = p_hGeoObjInTableAtIndex + xNbOfgEOoBJ;
    for( ; p_hGeoObjInTableAtIndex < p_hGeoObjInTableEnd ; p_hGeoObjInTableAtIndex++ )
	{
        xNbP = ( *p_hGeoObjInTableAtIndex ) -> xNbPoints;
        ulSize = ulSizeVector * xNbP;
		if(ulSize!=0) /* for u64, geometric objects can have 0 acp points*/
		{
        memcpy( _hGeoObj -> d_stListOfPoints + xNbPoints,        (*p_hGeoObjInTableAtIndex) -> d_stListOfPoints,        ulSize );
        memcpy( _hGeoObj -> d_stListOfPointsNormals + xNbPoints, (*p_hGeoObjInTableAtIndex) -> d_stListOfPointsNormals, ulSize );
 
		/* Elements*/
        p_hCurrentElementTarget     = (*p_hGeoObjInTableAtIndex)->d_stListOfElements;
        p_hCurrentElementTargetEnd  = p_hCurrentElementTarget + (ACP_tdxIndex)((*p_hGeoObjInTableAtIndex) -> xNbElements);
        p_xCurrentElementTypeTarget = (*p_hGeoObjInTableAtIndex)->d_xListOfElementsTypes;
 
        for( ; p_hCurrentElementTarget < p_hCurrentElementTargetEnd ; p_hCurrentElementTarget++,p_xCurrentElementTypeTarget++ )
		{
            switch( *p_xCurrentElementTypeTarget )
			{
			case GEO_C_xElementSpheres:
				p_stESTarget = (GEO_tdstElementSpheres*)*p_hCurrentElementTarget;
                p_stISTarget = ((GEO_tdstElementSpheres*)*p_hCurrentElementTarget) -> d_stListOfSpheres;
                xNbSubElt    = ((GEO_tdstElementSpheres*)*p_hCurrentElementTarget) -> xNbSpheres;
                memcpy( p_stISSource, p_stISTarget, ulSizeSphere * xNbSubElt );
                if( xNbPoints )
                {
                    p_stISSourceEnd = p_stISSource + xNbSubElt;
                    for( ; p_stISSource < p_stISSourceEnd ; p_stISSource++ )
                    {
                        p_stISSource -> xCenterPoint += xNbPoints;
                    }
                }
                else
                {
                    p_stISSource += xNbSubElt;
                }
                p_stESSource -> xNbSpheres += xNbSubElt;
				break;
 
			case GEO_C_xElementAlignedBoxes:
				p_stEBTarget = (GEO_tdstElementAlignedBoxes *)*p_hCurrentElementTarget;
                p_stIBTarget = ((GEO_tdstElementAlignedBoxes *)*p_hCurrentElementTarget) -> d_stListOfAlignedBoxes;
                xNbSubElt    = ((GEO_tdstElementAlignedBoxes *)*p_hCurrentElementTarget) -> xNbAlignedBoxes;
                memcpy( p_stIBSource, p_stIBTarget, ulSizeBox * xNbSubElt );
                if( xNbPoints )
                {
                    p_stIBSourceEnd = p_stIBSource + xNbSubElt;
                    for ( ; p_stIBSource < p_stIBSourceEnd ; p_stIBSource++ )
                    {
                        p_stIBSource -> xMinPoint += xNbPoints;
                        p_stIBSource -> xMaxPoint += xNbPoints;
                    }
                }
                else
                {
                    p_stIBSource += xNbSubElt;
                }
                p_stEBSource -> xNbAlignedBoxes += xNbSubElt;
				break;
 
			case GEO_C_xElementCones:
				p_stECTarget = (GEO_tdstElementCones *)*p_hCurrentElementTarget;
                p_stICTarget = ((GEO_tdstElementCones *)*p_hCurrentElementTarget) -> d_stListOfCones;
                xNbSubElt    = ((GEO_tdstElementCones *)*p_hCurrentElementTarget) -> xNbCones;
                memcpy( p_stICSource, p_stICTarget, ulSizeCone * xNbSubElt );
                if( xNbPoints )
                {
                    p_stICSourceEnd = p_stICSource + xNbSubElt;
                    for ( ; p_stICSource < p_stICSourceEnd ; p_stICSource++ )
                    {
                        p_stICSource -> xTopPoint   += xNbPoints;
                        p_stICSource -> xBasePoint  += xNbPoints;
                    }
                }
                else
                {
                    p_stICSource += xNbSubElt;
                }
                p_stECSource -> xNbCones += xNbSubElt;
				break;
 
			case GEO_C_xElementPoints:
                p_stEPTarget = ((GEO_tdstElementPoints *)*p_hCurrentElementTarget);
 
                p_stEPSource -> xFatness  = p_stEPTarget -> xFatness;
                p_stEPSource -> hMaterial = p_stEPTarget -> hMaterial;
 
                p_xIPTarget = p_stEPTarget -> d_xListOfPointIndex;
                xNbSubElt   = p_stEPTarget -> xNbPoints;
                p_xIPSourceEnd = p_xIPSource + xNbSubElt;
                for ( ; p_xIPSource < p_xIPSourceEnd ; p_xIPTarget++,p_xIPSource++ )
                {
                    *p_xIPSource = (*p_xIPTarget) + xNbPoints;
										if ( _hGeoObj->d_hListOfPointsMaterial )
                    _hGeoObj->d_hListOfPointsMaterial[ *p_xIPSource ] = p_stEPTarget -> hMaterial;
                }
                p_stEPSource -> xNbPoints += xNbSubElt;
				break;
 
                /* Nothing to do with the others types of elements*/
			}
 
		}
        xNbPoints += xNbP;
   }
   }
   _hGeoObj->xNbPoints = xNbPoints;
   /*GEO_vEndModifyObject( _hGeoObj );*/
   return _hGeoObj;
}
 
#ifndef _FIRE_DEADCODE_U64_
void GEO_fn_vMoveFaceToFaceDescriptors( ACP_tdxHandleOfObject p_stObj, ACP_tdxIndex xElementIT, ACP_tdxIndex xFaceIT, ACP_tdxIndex *p_xElementFMD, ACP_tdxIndex *p_xFaceFMD)
{
}
 
 
void GEO_fn_vMoveFaceDescriptorsToFace( ACP_tdxHandleOfObject p_stObj, ACP_tdxIndex xElementFMD, ACP_tdxIndex xFaceFMD, ACP_tdxIndex xElementIT, ACP_tdxIndex xFaceIT)
{
}
#endif /* _FIRE_DEADCODE_U64_ */
 
/*ANNECY CT 02/02/98{*/
/*-----------------------------------------------------------------------------
 *  Description :   Compute Surface Speed of a face (for scrolling texture)
 *-----------------------------------------------------------------------------
 *  Input :         Object which the surface belongs
 *					Index of the element of the object
 *					Index of the surface of the element
 *					vector to return speed
 *-----------------------------------------------------------------------------
 *  Creation date : 02/02/98            Author : Carlos Torres
 *---------------------------------------------------------------------------*/
void GEO_vGetFaceSurfaceSpeed(ACP_tdxHandleOfObject hObject,
							  ACP_tdxIndex xElement,
							  ACP_tdxIndex xFace,
							  MTH3D_tdstVector * p_vSpeed) {
	GEO_tdstElementIndexedTriangles * p_stElement;
	GEO_tdstTripledIndex * p_stListOfTripled;
	MTH3D_tdstVector * p_vA,* p_vB,* p_vC;
	ACP_tdst2DUVValues * p_uvA,* p_uvB,* p_uvC;
	long bScrollMode;
	MTH_tdxReal xUSpeed,xVSpeed;
	MTH2D_tdstVector vABCSpeed2D;
 
	/* init speed*/
	MTH3D_M_vNullVector(p_vSpeed);
 
	/* work only for indexed triangles*/
	if (hObject->d_xListOfElementsTypes[xElement] != GEO_C_xElementIndexedTriangles)
		return;
 
	/* get element*/
	p_stElement=hObject->d_stListOfElements[xElement];
 
	/* get speed*/
	GLI_xGetMaterialTextureScrollingCoef(
		GMT_fn_hGetVisualMaterial(p_stElement->hMaterial),
		0,	/* unuse param*/
		&bScrollMode,
		&xUSpeed ,
		&xVSpeed );
	/* change speed unity m/trame to m/s*/
	xUSpeed= MTH_M_xMul(MTH_M_xLongToReal(60),MTH_M_xNeg(xUSpeed));
	xVSpeed= MTH_M_xMul(MTH_M_xLongToReal(60),MTH_M_xNeg(xVSpeed));
 
	/* get points A, B and C xyz coordinates*/
    p_stListOfTripled = p_stElement->d_stListOfFacesTripled + xFace;
	p_vA = hObject->d_stListOfPoints + p_stListOfTripled->a3_xIndex[0];
	p_vB = hObject->d_stListOfPoints + p_stListOfTripled->a3_xIndex[1];
	p_vC = hObject->d_stListOfPoints + p_stListOfTripled->a3_xIndex[2];
	/* get points A, B and C uv coordinates*/
    p_stListOfTripled = p_stElement->d_stListOfFacesTripledIndexUV + xFace;
	p_uvA = p_stElement->d_stListOfElementUV + p_stListOfTripled->a3_xIndex[0];
	p_uvB = p_stElement->d_stListOfElementUV + p_stListOfTripled->a3_xIndex[1];
	p_uvC = p_stElement->d_stListOfElementUV + p_stListOfTripled->a3_xIndex[2];
 
 
	/*///////////////////////////////////////// 2D Speed*/
	{
		MTH2D_tdstMatrix mUVToABC,mABCToUV;
		MTH2D_tdstVector vUVSpeed,vAB,vAC;
 
		/* set Speed UV*/
		MTH2D_M_vSetVectorElements(&vUVSpeed,xUSpeed,xVSpeed);
		/* set vectors AB et AC*/
		MTH2D_M_vSetVectorElements(&vAB,p_uvB->xU-p_uvA->xU,p_uvB->xV-p_uvA->xV);
		MTH2D_M_vSetVectorElements(&vAC,p_uvC->xU-p_uvA->xU,p_uvC->xV-p_uvA->xV);
		/* set changement matrice UV -> ABC*/
		MTH2D_M_vSetVectorsInMatrix(&mABCToUV,&vAB,&vAC);
		MTH2D_M_vInverMatrix(&mUVToABC,&mABCToUV);
		/* compute Speed ABC 2D*/
		MTH2D_M_vMulMatrixVectorWithoutBuffer(&vABCSpeed2D,&mUVToABC,&vUVSpeed);
	}
 
	/*///////////////////////////////////////// 3D Speed*/
	{
		MTH3D_tdstMatrix mABCToXYZ;
		MTH3D_tdstVector vABCSpeed3D,vAB,vAC,vN;
 
		/* set Speed ABC 3D*/
		MTH3D_M_vSetVectorElements(&vABCSpeed3D,MTH2D_M_xGetXofVector(&vABCSpeed2D),MTH2D_M_xGetYofVector(&vABCSpeed2D),MTH_C_ZERO);
		/* set vectors AB et AC and useless normal*/
		MTH3D_M_vSubVector(&vAB,p_vB,p_vA);
		MTH3D_M_vSubVector(&vAC,p_vC,p_vA);
		MTH3D_M_vNullVector(&vN);
		/* set changement matrice ABC -> XYZ*/
		MTH3D_M_vSetVectorsInMatrix(&mABCToXYZ,&vAB,&vAC,&vN);
		/* compute Speed ABC in XYZ*/
		MTH3D_M_vMulMatrixVectorWithoutBuffer(p_vSpeed,&mABCToXYZ,&vABCSpeed3D);
	}
 
}
/*ENDANNECY CT}*/
 
/*ANNECY MT 20/02/98 {*/
/*-----------------------------------------------------------------------------
 *  Description :   Allocate the list of parallel boxes
 *-----------------------------------------------------------------------------
 *  Input :         Object
 *-----------------------------------------------------------------------------
 *  Creation date : 20/02/98            Author : Marc Trabucato
 *---------------------------------------------------------------------------*/
void GEO_vCreateObjectListOfParallelBox( ACP_tdxHandleOfObject hObject, ACP_tdxIndex xNumberOfParallelBoxes )
{
  ACP_tdxIndex xIndex;
 
  hObject -> xNbParallelBoxes = xNumberOfParallelBoxes;
 
  if ( hObject -> xNbParallelBoxes == 0 )
    return;
 
  if ( hObject -> d_stListOfParallelBoxes != NULL )
    return;
 
  MMG_fn_vAddMemoryInfo( MMG_C_lTypeGeometricObject , MMG_C_lSubTypeParallelBox , 0 );
 
 
  GEO_M_CPAMalloc ( hObject -> d_stListOfParallelBoxes,
                    GEO_tdstParallelBox *,
                    sizeof(GEO_tdstParallelBox) * hObject -> xNbParallelBoxes,
                    E_uwGEONotEnoughtMemory );
 
  for ( xIndex = 0 ; xIndex < hObject -> xNbParallelBoxes ; xIndex ++ )
  {
	  MTH3D_M_vFillVector( & ( hObject -> d_stListOfParallelBoxes [ xIndex ] . stMinPoint ), MTH_C_InfinitPlus  );
	  MTH3D_M_vFillVector( & ( hObject -> d_stListOfParallelBoxes [ xIndex ] . stMaxPoint ), MTH_C_InfinitMinus );
  }
}
 
/*-----------------------------------------------------------------------------
 *  Description :   Compute the list of parallel boxes
 *-----------------------------------------------------------------------------
 *  Input :         Object
 *-----------------------------------------------------------------------------
 *  Creation date : 20/02/98            Author : Marc Trabucato
 *---------------------------------------------------------------------------*/
void GEO_vComputeObjectListOfParallelBox( ACP_tdxHandleOfObject hObject )
{
  ACP_tdxIndex xIndex;
 
  if ( hObject -> xNbParallelBoxes == 0 )
    return;
 
  if ( hObject -> d_stListOfParallelBoxes == NULL )
    GEO_vCreateObjectListOfParallelBox( hObject , hObject -> xNbParallelBoxes );
 
  for ( xIndex = 0 ; xIndex < hObject -> xNbParallelBoxes ; xIndex ++ )
  {
	  GEO_vComputeObjectParallelBox( hObject, xIndex );
  }
}
 
/*-----------------------------------------------------------------------------
 *  Description :   Return the number of Parallel boxes in the object
 *-----------------------------------------------------------------------------
 *  Input :         Object
 *-----------------------------------------------------------------------------
 *	Output:			the number of Parallel boxes in the object
 *-----------------------------------------------------------------------------
 *  Creation date : 20/02/98            Author : Marc Trabucato
 *---------------------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
ACP_tdxIndex GEO_xGetGeometricObjectNumberOfParallelBox( ACP_tdxHandleOfObject hObject )
{
	return hObject -> xNbParallelBoxes;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/*-----------------------------------------------------------------------------
 *  Description :   Return the nth Parallel boxe in the object
 *-----------------------------------------------------------------------------
 *  Input :         Object
 *					the index of the wanted parallel box
 *-----------------------------------------------------------------------------
 *	Output:			an handle of Parallel boxes, or NULL
 *-----------------------------------------------------------------------------
 *  Creation date : 20/02/98            Author : Marc Trabucato
 *---------------------------------------------------------------------------*/
GEO_tdxHandleToParallelBox GEO_hGetParallelBox( ACP_tdxHandleOfObject hObject, ACP_tdxIndex xParallelBox )
{
	if( xParallelBox < hObject -> xNbParallelBoxes )
		return hObject -> d_stListOfParallelBoxes + xParallelBox;
	else
		return NULL;
}
 
/*-----------------------------------------------------------------------------
 *  Description :   Return the index of th Parallel boxe of the nth element of the object
 *-----------------------------------------------------------------------------
 *  Input :         Object
 *					the index of the wanted element
 *-----------------------------------------------------------------------------
 *	Output:			an index of Parallel boxes, or GEO_C_xNoParallelBox
 *-----------------------------------------------------------------------------
 *  Creation date : 20/02/98            Author : Marc Trabucato
 *---------------------------------------------------------------------------*/
ACP_tdxIndex GEO_xGetParallelBoxIndexOfElement( ACP_tdxHandleOfObject hObject, ACP_tdxIndex xIndexElement )
{
    switch ( hObject -> d_xListOfElementsTypes[ xIndexElement ] )
    {
    case GEO_C_xElementIndexedTriangles:
        return ((GEO_tdstElementIndexedTriangles*)   ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox;
        break;
//XB99/04/27
#ifndef U64
    case GEO_C_xElementFaceMapDescriptors:
        return ((GEO_tdstElementFaceMapDescriptors*) ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox;
        break;
#endif U64
//End XB99/04/27
    case GEO_C_xElementSprites:
		return ((GEO_tdstElementSprite*)			 ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox;
        break;
//XB99/04/27
#ifndef U64
    case GEO_C_xElementTMeshes:
		return ((GEO_tdstElementTMeshes*)			 ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox;
        break;
#endif U64
//End XB99/04/27
    case GEO_C_xElementPoints:
        return ((GEO_tdstElementPoints*)			 ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox;
        break;
    case GEO_C_xElementLines:
        return ((GEO_tdstElementLines*)				 ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox;
        break;
    case GEO_C_xElementSpheres:
        return ((GEO_tdstElementSpheres*)			 ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox;
        break;
    case GEO_C_xElementAlignedBoxes:
        return ((GEO_tdstElementAlignedBoxes*)		 ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox;
        break;
    case GEO_C_xElementCones:
        return ((GEO_tdstElementCones*)				 ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox;
        break;
//XB99/04/27
#ifndef U64
    case GEO_C_xElementAltimap:
		return GEO_C_xNoParallelBox;
        break;
#endif U64
//End XB99/04/27
	default:
		return GEO_C_xNoParallelBox;
    }
}
 
/*-----------------------------------------------------------------------------
 *  Description :   Set the index of th Parallel boxe of the nth element of the object
 *-----------------------------------------------------------------------------
 *  Input :         Object
 *					the index of the wanted element
 *-----------------------------------------------------------------------------
 *  Creation date : 20/02/98            Author : Marc Trabucato
 *---------------------------------------------------------------------------*/
void GEO_vSetParallelBoxIndexOfElement( ACP_tdxHandleOfObject hObject, ACP_tdxIndex xIndexElement, ACP_tdxIndex xIndexOfParallelBox )
{
    switch ( hObject -> d_xListOfElementsTypes[ xIndexElement ] )
    {
    case GEO_C_xElementIndexedTriangles:
        ((GEO_tdstElementIndexedTriangles*)   ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox = xIndexOfParallelBox;
        break;
//XB99/04/27
#ifndef U64
    case GEO_C_xElementFaceMapDescriptors:
        ((GEO_tdstElementFaceMapDescriptors*) ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox = xIndexOfParallelBox;
        break;
#endif U64
//End XB99/04/27
    case GEO_C_xElementSprites:
		((GEO_tdstElementSprite*)			  ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox = xIndexOfParallelBox;
        break;
//XB99/04/27
#ifndef U64
    case GEO_C_xElementTMeshes:
		((GEO_tdstElementTMeshes*)			  ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox = xIndexOfParallelBox;
        break;
#endif U64
//End XB99/04/27
    case GEO_C_xElementPoints:
        ((GEO_tdstElementPoints*)			  ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox = xIndexOfParallelBox;
        break;
    case GEO_C_xElementLines:
        ((GEO_tdstElementLines*)			  ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox = xIndexOfParallelBox;
        break;
    case GEO_C_xElementSpheres:
        ((GEO_tdstElementSpheres*)			  ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox = xIndexOfParallelBox;
        break;
    case GEO_C_xElementAlignedBoxes:
        ((GEO_tdstElementAlignedBoxes*)		  ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox = xIndexOfParallelBox;
        break;
    case GEO_C_xElementCones:
        ((GEO_tdstElementCones*)			  ( hObject -> d_stListOfElements[ xIndexElement ] )) -> xIndexOfParallelBox = xIndexOfParallelBox;
        break;
//XB99/04/27
#ifndef U64
    case GEO_C_xElementAltimap:
        break;
#endif U64
//End XB99/04/27
    }
}
 
 
 
/*-----------------------------------------------------------------------------
 *  Description :   Compute given bounding volume
 *-----------------------------------------------------------------------------
 *  Input :         an object
 *                  the index of bounding volume to compute
 *-----------------------------------------------------------------------------
 *  Creation date : 20/02/98            Author : Marc Trabucato
 *---------------------------------------------------------------------------*/
/*Move in GeoObj2.c because gcc -O2 crash*/
 
 
 

#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC 04/06/99 */
ACP_tdxBool GEO_bIsLookAt (GEO_tdstGeometricObject *p_stObj) {
  return ( (ACP_tdxBool)p_stObj->ulType ) ;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC 04/06/99 */

 
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void GEO_vTurnLookAt ( GEO_tdstGeometricObject *p_stObj, 
                       GLD_tdxHandleToViewportAttributes hVpt, 
                       struct POS_stCompletePosition *p_stCurrentMatrix) {
  GLI_tdstCamera             *p_stCam ;
  POS_tdstCompletePosition   hCameraPosInv ;
  MTH3D_tdstVector           stX, stY, stZ ;
  MTH_tdxReal                xNorme ;
 
  p_stCam = (( GLI_tdstSpecificAttributesFor3D *)hVpt->p_vSpecificToXD)->p_stCam ;
  POS_fn_vInvertIsoMatrix( &hCameraPosInv, &(p_stCam->stMatrix) );
 
  stX.xX = hCameraPosInv.stTranslationVector.xX - p_stCurrentMatrix->stTranslationVector.xX ;
  stX.xY = hCameraPosInv.stTranslationVector.xY - p_stCurrentMatrix->stTranslationVector.xY ;
  stX.xZ = hCameraPosInv.stTranslationVector.xZ - p_stCurrentMatrix->stTranslationVector.xZ ;
  MTH3D_M_vNormalizeVector(&stX, &stX) ;
 
  /* STM - avoid using the rotation matrix - it might disappear*/
  if ( p_stObj->ulType & GEO_C_SemiLookAt ) {
	POS_fn_vGetRotationMatrixCol2(p_stCurrentMatrix, &stZ);
    /* stZ.xX = p_stCurrentMatrix->stRotationMatrix.stCol_2.xX ;*/
    /* stZ.xY = p_stCurrentMatrix->stRotationMatrix.stCol_2.xY ;*/
    /* stZ.xZ = p_stCurrentMatrix->stRotationMatrix.stCol_2.xZ ;*/
  }
  else { 
    stZ.xX = hCameraPosInv.stTransformMatrix.stCol_1.xX ;
    stZ.xY = hCameraPosInv.stTransformMatrix.stCol_1.xY ;
    stZ.xZ = hCameraPosInv.stTransformMatrix.stCol_1.xZ ;
  }
 
  MTH3D_M_vCrossProductVectorWithoutBuffer ( &stY, &stZ, &stX ) ;
  xNorme = MTH3D_M_xNormVector (&stY) ;
  if ( xNorme > 0 ){
    MTH3D_M_vNormalizeVector(&stY, &stY) ;
    MTH3D_M_vCrossProductVectorWithoutBuffer ( &stX, &stY, &stZ ) ;
    POS_fn_vSetRotationMatrix ( p_stCurrentMatrix, &stX, &stY, &stZ ) ;
  }
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
