/*
Tested with LINT
*/
#include <assert.h>
 
/*#include "gli_st.h"
#include "GLI_Defn.h"
#include "light_st.h"
#include "PvObj_st.h"
#include "watrplan.h"
 
  #include "COL.h"
  
    #include "gmt.h"
    
#include "camera.h"*/
#include"gli_st.h"
#include "GLI_Defn.h"
#include "vertex.h"
#include "light_st.h"
#include "PvObj_st.h"
#include "watrplan.h"
#include "camera.h"
#include "matstack.h"
#include "COL.h"
 
#include "gmt.h"
#include "GliBench.h"
 
#define GLI_TSINTA 64
float a64_fSinTable[128];
extern long GLD_RenderingCounter;
long gs_lXBase;
long gs_lYBase;
static float GLI_fF2pow24;
static float GLI_fSinEffectBase ;
static float GLI_gsWaterPlaneRefraction = 0.6f;
static float GLI_gsWaterPlaneDepthSizeOf2DMove = 2.0f;
static float GLI_gsWaterPlaneDepthStartOf2DMove = -1.0f;
 
long bWaterPlaneState;
MTH3D_tdstVector stWaterPlaneNormale;
MTH_tdxReal fWaterPlaneDistance;
MTH_tdxReal GLI_gsfWaterPlaneFogStart = 2.0f;
GLI_tdstColor GLI_gsfWaterPlaneFogColor ;
extern long TRYIT;  
extern GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BIG_GLOBALS;
/*#ifdef KAMUI
#include <KAMUI.h>
extern  KMVERTEXBUFFDESC	VertexBufferDesc;
#endif*/
void  GLI_vWaitEndOfRendering();
void GLI_vWaitEndOfVertexTransfert();
void GLI_vWaitEndOfVSync();
 
/*ANNECY VL04/03/98{*/
/*
 * var for sinus effect
 */
MTH_tdxReal			a3_xSinEffectBase[3];
long				a3_lSinEffectFreq[3];
MTH3D_tdstVector	stSinEffectAmp;
MTH3D_tdstVector	stSinEffectVector;
MTH_tdxReal			xSinusEffectDepthStart;
char				g_cSinusEffectState;
char				g_cSinusEffectFlag;
 
/*
 * saved sinus parameter
 */
MTH_tdxReal			a3_xSinEffectBaseSaved[3];
long				a3_lSinEffectFreqSaved[3];
MTH3D_tdstVector	stSinEffectAmpSaved;
MTH3D_tdstVector	stSinEffectVectorSaved;
MTH_tdxReal			xSinusEffectDepthStartSaved;
char				g_cSinusEffectStateSaved;
char				g_cSinusEffectFlagSaved;
 
 
 
MTH_tdxReal a3_lSinRLIBase[3] ;  /* 0->red ; 1->green ; 2->blue */
MTH_tdxReal a3_lSinRLIAmp[3] ;   /* 0->red ; 1->green ; 2->blue */
/*ENDANNECY VL}*/
 
 
void GLI_xSetMaterialType ( ACP_tdxHandleOfMaterial  hMaterial, unsigned long xMType) ;
void GLI_xSetMaterialAmbientCoef ( ACP_tdxHandleOfMaterial hMaterial, struct GEO_tdstColor_ *p_stColor ) ;
void GLI_xSetMaterialDiffuseCoef ( ACP_tdxHandleOfMaterial hMaterial, struct GEO_tdstColor_ *p_stColor ) ;
 
 
/**********************************************************************************************/
/* Name: GLI_WaterBresenheim*/
/* Goal : Draw a line in a buffer*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : */
/**********************************************************************************************/
void GLI_WaterBresenheim(short *TABLEA , short *TABLEB , long X1 , long X2 , long Y1 , long Y2 , short color , long SizeInPowerOf2 )
{
    long DX,DY,counter;
    long size;
    float BaseX,BaseY,incX,incY;
    X1 += 65536;
    X2 += 65536;
    Y1 += 65536;
    Y2 += 65536;
    if (X1 > X2 )
    {
        DX = X1 ; X1 = X2 ; X2 = DX ; DY = Y1 ; Y1 = Y2 ; Y2 = DY;
    }
    DX = X2 - X1 ;
    DY = Y2 - Y1 ;
    size = (1<<SizeInPowerOf2)-1;
    if (DX == 0)
    {
        if (DY == 0) return;
        TABLEA += (X1 & size) ;
        TABLEB += (X1 & size) ;
        if (DY < 0)
        {
            DY = -DY;
            Y1 = Y2;
        }
        while (DY--)
        {
            *(TABLEA + ((Y1  & size) << SizeInPowerOf2)) = color;
            *(TABLEB + (((Y1++)  & size) << SizeInPowerOf2)) = color;
        } 
        return;
    }
    if (DY == 0)
    {
        TABLEA += (Y1 & size) << SizeInPowerOf2;
        TABLEB += (Y1 & size) << SizeInPowerOf2;
        while (DX--)
        {
            *(TABLEA + ((X1) & size)) = color;
            *(TABLEB + ((X1++) & size)) = color;
        }
        return;
    }
 
    if (DY < 0)
    {
        if (-DY > DX)
            counter = -DY;
        else
            counter = DX;
    }
    else
    {
        if (DY > DX)
            counter = DY;
        else
            counter = DX;
    }
    incX = 1.0f / ((float)counter ) ;
    incY = DY * incX;
    incX = DX * incX;
    BaseX = (float)X1 ;
    BaseY = (float)Y1 ;
 
    while (counter--)
    {
        *(float *)&DX = BaseX + 65536.0f * 128.0f ;
        *(float *)&DY = BaseY + 65536.0f * 128.0f ;
        DY &= size;
        DX = (DX & size)  + ( DY <<SizeInPowerOf2);
        *( TABLEA + DX ) = color;
        *( TABLEB + DX ) = color;
        BaseX += incX;
        BaseY += incY;
    }
}
#define WATERSIZE 256L
#define WATERDEC 8L
#define WATERWAVELGHT 1L
short WATERTEXTURES[WATERSIZE*WATERSIZE*2 + WATERSIZE * (4L)];
unsigned short WATERTEXTURESPROTO[WATERSIZE*WATERSIZE * 4 ];
extern short VignetteBuffer[1024L * 1024L];
 
void GLI_SPECIALMEMCPY(unsigned short *p_DST , unsigned short *p_SRC , short *p_SPECIAL , unsigned long offset) 
{
    unsigned long size;
long DEC;
    unsigned short *p_DSTLAST;
    short *p_SPECIALLOCAL;
    size = 0xFFFF + offset;
    p_DSTLAST = p_DST + WATERSIZE * (WATERSIZE - WATERWAVELGHT);
    p_SPECIALLOCAL = p_SPECIAL;
    while (p_DST < p_DSTLAST)
    {
        DEC = 0xFFFF + (*(p_SPECIAL) - *(p_SPECIAL + WATERWAVELGHT) >> 4);
        DEC += ((*(p_SPECIAL) - *(p_SPECIAL + (WATERWAVELGHT * WATERSIZE))) << (4)) & (0xFFFFFFFF<<WATERDEC) ;
        *(p_DST++) =  *((p_SRC) + (((size++) + DEC) & (WATERSIZE * WATERSIZE - 1) ));
        p_SPECIAL++;
    }
    p_DSTLAST = p_DST + WATERSIZE * (WATERWAVELGHT);
    while (p_DST < p_DSTLAST)
    {
        DEC = 0xFFFF + (*(p_SPECIAL) - *(p_SPECIAL + WATERWAVELGHT) >> 4);
        DEC += ((*(p_SPECIAL) - *(p_SPECIALLOCAL + (WATERWAVELGHT * WATERSIZE))) << (4)) & (0xFFFFFFFF<<WATERDEC) ;
        *(p_DST++) =  *((p_SRC) + (((size++) + DEC) & (WATERSIZE * WATERSIZE - 1) ));
        p_SPECIAL++;
        p_SPECIALLOCAL++;
    }
    /*        *(p_DST++) =  (*(p_SPECIAL++) >> 2 ) | 0xf000;*/
}
 
void GLI_LineWaterNoise(GLI_tdstAligned3DVector *P1,GLI_tdstAligned3DVector *P2)
{
    long X1,X2,Y1,Y2;
    X1 = (long)(P1->xX * WATERSIZE);
    X2 = (long)(P2->xX * WATERSIZE);
    Y1 = (long)(P1->xZ * WATERSIZE);
    Y2 = (long)(P2->xZ * WATERSIZE);
    GLI_WaterBresenheim(WATERTEXTURES + WATERSIZE, WATERTEXTURES + WATERSIZE * 3L + WATERSIZE * WATERSIZE, X1 , X2 , Y1 , Y2 , 0x400, WATERDEC  );
}
 
void GLD_vWrite16bBitmapToBackBuffer_flotte (void)
{
#ifdef ZGLARRRRRRRRGL
    GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT;
    static bFirst1 = 0;
    static short offset;
    short *p_mem1,*p_mem2 , *p_memLast;
    
    if (!(TRYIT & (1<<7))) return;
    p_stGlobaleMT = GLI_BIG_GLOBALS;
    
    bFirst1++;
    /* ------------------    ALGOTEX.C    ------------------*/
    if (bFirst1 == 1)
    {
        unsigned char aDEF_ucReadBuffer[256L*4L];
        FILE *p_stTextureFile;
        unsigned long lWidth,lHeight,lConvert;
        unsigned short *p_usConvert;
        unsigned long *p_ulConvert;
        p_stTextureFile=fopen("PLOUF.tga","rb");
        if (p_stTextureFile==NULL)
            return ;
        fread(aDEF_ucReadBuffer,18,1,p_stTextureFile);
        lWidth=(aDEF_ucReadBuffer[13]<<8) + aDEF_ucReadBuffer[12];
        lHeight=(aDEF_ucReadBuffer[15]<<8) + aDEF_ucReadBuffer[14];
        
        if (aDEF_ucReadBuffer[0] != 0)
            fread(aDEF_ucReadBuffer,aDEF_ucReadBuffer[0],1,p_stTextureFile);
        fread((void*)WATERTEXTURESPROTO,4,lWidth*lHeight,p_stTextureFile);
        /* convert in 16 bits */
        p_usConvert = WATERTEXTURESPROTO;
        p_ulConvert = WATERTEXTURESPROTO;
        lConvert = lHeight * lHeight ;
        while (lConvert--)
            *(p_usConvert++) = ((*(p_ulConvert) & 0xf0000000)>> 16) + ((*(p_ulConvert) & 0x00f00000)>> 12) + ((*(p_ulConvert) & 0x0000f000)>> 8) + ((*(p_ulConvert++) & 0x000000f0)>> 4) ;
        memset(WATERTEXTURES,0 , WATERSIZE * WATERSIZE * 2L * 2L);
    }
    if (bFirst1 & 1)
    {
        p_mem1 = WATERTEXTURES + WATERSIZE * WATERSIZE + WATERSIZE * 3L;
        p_mem2 = WATERTEXTURES + WATERSIZE;
    }else
    {
        p_mem1 = WATERTEXTURES + WATERSIZE;
        p_mem2 = WATERTEXTURES + WATERSIZE * WATERSIZE + WATERSIZE * 3L;
    }
    p_memLast = p_mem1+WATERSIZE*WATERSIZE;
    while (p_mem1 < p_memLast)
    {
        *p_mem1 = ((*(p_mem2 + WATERSIZE) + *(p_mem2 - WATERSIZE) + *(p_mem2 + 1) + *(p_mem2 - 1))>>2) - *p_mem1 + *(p_mem2);
        *p_mem1 -= (*p_mem1)>>7;
        p_mem1++;
        p_mem2++;
    }
 
    if (bFirst1 & 1)
    {
        p_mem2 = WATERTEXTURES + WATERSIZE;
    }else
    {
        p_mem2 = WATERTEXTURES + WATERSIZE * WATERSIZE + WATERSIZE * 3L;
    }
    GLI_SPECIALMEMCPY(VignetteBuffer , WATERTEXTURESPROTO , p_mem2  , 0 ) ;
    /* ------------------   ALGOTEX.C  ------------------*/
 
    /* ----------------     TEX     -------------------*/
/*#ifdef KAMUI
    GLI_fnSwitchTwiddled((VignetteBuffer ), WATERSIZE);
    GLI_vWaitEndOfVertexTransfert();
    GLI_vWaitEndOfRendering();
    kmLoadTexture(&stSpecialTexture20,(void *)(VignetteBuffer ),FALSE,FALSE);
#endif*/
    /* ----------------     TEX     -------------------*/
#endif
}
 
/**********************************************************************************************/
/* Name: GLI_vSetWaterplane*/
/* Goal : Set The Plane For Water Effect*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : */
/**********************************************************************************************/
void GLI_vSetWaterplane(struct GLD_tdstViewportAttributes_ *p_stVpt,
                        MTH3D_tdstVector *p_stNormale,
                        MTH_tdxReal xDistance)
{
    stWaterPlaneNormale = *p_stNormale;
    fWaterPlaneDistance = xDistance;
}
/**********************************************************************************************/
/* Name: GLI_vSetWaterplaneRefraction*/
/* Goal : 0.0f is nothing, 1.0f is maximum*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : */
/**********************************************************************************************/
void GLI_vSetWaterplane2DMoveSize(MTH_tdxReal xSizeInPixels)
{
    GLI_gsWaterPlaneDepthSizeOf2DMove = xSizeInPixels;
}
void GLI_vSetWaterplane2DMoveDepthStart(MTH_tdxReal xDepth)
{
    GLI_gsWaterPlaneDepthStartOf2DMove = xDepth;
}
/**********************************************************************************************/
/* Name: GLI_vSetWaterplaneRefraction*/
/* Goal : 0.0f is nothing, 1.0f is maximum*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : */
/**********************************************************************************************/
void GLI_vSetWaterplaneRefraction(MTH_tdxReal xRefraction)
{
    GLI_gsWaterPlaneRefraction = xRefraction;
}
/**********************************************************************************************/
/* Name: GLI_vSetWaterplaneOn*/
/* Goal : watrplane ON*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : */
/**********************************************************************************************/
void GLI_vSetWaterplaneOn()
{
    bWaterPlaneState |= GLI_C_l2DPlaneIsEnable;
}
/**********************************************************************************************/
/* Name: GLI_vSetWaterplaneOff*/
/* Goal : No watrplane*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : */
/**********************************************************************************************/
void GLI_vSetWaterplaneOff()
{
    bWaterPlaneState &= 0xffffffff - GLI_C_l2DPlaneIsEnable;
}
/**********************************************************************************************/
/* Name: GLI_vSetWaterplaneOff*/
/* Goal : No watrplane*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : */
/**********************************************************************************************/
void GLI_vWaterplaneEnableRefraction()
{
    bWaterPlaneState &= 0xffffffff - GLI_C_lWaterPlaneNoRefraction;
}
long GLI_vIsWaterplaneEnable(GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobalsParrameters)
{
    return ((bWaterPlaneState & GLI_C_l2DPlaneIsEnable));
}
void GLI_vWaterplaneDisableRefraction()
{
    bWaterPlaneState |= GLI_C_lWaterPlaneNoRefraction;
}
void GLI_vWaterplaneEnable2DSinus()
{
    bWaterPlaneState &= 0xffffffff - GLI_C_lWaterPlaneNoSinusMoves;
}
void GLI_vWaterplaneDisable2DSinus()
{
    bWaterPlaneState |= GLI_C_lWaterPlaneNoSinusMoves;
}
void GLI_vWaterplaneEnableFog()
{
    bWaterPlaneState &= 0xffffffff - GLI_C_lWaterPlaneNoFog ;
}
void GLI_vWaterplaneDisableFog()
{
    bWaterPlaneState |= GLI_C_lWaterPlaneNoFog ;
}
/**********************************************************************************************/
/* Name: GLI_v2DWaterPlaneEffect*/
/* Goal : move points in 2D for water effect.*/
/* Code: Philippe Vimont */
/* OPTIMMIZE : FINAL VERSION SHOULD BE IN ASSEMBLY*/
/**********************************************************************************************/
 
void
GLI_v2DWaterPlaneEffect(GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobalsParrameters,long xStart,long xNumber)
{
    long lVerticeX,lVerticeY;
    float *p_xCounter;
    float WaterPlaneDepthSizeOf2DMoveLocal;
    long lLocal2;
    GLI_tdstAligned3DVector *p_Vertex3D ;
    GLI_tdstAligned2DVector *p_Vertex2D , *p_Vertex2DEnd ;
    
    /* STM - this is tested before calling this function */
	/* if ((!(bWaterPlaneState & GLI_C_l2DPlaneIsEnable))) return;*/
    if  (GLI_C_lWaterPlaneNoSinusMoves & bWaterPlaneState) return;
    
    p_Vertex3D = p_stGlobalsParrameters->GLI_TurnedScaledDisplecedPoint + xStart;
    p_Vertex2D = p_stGlobalsParrameters->GLI_ScreenPoint + xStart;
    p_Vertex2DEnd = p_Vertex2D + xNumber;
    p_xCounter = p_stGlobalsParrameters->GLI_aDEF_xWaterPlaneDepth + xStart;
    gs_lXBase = GLD_RenderingCounter;
    WaterPlaneDepthSizeOf2DMoveLocal = (1.0f / GLI_gsWaterPlaneDepthStartOf2DMove) * GLI_gsWaterPlaneDepthSizeOf2DMove;
    
    
    if ((bWaterPlaneState & GLI_C_lWaterPlaneCameraIsInWater) != 0)
    {
        /* camera is under water -> sinusoidal moves are out of water.*/
        *((float *)&lLocal2) = -GLI_gsWaterPlaneDepthStartOf2DMove;
        for (;p_Vertex2D<p_Vertex2DEnd;p_Vertex2D++,p_Vertex3D ++,p_xCounter++)
            if (p_Vertex3D->xZ > GLI_C_xZClippingNear)
                if (*((long *)p_xCounter) > lLocal2 )
                {
                    /* 2 next lines:*/
                    /*lVerticeX = (long)p_Vertex2D->xX;*/
                    /*lVerticeY = (long)p_Vertex2D->xY;*/
                    /* is slower than.*/
                    *(float *)((void *)&lVerticeX) = p_Vertex2D->xX + GLI_fF2pow24; 
                    *(float *)((void *)&lVerticeY) = p_Vertex2D->xY + GLI_fF2pow24;
                    /* sinus moves:*/
                    p_Vertex2D->xX = p_Vertex2D->xX + a64_fSinTable [ ( lVerticeX + gs_lXBase ) & (GLI_TSINTA-1)] * GLI_gsWaterPlaneDepthSizeOf2DMove;
                    p_Vertex2D->xY = p_Vertex2D->xY + a64_fSinTable [ ( lVerticeY + gs_lXBase + 16) & (GLI_TSINTA-1)] * GLI_gsWaterPlaneDepthSizeOf2DMove;
                }
    }
    else
    {
        *((float *)&lLocal2) = -GLI_gsWaterPlaneDepthStartOf2DMove;
        for (;p_Vertex2D<p_Vertex2DEnd;p_Vertex2D++,p_Vertex3D ++,p_xCounter++)
            if (p_Vertex3D->xZ>GLI_C_xZClippingNear)
            {
                /* if (-*((long *)p_xCounter) > lLocal2 )*/
                if (*p_xCounter < GLI_gsWaterPlaneDepthStartOf2DMove)
                {
                    *(float *)((void *)&lVerticeX) = p_Vertex2D->xX + GLI_fF2pow24; 
                    *(float *)((void *)&lVerticeY) = p_Vertex2D->xY + GLI_fF2pow24; 
                    p_Vertex2D->xX = p_Vertex2D->xX + a64_fSinTable [ ( lVerticeX + gs_lXBase ) & (GLI_TSINTA-1)] * GLI_gsWaterPlaneDepthSizeOf2DMove;
                    p_Vertex2D->xY = p_Vertex2D->xY + a64_fSinTable [ ( lVerticeY + gs_lXBase + 16) & (GLI_TSINTA-1)] * GLI_gsWaterPlaneDepthSizeOf2DMove;
                }else
                    if (*p_xCounter < 0.0f)
                    {
                        *(float *)((void *)&lVerticeX) = p_Vertex2D->xX + GLI_fF2pow24; 
                        *(float *)((void *)&lVerticeY) = p_Vertex2D->xY + GLI_fF2pow24; 
                        p_Vertex2D->xX = p_Vertex2D->xX + a64_fSinTable [ ( lVerticeX + gs_lXBase ) & (GLI_TSINTA-1)] * WaterPlaneDepthSizeOf2DMoveLocal * *p_xCounter;
                        p_Vertex2D->xY = p_Vertex2D->xY + a64_fSinTable [ ( lVerticeY + gs_lXBase + 16) & (GLI_TSINTA-1)] * WaterPlaneDepthSizeOf2DMoveLocal * *p_xCounter;
                    }
            }
    }
}
 
/**********************************************************************************************/
/* Name: GLI_vFogWaterPlaneEffect*/
/* Goal : Make a Dpth */
/* Code: Philippe Vimont */
/* OPTIMMIZE : FINAL VERSION SHOULD BE IN ASSEMBLY*/
/**********************************************************************************************/
 
 
void
GLI_vFogWaterPlaneEffect(GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobalsParrameters,long xStart,long xNumber)
{
    float *p_xCounter,fOoWaterPlaneFogStart,fLocal;
    long lLocal2;
    GLI_tdstColor  *p_Color , *p_ColorEnd ;
    
    if ((!(bWaterPlaneState & GLI_C_l2DPlaneIsEnable)) ||
        (GLI_C_lWaterPlaneNoFog & bWaterPlaneState)) return;
    
    p_Color = p_stGlobalsParrameters->GLI_aDEF_stColorsRLID + xStart;
    
    p_ColorEnd = p_Color +  xNumber;
    p_xCounter = p_stGlobalsParrameters->GLI_aDEF_xWaterPlaneDepth + xStart;
    fOoWaterPlaneFogStart = -1.0f / GLI_gsfWaterPlaneFogStart;
    *((float *)&lLocal2) = -GLI_gsfWaterPlaneFogStart ;
    
    for (;p_Color <p_ColorEnd;p_Color ++,p_xCounter++)
        if (*((long *)p_xCounter) < 0)
        {
            if (*p_xCounter  > -GLI_gsfWaterPlaneFogStart)
            {
                fLocal = fOoWaterPlaneFogStart * *p_xCounter;
                p_Color -> xR += fLocal * GLI_gsfWaterPlaneFogColor . xR;
                p_Color -> xG += fLocal * GLI_gsfWaterPlaneFogColor . xG;
                p_Color -> xB += fLocal * GLI_gsfWaterPlaneFogColor . xB;
            }
            else
            {
                p_Color -> xR += GLI_gsfWaterPlaneFogColor . xR ;
                p_Color -> xG += GLI_gsfWaterPlaneFogColor . xG ;
                p_Color -> xB += GLI_gsfWaterPlaneFogColor . xB ;
            }
        }
}
  
/**********************************************************************************************/
/* Name: GLI_v3DWaterPlaneEffect*/
/* Goal : Detect in 3D if point are in front or over a 3D plane defined and do refraction.*/
/* Code: Philippe Vimont */
/* OPTIMMIZE : FINAL VERSION SHOULD BE IN ASSEMBLY*/
/**********************************************************************************************/
 
void
GLI_v3DWaterPlaneEffect(GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobalsParrameters,long xStart,long xNumber)
{
    MTH3D_tdstVector   stLocal;
    GLI_tdstAligned3DVector        *p_Vertex3D ;
    GLI_tdstAligned3DVector    *p_Vertex3DEnd ;
    GLI_tdstAligned3DVector    stWaterPlaneNormaleLocale;
    MTH_tdxReal xDistanceLocal;
    POS_tdstCompletePosition stMatrix;
    MTH_tdxReal *p_xDepthPTR;
    
    if (!(bWaterPlaneState & GLI_C_l2DPlaneIsEnable)) return;
    
    bWaterPlaneState &= 0xffffffff - GLI_C_lWaterPlaneCameraIsInWater;
    
    /* comopute new waterplane (normale & distance in camera matrix)*/
    p_Vertex3D = p_stGlobalsParrameters->GLI_TurnedScaledDisplecedPoint + xStart;
    p_Vertex3DEnd = p_Vertex3D + xNumber;
    MTH3D_M_vMulScalarVector( &stLocal , fWaterPlaneDistance , &stWaterPlaneNormale);
    POS_fn_vSetIdentityMatrix(&stMatrix );
    stMatrix = *p_stGlobalsParrameters->gs_st_CameraMatrix ;
    MTH3D_M_vNullVector(&stWaterPlaneNormaleLocale);
    POS_fn_vSetTranslationVector(&stMatrix,(MTH3D_tdstVector  *)&stWaterPlaneNormaleLocale);
    POS_fn_vMulMatrixVertex((MTH3D_tdstVector  *)&stWaterPlaneNormaleLocale , &stMatrix ,(MTH3D_tdstVector  *)&stWaterPlaneNormale);
    POS_fn_vMulMatrixVertex(&stLocal , p_stGlobalsParrameters->gs_st_CameraMatrix ,&stLocal );
    xDistanceLocal = MTH3D_M_xDotProductVector( &stWaterPlaneNormaleLocale , &stLocal );
    p_xDepthPTR = p_stGlobalsParrameters->GLI_aDEF_xWaterPlaneDepth + xStart;
 
    p_stGlobalsParrameters -> xWaterPlaneDistance = xDistanceLocal;
    p_stGlobalsParrameters -> stWaterPlanNormale = stWaterPlaneNormaleLocale;
    
    if (( xDistanceLocal > 0.0f ) || (GLI_C_lWaterPlaneNoRefraction & bWaterPlaneState))
    {
        /* camera is under water -> no refraction.*/
        bWaterPlaneState |= GLI_C_lWaterPlaneCameraIsInWater;
        for (;p_Vertex3D<p_Vertex3DEnd;p_Vertex3D ++,p_xDepthPTR++)
            *p_xDepthPTR = MTH3D_M_xDotProductVector( p_Vertex3D , &stWaterPlaneNormaleLocale) - xDistanceLocal ;
    }
    else 
    {
        float TheNewBince;
        for (;p_Vertex3D<p_Vertex3DEnd;p_Vertex3D++,p_xDepthPTR++)
        {
            *p_xDepthPTR = MTH3D_M_xDotProductVector( p_Vertex3D , &stWaterPlaneNormaleLocale) - xDistanceLocal ;
            if ( *p_xDepthPTR < 0.0f )
            {
                /* refraction:*/
                TheNewBince = -*p_xDepthPTR * GLI_gsWaterPlaneRefraction ;
                MTH3D_M_vMulScalarVector( &stLocal, TheNewBince , &stWaterPlaneNormaleLocale );
                MTH3D_M_vAddVector((MTH3D_tdstVector *)p_Vertex3D, (MTH3D_tdstVector *)p_Vertex3D, &stLocal);
            }
        }
    }
}
  
 
float
GLI_v3DWaterPlaneEffectForOnePoint(MTH3D_tdstVector  *p_Vertex3D , MTH3D_tdstVector  *p_Vertex3DDst , POS_tdstCompletePosition *p_stCameraMatrix)
{
    MTH3D_tdstVector   stLocal1,stLocal2;
    float TheNewBince,xDistanceLocal;
    float fReturnValue;
    
    if (!(bWaterPlaneState & GLI_C_l2DPlaneIsEnable)) return 100000000.0f;
    if (GLI_C_lWaterPlaneNoRefraction & bWaterPlaneState) return 100000000.0f;
 
 
    MTH3D_M_vMulScalarVector( &stLocal1, fWaterPlaneDistance , &stWaterPlaneNormale );
    MTH3D_M_vAddVector( &stLocal2, &stWaterPlaneNormale , &stLocal1);
 
    POS_fn_vMulMatrixVertex(&stLocal1 , p_stCameraMatrix ,&stLocal1);
    POS_fn_vMulMatrixVertex(&stLocal2 , p_stCameraMatrix ,&stLocal2);
    MTH3D_M_vSubVector( &stLocal2, &stLocal2, &stLocal1);
 
    xDistanceLocal = MTH3D_M_xDotProductVector( &stLocal2 , &stLocal1 );
 
    if ( xDistanceLocal > 0 )
    {
        /* Camera is under waterplane -> norefraction*/
        TheNewBince = MTH3D_M_xDotProductVector ( p_Vertex3D , &stLocal2 ) - xDistanceLocal ;
        if ( TheNewBince < 0.0f )
            return (-TheNewBince);
        else
            return (TheNewBince);
    }
 
    TheNewBince = MTH3D_M_xDotProductVector ( p_Vertex3D , &stLocal2 ) - xDistanceLocal ;
    if ( TheNewBince < 0.0f )
    {
        /* refraction:*/
        fReturnValue = -TheNewBince ;
        TheNewBince *= GLI_gsWaterPlaneRefraction ;
        MTH3D_M_vMulScalarVector ( &stLocal2 , TheNewBince , &stLocal2 );
        MTH3D_M_vSubVector ( p_Vertex3DDst , p_Vertex3D , &stLocal2 );
        return (fReturnValue);
    } else
        return (TheNewBince);
}
void
GLI_v3DWaterPlaneEffectForSomePoint(GLI_tdstAligned3DVector  *p_Vertex3D ,long lNbPoint , POS_tdstCompletePosition *p_stCameraMatrix)
{
    MTH3D_tdstVector   stLocal1,stLocal2;
    float TheNewBince,xDistanceLocal;
    
    if (!(bWaterPlaneState & GLI_C_l2DPlaneIsEnable)) return;
    if (GLI_C_lWaterPlaneNoRefraction & bWaterPlaneState) return;
    
 
    MTH3D_M_vMulScalarVector( &stLocal1, fWaterPlaneDistance , &stWaterPlaneNormale );
    MTH3D_M_vAddVector( &stLocal2, &stWaterPlaneNormale , &stLocal1);
 
    POS_fn_vMulMatrixVertex(&stLocal1 , p_stCameraMatrix ,&stLocal1);
    POS_fn_vMulMatrixVertex(&stLocal2 , p_stCameraMatrix ,&stLocal2);
    MTH3D_M_vSubVector( &stLocal2, &stLocal2, &stLocal1);
 
    xDistanceLocal = MTH3D_M_xDotProductVector( &stLocal2 , &stLocal1 );
 
    if ( xDistanceLocal > 0 )
    {
        /* Camera is under waterplane -> norefraction*/
        return;
    }
    while (lNbPoint--)
    {
        TheNewBince = MTH3D_M_xDotProductVector ( p_Vertex3D , &stLocal2 ) - xDistanceLocal ;
        if ( TheNewBince < 0.0f )
        {
            /* refraction:*/
            TheNewBince *= GLI_gsWaterPlaneRefraction ;
            MTH3D_M_vMulScalarVector ( &stLocal2 , TheNewBince , &stLocal2 );
            MTH3D_M_vSubVector ( (MTH3D_tdstVector *)p_Vertex3D , (MTH3D_tdstVector *)p_Vertex3D , &stLocal2 );
        }
        p_Vertex3D++;
    }
}
void GLI_xSendObjectToViewportWithLights ( GLD_tdstViewportAttributes *p_stVpt ,GEO_tdstGeometricObject *p_stObj ,long lDrawModeMask);
void GEO_vCreateGeometricObject (    ACP_tdxHandleOfObject *p_hObject ,ACP_tdxIndex xNbPoints ,ACP_tdxIndex xNbElements );
void GEO_vCreateElementIndexedTriangles (    ACP_tdxHandleOfObject hObject , ACP_tdxHandleOfElement *p_hElement ,ACP_tdxIndex xNbFaces,ACP_tdxIndex xNbElementUV);
void GEO_vEndModifyObject(ACP_tdxHandleOfObject hObject);
void GEO_vSetFaceOfIndexedTriangles (ACP_tdxHandleOfObject hObject , ACP_tdxHandleOfElement hElement ,ACP_tdxIndex xIndexOfFace,ACP_tdxIndex xPoint1,ACP_tdxIndex xPoint2,ACP_tdxIndex xPoint3);
void GEO_vSetIndexedUVOfFaceOfIndexedTriangles ( ACP_tdxHandleOfObject hObject , ACP_tdxHandleOfElement hElement ,ACP_tdxIndex xIndexOfFace,ACP_tdxIndex xUV1,ACP_tdxIndex xUV2,ACP_tdxIndex xUV3);
void GEO_vSetUVOfIndexedTriangles (  ACP_tdxHandleOfObject hObject , ACP_tdxHandleOfElement hElement ,ACP_tdxIndex xIndexOfUV,ACP_tdst2DUVValues *p_stUV);
extern CPA_EXPORT GMT_tdxHandleToGameMaterial GMT_fn_hCreateGameMaterial(void);
void GLI_xCreateMaterial ( ACP_tdxHandleOfMaterial *p_hMaterial ) ;
extern CPA_EXPORT void GMT_fn_vSetVisualMaterial(GMT_tdxHandleToGameMaterial _hGameMat, ACP_tdxHandleOfMaterial _hVisualMat);
extern CPA_EXPORT void GEO_vSetNormalOfIndexedTrianges (       ACP_tdxHandleOfObject hObject , ACP_tdxHandleOfElement hElement ,ACP_tdxIndex xIndexOfFace,MTH3D_tdstVector *p_stNormal);
void GEO_xCreateObjectPointNormals ( GEO_tdstGeometricObject *p_stObj );
void
GLI_v3DDrawWaterPlan(GLD_tdstViewportAttributes *p_stVpt)
{
    static bFirst = 1;
    static ACP_tdxHandleOfObject hWaterPlaneObject;
    POS_tdstCompletePosition stMatrix;
    MTH3D_tdstVector stPoint ;
    GLI_tdstColor stColor;
    if (bFirst)
    {
        GMT_tdxHandleToGameMaterial hWaterGMT;
        ACP_tdxHandleOfMaterial hWaterMAT;
        ACP_tdxHandleOfElement hElement;
        ACP_tdst2DUVValues stUV;
        bFirst = 0;
        GEO_vCreateGeometricObject ( &hWaterPlaneObject , 4 , 1 );
        GEO_xCreateObjectPointNormals ( hWaterPlaneObject  );
        GEO_vCreateElementIndexedTriangles ( hWaterPlaneObject , &hElement , 2 , 4 );
        GEO_vSetFaceOfIndexedTriangles (hWaterPlaneObject , hElement ,0,0,1,3);
        GEO_vSetIndexedUVOfFaceOfIndexedTriangles ( hWaterPlaneObject , hElement ,0,0,1,3);
        GEO_vSetFaceOfIndexedTriangles (hWaterPlaneObject , hElement ,1,3,1,2);
        GEO_vSetIndexedUVOfFaceOfIndexedTriangles ( hWaterPlaneObject , hElement ,1,3,1,2);
#define CYCLEWATER 3.0f
        stUV . xU = 0.0f;
        stUV . xV = 0.0f;
        GEO_vSetUVOfIndexedTriangles (  hWaterPlaneObject , hElement ,0,&stUV);
        stUV . xU = CYCLEWATER;
        stUV . xV = 0.0f;
        GEO_vSetUVOfIndexedTriangles (  hWaterPlaneObject , hElement ,1,&stUV);
        stUV . xU = CYCLEWATER;
        stUV . xV = CYCLEWATER;
        GEO_vSetUVOfIndexedTriangles (  hWaterPlaneObject , hElement ,2,&stUV);
        stUV . xU = 0.0f;
        stUV . xV = CYCLEWATER;
        GEO_vSetUVOfIndexedTriangles (  hWaterPlaneObject , hElement ,3,&stUV);
        hWaterGMT = GMT_fn_hCreateGameMaterial();
        GEO_vSetGameMaterialOfIndexedTriangles ( hWaterPlaneObject , hElement ,hWaterGMT);
        GLI_xCreateMaterial ( &hWaterMAT ) ;
        GMT_fn_vSetVisualMaterial(hWaterGMT, hWaterMAT);
        GLI_xSetMaterialType ( hWaterMAT , 0xffffffff - GLI_C_lIsTestingBackface ) ;
        stColor . xR = stColor . xG = stColor . xB = stColor . xA = 0.6f;
        GLI_xSetMaterialAmbientCoef ( hWaterMAT , &stColor );
        stColor . xR = stColor . xG = stColor . xB = stColor . xA = 0.0f;
        GLI_xSetMaterialDiffuseCoef ( hWaterMAT , &stColor );
 
        stPoint .xX = 0.0f;
        stPoint .xY = 0.0f;
        stPoint .xZ = 1.0f;
        GEO_vSetNormalOfIndexedTrianges ( hWaterPlaneObject , hElement , 0 , &stPoint);
        GEO_vSetNormalOfIndexedTrianges ( hWaterPlaneObject , hElement , 1 , &stPoint);
        GEO_vSetNormalOfIndexedTrianges ( hWaterPlaneObject , hElement , 2 , &stPoint);
        GEO_vSetNormalOfIndexedTrianges ( hWaterPlaneObject , hElement , 3 , &stPoint);
        GEO_vEndModifyObject( hWaterPlaneObject );
    }
#define SQUAREWATERPLANESIZE 210.f
    stPoint . xX = -SQUAREWATERPLANESIZE;
    stPoint . xZ = -SQUAREWATERPLANESIZE;
    stPoint . xY = fWaterPlaneDistance + 0.1f;
    GEO_vSetPointOfObject ( hWaterPlaneObject , &stPoint, 0);
    stPoint . xX = +SQUAREWATERPLANESIZE;
    stPoint . xZ = -SQUAREWATERPLANESIZE;
    stPoint . xY = fWaterPlaneDistance + 0.1f;
    GEO_vSetPointOfObject ( hWaterPlaneObject , &stPoint, 1);
    stPoint . xX = +SQUAREWATERPLANESIZE;
    stPoint . xZ = +SQUAREWATERPLANESIZE;
    stPoint . xY = fWaterPlaneDistance + 0.1f;
    GEO_vSetPointOfObject ( hWaterPlaneObject , &stPoint, 2);
    stPoint . xX = -SQUAREWATERPLANESIZE;
    stPoint . xZ = +SQUAREWATERPLANESIZE;
    stPoint . xY = fWaterPlaneDistance + 0.1f;
    GEO_vSetPointOfObject ( hWaterPlaneObject , &stPoint, 3);
    POS_fn_vSetIdentityMatrix(&stMatrix );
/*    g_p_stCurrentMatrix = &stMatrix;*/
    GLI_xPushMatrix ( &stMatrix ) ;
    GLI_xSendObjectToViewportWithLights ( p_stVpt , hWaterPlaneObject ,0xffffffff);
}
 
void GLI_LineWaterNoise(GLI_tdstAligned3DVector *,GLI_tdstAligned3DVector *);
void GLI_vInformWaterNoise(GLI_tdstAligned3DVector *p_Point,GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BG)
{
    static POS_tdstCompletePosition stMatrix;
    GLI_tdstAligned3DVector stPoint;
    static GLI_tdstAligned3DVector lastpoint;
    static long Counter = 0;
 
    Counter ++ ;
    Counter &=1;
 
    POS_fn_vSetIdentityMatrix(&stMatrix);
    POS_fn_vInvertIsoMatrix ( &stMatrix, GLI_BG -> gs_st_CameraMatrix ) ;
    POS_M_vFastMulMatrixVertex( (MTH3D_tdstVector *)&stPoint, &stMatrix , (MTH3D_tdstVector *)p_Point );
    stPoint.xX *= CYCLEWATER * 0.5f / SQUAREWATERPLANESIZE;
    stPoint.xZ *= CYCLEWATER * 0.5f / SQUAREWATERPLANESIZE;
    stPoint.xX += 0.5f ;
    stPoint.xZ += 0.5f ;
    if (Counter) lastpoint = stPoint;
    else
    {
        GLI_LineWaterNoise(&stPoint,&lastpoint);
    }
}
 
 
/**********************************************************************************************/
/* Name: GLI_vSetWaterFog*/
/* Goal : Init waterplane module*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : */
/**********************************************************************************************/
void GLI_vSetWaterFog(MTH_tdxReal xDepth,GLI_tdstColor *p_stFogColor)
{
    GLI_gsfWaterPlaneFogColor = *p_stFogColor;
    GLI_gsfWaterPlaneFogStart = xDepth;
}
/**********************************************************************************************/
/* Name: GLI_vInitWaterplaneModule*/
/* Goal : Init waterplane module*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : */
/**********************************************************************************************/
void GLI_vInitWaterplaneModule()
{
    /* !!! = Could be used as a REINIT function, so it could stay optimlised*/
    long lCounter;
    static unsigned char lIsAlreadyInit = 1;
    
    GLI_fF2pow24 = (float)(3L * pow(2,23));
    
    if (lIsAlreadyInit)
        for (lCounter=0;lCounter<GLI_TSINTA;lCounter++)
        {
            a64_fSinTable[lCounter]= (MTH_M_xCos( ((2.0*3.1415927f/GLI_TSINTA) * (float)lCounter))) * 2;
        }
    
    lIsAlreadyInit = 0;
    bWaterPlaneState = 0;
    gs_lXBase = 0;
    gs_lYBase = 32;
    GLI_gsfWaterPlaneFogColor . xR = -0.6f;
    GLI_gsfWaterPlaneFogColor . xG = -0.3f;
    GLI_gsfWaterPlaneFogColor . xB = -0.4f;
    GLI_gsWaterPlaneRefraction = 0.7f;
    GLI_gsWaterPlaneDepthSizeOf2DMove = 1.4f;
    GLI_gsWaterPlaneDepthStartOf2DMove = -5.0f;
    GLI_gsfWaterPlaneFogStart = 7.0f;
    stWaterPlaneNormale . xX = 0.0f;
    stWaterPlaneNormale . xZ = 0.0f;
    stWaterPlaneNormale . xY = 1.0f;
    fWaterPlaneDistance = 0.0f;
 
    /*ANNECY VL04/03/98{*/
	stSinEffectAmp.xX = 1.0f;
	stSinEffectAmp.xY = 0.0f;
	stSinEffectAmp.xZ = 0.0f;
 
	a3_lSinEffectFreq[0] = 1;
	a3_lSinEffectFreq[1] = 0;
	a3_lSinEffectFreq[2] = 0;
 
	a3_xSinEffectBase[0] = MTH_C_ZERO;
	a3_xSinEffectBase[1] = MTH_C_ZERO;
	a3_xSinEffectBase[2] = MTH_C_ZERO;
 
	xSinusEffectDepthStart = 10.0f;
 
	g_cSinusEffectState = 0;
	g_cSinusEffectFlag = 0;
	/*ENDANNECY VL}*/
}
 
/*ANNECY VL04/03/98{*/
/*
 =======================================================================================
	Function for sinus Effect 
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : get / set state
 ----------------------------------------------------------------------------------------
 */
void GLI_fn_SinusEffect_vSetState( char _cState )
{
	g_cSinusEffectState = _cState;
}
 
char GLI_fn_SinusEffect_vGetState( void )
{
	return g_cSinusEffectState;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : get / set flag
 ----------------------------------------------------------------------------------------
 */
void GLI_fn_SinusEffect_vSetFlag( char _cFlag )
{
	g_cSinusEffectFlag = _cFlag;
}
 
char GLI_fn_SinusEffect_vGetFlag( void )
{
	return g_cSinusEffectFlag;
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : return non zero value if object in second viewport have to be
				affected by sinus effect
 ----------------------------------------------------------------------------------------
 */
char GLI_fn_SinusEffect_cIsSecondViewportAffected( void )
{
	return g_cSinusEffectFlag & C_SinusEffect_cAffectSecondViewPort;
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : set frequences
 ----------------------------------------------------------------------------------------
 */
void GLI_fn_SinusEffect_vSetFreq( long _lXFreq, long _lYFreq, long _lZFreq )
{
	a3_lSinEffectFreq[0] = _lXFreq;
	a3_lSinEffectFreq[1] = _lYFreq;
	a3_lSinEffectFreq[2] = _lZFreq;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Set amplitude vector
 ----------------------------------------------------------------------------------------
 */
void GLI_fn_SinusEffect_vSetAmplitude( MTH3D_tdstVector *_p_stAmpVector )
{
	MTH3D_M_vCopyVector( &stSinEffectAmp, _p_stAmpVector );
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : 3D Sinus effect 
 ----------------------------------------------------------------------------------------
 *
void GLI_v3DSinusEffect( GLI_tdstInternalGlobalValuesFor3dEngine *_p_stGP, long _xStart, long _xNumber)
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*
	GLI_tdstAligned3DVector     *p_Vertex3D ;
	GLI_tdstAligned3DVector		*p_Vertex3DEnd ;
	long						lVertice;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*
 
	p_Vertex3D		= _p_stGP->GLI_TurnedScaledDisplecedPoint + _xStart;
	p_Vertex3DEnd	= p_Vertex3D + _xNumber;
 
	for ( ; p_Vertex3D<p_Vertex3DEnd ; p_Vertex3D ++)
	{
		if ( p_Vertex3D->xZ > xSinusEffectDepthStart )
		{
			if (a3_lSinEffectFreq[0] )
			{
				*(float *)((void *)&lVertice) = p_Vertex3D->xX + a3_xSinEffectBase[0] +GLI_fF2pow24; 
				p_Vertex3D->xX = p_Vertex3D->xX + ((lVertice & 64) ? 1 : -1 ) * a64_fSinTable [ lVertice & 63] * stSinEffectAmp.xX;
			}
			if (a3_lSinEffectFreq[1] )
			{
				*(float *)((void *)&lVertice) = p_Vertex3D->xY + a3_xSinEffectBase[1] + GLI_fF2pow24; 
				p_Vertex3D->xY = p_Vertex3D->xY + ((lVertice & 64) ? 1 : -1 ) * a64_fSinTable [ lVertice & 63] * stSinEffectAmp.xY;
			}
			if (a3_lSinEffectFreq[2] )
			{
				*(float *)((void *)&lVertice) = p_Vertex3D->xZ + a3_xSinEffectBase[2] + GLI_fF2pow24; 
				p_Vertex3D->xZ = p_Vertex3D->xZ + ((lVertice & 64) ? 1 : -1 ) * a64_fSinTable [ lVertice & 63] * stSinEffectAmp.xZ;
			}
		}
	}
}
*/
/*
 ----------------------------------------------------------------------------------------
  Description   : 2D Sinus effect 
 ----------------------------------------------------------------------------------------
 */
void GLI_v2DSinusEffect(GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobalsParrameters,long xStart,long xNumber)
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	long					lVerticeY;
	long					lVerticeX;
	GLI_tdstAligned3DVector *p_Vertex3D ;
	GLI_tdstAligned2DVector *p_Vertex2D , *p_Vertex2DEnd ;
	MTH_tdxReal				xFactor;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	
	/*
	 * init loop data
	 */
	p_Vertex3D		= p_stGlobalsParrameters->GLI_TurnedScaledDisplecedPoint + xStart;
	p_Vertex2D		= p_stGlobalsParrameters->GLI_ScreenPoint + xStart;
	p_Vertex2DEnd	= p_Vertex2D + xNumber;
 
	/*
	 * loop on vertex
	 */
	if (g_cSinusEffectFlag & C_SinusEffect_cUseZFactor )
	{
		for ( ;p_Vertex2D < p_Vertex2DEnd; p_Vertex2D++, p_Vertex3D ++)
		{
			if (p_Vertex3D->xZ > GLI_C_xZClippingNear)
			{
				*(float *)((void *)&lVerticeX) = (p_Vertex2D->xX) + a3_xSinEffectBase[0] + GLI_fF2pow24;
				*(float *)((void *)&lVerticeY) = (p_Vertex2D->xY) + a3_xSinEffectBase[1] + GLI_fF2pow24;
				xFactor = (p_Vertex2D->xOoZ > 0.005) ? 1 : 200 * p_Vertex2D->xOoZ;
 
				p_Vertex2D->xX += p_Vertex2D->xX + a64_fSinTable [ lVerticeX & 63] * stSinEffectAmp.xX * xFactor;
				p_Vertex2D->xY += p_Vertex2D->xY + a64_fSinTable [ lVerticeY & 63] * stSinEffectAmp.xY * xFactor;
			}
		}
	}
	else
	{
		for ( ;p_Vertex2D < p_Vertex2DEnd; p_Vertex2D++, p_Vertex3D ++)
		{
			if (p_Vertex3D->xZ > GLI_C_xZClippingNear)
			{
				*(float *)((void *)&lVerticeX) = (p_Vertex2D->xX) + a3_xSinEffectBase[0] + GLI_fF2pow24;
				*(float *)((void *)&lVerticeY) = (p_Vertex2D->xY) + a3_xSinEffectBase[1] + GLI_fF2pow24;
 
				p_Vertex2D->xX += a64_fSinTable[ lVerticeX & 63 ] * stSinEffectAmp.xX;
				p_Vertex2D->xY += a64_fSinTable[ lVerticeY & 63 ] * stSinEffectAmp.xY;
			}
		}
	}
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : update effect variable.
					called only once by trame before world is displayed
 ----------------------------------------------------------------------------------------
 */
MTH_tdxReal gs_xFactor;
 
void GLI_vUpdateEffectData( unsigned long _ulDeltaT )
{
	MTH_tdxReal xFactor;
 
	gs_xFactor = xFactor = MTH_M_xMul( (float)_ulDeltaT, 0.0128f );
 
	a3_xSinEffectBase[0] += a3_lSinEffectFreq[0] * xFactor;
	a3_xSinEffectBase[1] += a3_lSinEffectFreq[1] * xFactor;
	a3_xSinEffectBase[2] += a3_lSinEffectFreq[2] * xFactor;
 
    /*
     * Reset bench data
     */
    GLI_M_vBenchReset();
}
 
 
/*ENDANNECY VL}*/
void GLI_DoSinusEffetOnRLI ( GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobalsParrameters, 
                             long xStart, long lNumber) {
  GEO_tdstColor *GEOCol ;
	float				*p_fGeo, *p_fLastGeo;
  long lVerticeX ;
  MTH3D_tdstVector * p_stVertex3D;
  static float facteur = 1.0f ;
 
  GEOCol = p_stGlobalsParrameters->GLI_aDEF_stColorsRLID  + xStart ;
	p_fGeo		= (float *) GEOCol;
	p_fLastGeo	= (float *) (GEOCol + lNumber);
 
  p_stVertex3D = p_stGlobalsParrameters->p_stObj->d_stListOfPoints ;
 
	for (; p_fGeo < p_fLastGeo; p_stVertex3D++)
	{
    *(float *)((void *)&lVerticeX) = facteur * ((p_stVertex3D->xX+p_stVertex3D->xY+p_stVertex3D->xZ) + a3_xSinEffectBase[0] + GLI_fF2pow24) ;
		*p_fGeo++ = a3_lSinRLIBase[0] + a64_fSinTable[ lVerticeX & 63 ] * a3_lSinRLIAmp[0] ;
		*p_fGeo++ = a3_lSinRLIBase[1] + a64_fSinTable[ lVerticeX & 63 ] * a3_lSinRLIAmp[1];
		*p_fGeo++ = a3_lSinRLIBase[2] + a64_fSinTable[ lVerticeX & 63 ] * a3_lSinRLIAmp[2];
		*p_fGeo++ ;
	}
 
}
 
void GLI_vSinusEffetOn3DVertex ( MTH3D_tdstVector * p_stVertex3D ){
  long lVertice ;
  float xX, xY, xZ ;
  float fFreq ;
    
  if ( GLI_BIG_GLOBALS->lDisplayMenuIsDetected ) {
    fFreq = GLI_fSinEffectBase ;
  }
  else {
    fFreq = GLI_fF2pow24 ;
  }  
  
  *(float *)((void *)&lVertice) = a3_xSinEffectBase[0]+p_stVertex3D->xY+p_stVertex3D->xZ+fFreq ;
  xX = p_stVertex3D->xX + a64_fSinTable [ lVertice & 63] * stSinEffectAmp.xX;
  
  *(float *)((void *)&lVertice) = a3_xSinEffectBase[1]+p_stVertex3D->xX+p_stVertex3D->xZ+fFreq ;
  xY = p_stVertex3D->xY + a64_fSinTable [ lVertice & 63] * stSinEffectAmp.xY;
  
  *(float *)((void *)&lVertice) = a3_xSinEffectBase[2]+p_stVertex3D->xY+p_stVertex3D->xX+fFreq ;
  xZ = p_stVertex3D->xZ + a64_fSinTable [ lVertice & 63] * stSinEffectAmp.xZ;
  
  p_stVertex3D->xX = xX ;
  p_stVertex3D->xY = xY ;
  p_stVertex3D->xZ = xZ ;
  
}
void GLI_vSetSinusEffectOnRLIAmp ( MTH_tdxReal xRed, MTH_tdxReal xGreen, MTH_tdxReal xBlue ) {
  a3_lSinRLIAmp[0] = xRed ;
  a3_lSinRLIAmp[1] = xGreen ;
  a3_lSinRLIAmp[2] = xBlue ;
}
 
void GLI_vSetSinusEffectOnRLIBase ( MTH_tdxReal xRed, MTH_tdxReal xGreen, MTH_tdxReal xBlue ) {
  a3_lSinRLIBase[0] = xRed ;
  a3_lSinRLIBase[1] = xGreen ;
  a3_lSinRLIBase[2] = xBlue ;
}
 
void GLI_vSetSinEffetBase (MTH_tdxReal xBase) {
  GLI_fSinEffectBase = xBase ;
}
 
void GLI_vSaveSinusContext ( void ) {
  int i ;
  for (i=0 ; i<3 ; i++ ) {
    a3_xSinEffectBaseSaved[i] = a3_xSinEffectBase[i] ;
    a3_lSinEffectFreqSaved[i] = a3_lSinEffectFreq[i] ;
  }
  stSinEffectAmpSaved         = stSinEffectAmp;
  stSinEffectVectorSaved      = stSinEffectVector ;
  xSinusEffectDepthStartSaved = xSinusEffectDepthStart;
  g_cSinusEffectStateSaved    = g_cSinusEffectState;
  g_cSinusEffectFlagSaved     = g_cSinusEffectFlag ;
}
void GLI_vRestoreSinusContext ( void ) {
  int i ;
  for (i=0 ; i<3 ; i++ ) {
    a3_xSinEffectBase[i] = a3_xSinEffectBaseSaved[i] ;
    a3_lSinEffectFreq[i] = a3_lSinEffectFreqSaved[i] ;
  }
  stSinEffectAmp         = stSinEffectAmpSaved;
  stSinEffectVector      = stSinEffectVectorSaved ;
  xSinusEffectDepthStart = xSinusEffectDepthStartSaved;
  g_cSinusEffectState    = g_cSinusEffectStateSaved;
  g_cSinusEffectFlag     = g_cSinusEffectFlagSaved ;
  
}
#ifdef __cplusplus
} /*extern "C"*/
#endif
