/******************************************************************************************
FILE :                            CLIP.C
 
  VERS :  1.00 \ Philippe Vimont 
  
    DATE :  15.05.98
    
*******************************************************************************************/
#include "Gli_st.h"
#include "GLI_Defn.h"
#include "polygon.h"
#include "mater_st.h"
#include "light_st.h"
#include "PvObj_st.h"
#include "Liste.h"
#include "watrplan.h"
#include "proj.h"
#include "vpt3D.h"
#include "camera.h"
#include "material.h"
#include "texture.h"
#include "DLLCom.h"
#include "TEX.h"
 
#include "PRF.h"
 
#ifdef SGL2
#include <SGL2.h>
#endif
 
#ifdef __cplusplus
extern "C" 
{
#endif
#ifdef ZARMA
}}}
#endif
 
#include "drawflags.h"
/* collect the functions we need to call*/
/* we need to set this to zero somewhere*/
unsigned long ulFuncMask;
char temp_string[100];									\
 
 
/* -----------------------------------------------------------------------------------------*/
/* Global variable for optimisation */
/*---------------------------------------------------------------------------------------------*/
extern GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BIG_GLOBALS;
 
static float fAddU,fAddV,fConstantMirrorZValue;
static GEO_tdstTripledIndex *p_stCurrentTriangle , *p_stCurrentTriangleUV , *p_stLastTriangle;
static GEO_tdstElementIndexedTriangles *p_stCurrentElementIndexedTriangle ;
static long fX_CMP_Optimize , fY_CMP_Optimize;
static long fXMin_CLIP_Optimize , fYMin_CLIP_Optimize , fXMax_CLIP_Optimize , fYMax_CLIP_Optimize ;
static unsigned long *footptr;
static ACP_tdst2DUVValues   *d_stVirtualUV[3];
extern void GLI_vDoTextureSelection(GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT);
extern void GLI_vSetGlobalAlpha(float Alpha);
#define GLI_C_lCLIP_ALL (GLI_C_ClipMaskXMin | GLI_C_ClipMaskXMax | GLI_C_ClipMaskYMin | GLI_C_ClipMaskYMax )
/* -----------------------------------------------------------------------------------------*/
 
/**********************************************************************************************/
/* Name: GLI_vSetZClip*/
/* Goal: */
/* Code: Philippe Vimont */
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GLI_DRV_vSetZClip(float ZClip,GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT)
{
    p_stGlobaleMT -> fZClipping = ZClip;
    p_stGlobaleMT -> fWClipping = 1.0f / ZClip;
}
 
/**********************************************************************************************/
/* Name: GLI_vSetClipWindow*/
/* Goal: */
/* Code: Philippe Vimont */
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GLI_DRV_vSetClipWindow(float fXMin,float fXMax,float fYMin,float fYMax,GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT)
{
	p_stGlobaleMT->fXMinClipping = fXMin;
    p_stGlobaleMT->fXMaxClipping = fXMax;
    p_stGlobaleMT->fYMinClipping = fYMin;
    p_stGlobaleMT->fYMaxClipping = fYMax;
}
 
/**********************************************************************************************/
/* Name: GLI_ulInterpol2PackedColor*/
/* Goal: interpol 2 unsigned long coded colors with a float [0.0 .. 1.0f]*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : No*/
/**********************************************************************************************/
unsigned long GLI_ulInterpol2PackedColor(unsigned long ulP1,unsigned long ulP2,float fZClipLocalCoef)
{
    unsigned long RetValue,Interpoler; 
    if (fZClipLocalCoef >= 0.98f)
        return ulP2;
    if (fZClipLocalCoef <= 0.02f)
        return ulP1;
    *((float *)&Interpoler) = fZClipLocalCoef + 32768.0f + 16384.0f;
    RetValue =  (Interpoler & 128) ? (ulP2 & 0xfefefefe) >> 1 : (ulP1 & 0xfefefefe) >> 1;
    RetValue += (Interpoler &  64) ? (ulP2 & 0xfcfcfcfc) >> 2 : (ulP1 & 0xfcfcfcfc) >> 2;
    RetValue += (Interpoler &  32) ? (ulP2 & 0xf8f8f8f8) >> 3 : (ulP1 & 0xf8f8f8f8) >> 3;
    RetValue += (Interpoler &  16) ? (ulP2 & 0xf0f0f0f0) >> 4 : (ulP1 & 0xf0f0f0f0) >> 4;
    RetValue += (Interpoler &   8) ? (ulP2 & 0xe0e0e0e0) >> 5 : (ulP1 & 0xe0e0e0e0) >> 5;
    RetValue += (Interpoler &   4) ? (ulP2 & 0xc0c0c0c0) >> 6 : (ulP1 & 0xc0c0c0c0) >> 6;
    RetValue += (Interpoler &   2) ? (ulP2 & 0x80808080) >> 7 : (ulP1 & 0x80808080) >> 7;
    return RetValue;
}
 
/*void GLI_vInformWaterNoise(GLI_tdstAligned3DVector *p_Point,GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BG);*/
 
/* -----------------------------------------------------------------------------------------*/
/* Stack function's stuff */
/*---------------------------------------------------------------------------------------------*/
#define GLI_FuncNodeBegin(a) static void GLI_INTERFACE_FUNC(a) (void)
static long lActualFunction;
static void GLI_fn_LastFunc(void) {};
static void (* GLI_p_fn_ListOfFunc[20])(void) ;
static void (** GLI_fnCurrentFunc)(void) ;
static void GLI_M_ClearFuncList()
{
	ulFuncMask = 0;
    lActualFunction = 0;
    GLI_p_fn_ListOfFunc[0] = GLI_fn_LastFunc;
}
/* static void GLI_M_AddFunc(void (* Func)(void)) */
#define GLI_M_AddFunc( Func ) \
    (GLI_p_fn_ListOfFunc[lActualFunction++] = Func)
 
/* Print out ulFuncMask to Error log here if benching*/
#define GLI_M_CallFirstFunc() \
{\
	GLI_fnCurrentFunc = GLI_p_fn_ListOfFunc;			\
	(*(GLI_fnCurrentFunc))();							\
}
#define GLI_M_CallNextFunc() (*(++GLI_fnCurrentFunc))();
#define GLI_M_CallNextFuncAndSave() \
{\
    void (** GLI_fnCurrentFuncSave)(void) ;\
    GLI_fnCurrentFuncSave = GLI_fnCurrentFunc;\
    (*(++GLI_fnCurrentFunc))();\
    GLI_fnCurrentFunc = GLI_fnCurrentFuncSave ;\
}
#define GLI_M_TriangleIsOut() return
 
/* -----------------------------------------------------------------------------------------*/
/* ZList function stuff */
/*---------------------------------------------------------------------------------------------*/
void GLI_DRV_xClearViewingList ( void )
{
    unsigned long ulTableCounter;
 
    if (GLI_BIG_GLOBALS -> p_TheZListe == NULL) return;
 
    GLI_BIG_GLOBALS -> p_TheZListe -> p_CurrentPoint = GLI_BIG_GLOBALS -> p_TheZListe -> p_TableOfPoints;
    GLI_BIG_GLOBALS -> p_TheZListe -> p_stCurrentZNode = GLI_BIG_GLOBALS -> p_TheZListe -> aDEF_tdstZListeNodes;
    for  (ulTableCounter = 0; ulTableCounter < GLI_NumberOfZListes ; ulTableCounter ++)
    {
        GLI_BIG_GLOBALS -> p_TheZListe -> lMinValue[ulTableCounter] = 1 << GLI_MaxZEntryPO2;
        GLI_BIG_GLOBALS -> p_TheZListe -> lMaxValue[ulTableCounter] = 0;
    }
}
 
void GLI_v_AddNodeInZList(float Z)
{
    unsigned short index;
    index = (unsigned short )(((*(unsigned long *)&Z) >> 16) - 13000) & ((1 << GLI_MaxZEntryPO2) - 1);
 
    if( GLI_BIG_GLOBALS->p_TheZListe->lMinValue[ GLI_BIG_GLOBALS->ulCurrentZTable ] > index ) 
        GLI_BIG_GLOBALS->p_TheZListe->lMinValue[ GLI_BIG_GLOBALS->ulCurrentZTable ] = index;
    if( GLI_BIG_GLOBALS->p_TheZListe->lMaxValue[ GLI_BIG_GLOBALS->ulCurrentZTable ] < index ) 
        GLI_BIG_GLOBALS->p_TheZListe->lMaxValue[ GLI_BIG_GLOBALS->ulCurrentZTable ] = index;
 
    GLI_BIG_GLOBALS->p_TheZListe->p_stCurrentZNode->p_ThreePoints          = GLI_BIG_GLOBALS->p_TheZListe->p_CurrentPoint;
    GLI_BIG_GLOBALS->p_TheZListe->p_stCurrentZNode->p_TextureOfTheTriangle = GLI_BIG_GLOBALS->p_stCurrentTexture;
    /**/
    GLI_BIG_GLOBALS->p_TheZListe->p_stCurrentZNode->p_stMaterial           = GLI_BIG_GLOBALS->hCurrentMaterial;
 
	GLI_BIG_GLOBALS->p_TheZListe->p_stCurrentZNode->lCurrentDrawMask       = GLI_BIG_GLOBALS->lCurrentDrawMask & ~GLI_C_lIsWriteZBuffer;
    GLI_BIG_GLOBALS->p_TheZListe->p_stCurrentZNode->p_stFogParams          = GLI_BIG_GLOBALS->p_stActiveFog ;
	GLI_BIG_GLOBALS->p_TheZListe->p_stCurrentZNode->p_NextNode             = GLI_BIG_GLOBALS->p_TheZListe->aDEF_p_tdstTableOfZentryNearestOfWaterPlane[ index + ( GLI_BIG_GLOBALS->ulCurrentZTable << GLI_MaxZEntryPO2 ) ];
	GLI_BIG_GLOBALS->p_TheZListe->aDEF_p_tdstTableOfZentryNearestOfWaterPlane[ index + ( GLI_BIG_GLOBALS->ulCurrentZTable << GLI_MaxZEntryPO2 ) ] = GLI_BIG_GLOBALS->p_TheZListe->p_stCurrentZNode;
	GLI_BIG_GLOBALS->p_TheZListe->p_stCurrentZNode++;
}
 
#define GLI_M_InitSprite()\
{\
    SetX(CurrentDestXYZ[0],a4_st2DVertex [0] . xX);\
    SetY(CurrentDestXYZ[0],a4_st2DVertex [0] . xY);\
    SetX(CurrentDestXYZ[1],a4_st2DVertex [1] . xX);\
    SetY(CurrentDestXYZ[1],a4_st2DVertex [1] . xY);\
    SetX(CurrentDestXYZ[2],a4_st2DVertex [2] . xX);\
    SetY(CurrentDestXYZ[2],a4_st2DVertex [2] . xY);\
    SetX(CurrentDestXYZ[3],a4_st2DVertex [3] . xX);\
    SetY(CurrentDestXYZ[3],a4_st2DVertex [3] . xY);\
    SetZ(CurrentDestXYZ[0],xZ );\
    SetZ(CurrentDestXYZ[1],xZ );\
    SetZ(CurrentDestXYZ[2],xZ );\
    SetZ(CurrentDestXYZ[3],xZ );\
	SetPackedColor( CurrentDestXYZ[0] , p_stGlobaleMT -> ulColorInitForSprite);\
	SetPackedColor( CurrentDestXYZ[1] , p_stGlobaleMT -> ulColorInitForSprite);\
	SetPackedColor( CurrentDestXYZ[2] , p_stGlobaleMT -> ulColorInitForSprite);\
	SetPackedColor( CurrentDestXYZ[3] , p_stGlobaleMT -> ulColorInitForSprite);\
}
 
#define GLI_M_InitLine()\
{\
	SetX(CurrentDestXYZ[0],p_st2DVertex1->xX);\
	SetY(CurrentDestXYZ[0],p_st2DVertex1->xY);\
	SetX(CurrentDestXYZ[1],p_st2DVertex2->xX);\
	SetY(CurrentDestXYZ[1],p_st2DVertex2->xY);\
	SetZ(CurrentDestXYZ[0],p_stVertex1->xZ );\
	SetZ(CurrentDestXYZ[1],p_stVertex2->xZ );\
	SetPackedColor(CurrentDestXYZ[0],p_st2DVertex1->ulPackedColor  );\
	SetPackedColor(CurrentDestXYZ[1],p_st2DVertex2->ulPackedColor  );\
}
	
 
/*---------------------------------------------------------------------------------------------*/
/* Kamui specific*/
/*---------------------------------------------------------------------------------------------*/
#ifdef KAMUI
#include "Kamui\Acces_KAMUI.c"
#include "Acces_ALL.c"
#endif
 
/*---------------------------------------------------------------------------------------------*/
/* SGL2 specific*/
/*---------------------------------------------------------------------------------------------*/
#ifdef SGL2
#include "SGL2\Acces_SGL2.c"
#include "Acces_ALL.c"
#endif
 
/*---------------------------------------------------------------------------------------------*/
/* VOODOO1 specific*/
/*---------------------------------------------------------------------------------------------*/
#ifdef GLIDE2
#include "GLIDE2\SRC\Acces_GLIDE2.c"
#include "Acces_ALL.c"
#endif
 
/*---------------------------------------------------------------------------------------------*/
/* VOODOO1 specific with multitexture*/
/*---------------------------------------------------------------------------------------------*/
#ifdef GLIDE2MT
#include "GLIDE2MT\SRC\Glide2MT_Acces.c"
#include "Acces_ALL.c"
#endif
 
 
/*---------------------------------------------------------------------------------------------*/
/* VOODOO2 specific*/
/*---------------------------------------------------------------------------------------------*/
#ifdef GLIDE3
#include "GLIDE3\SRC\GLIDE3_Acces.c"
#include "Acces_ALL.c"
#endif
 
 
/*---------------------------------------------------------------------------------------------*/
/* DirectX6 specific*/
/*---------------------------------------------------------------------------------------------*/
#ifdef GLI_DIRECTX6
#include "DirectX6\Src\DX6_Acces.c"
#include "Acces_ALL.c"
#endif
 
/*---------------------------------------------------------------------------------------------*/
/* OpenGL specific*/
/*---------------------------------------------------------------------------------------------*/
#ifdef GLI_OPENGL
#include "OpenGL\Src\OGL_Acces.c"
#include "Acces_ALL.c"
#endif
 
 
 
/* -----------------------------------------------------------------------------------------*/
/* ZList Draw stuff */
/*---------------------------------------------------------------------------------------------*/
void GLI_vDoTransparentTextureSelection(GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT);
void GLI_fn_vSetRenderParametersBeforeTransparencyFace( void );
 
void GLI_DRV_xSendListToViewport ( GLD_tdstViewportAttributes *p_stVpt )
{
    GLI_tdstOneNodeOfZListe *p_CuurentNode,**p_TableEntry,**p_LastTableEntry;
    unsigned long ulTableCounter;
 
    if (GLI_BIG_GLOBALS->p_TheZListe == NULL) 
        return;
 
    GLI_BIG_GLOBALS -> lCurrentDrawMask   = 0xFFFFFFFF;
    GLI_BIG_GLOBALS -> p_stCurrentTexture = NULL;
    GLI_MDRV_vSetGlobalAlpha(128);
 
    GLI_BeforeDraw();
 
	GLI_fn_vSetRenderParametersBeforeTransparencyFace();
 
    for  (ulTableCounter = 0; ulTableCounter < GLI_NumberOfZListes; ulTableCounter ++)
    {
        if ( GLI_BIG_GLOBALS->p_TheZListe->lMaxValue[ulTableCounter] < GLI_BIG_GLOBALS->p_TheZListe->lMinValue[ulTableCounter] )
            continue;
 
        p_TableEntry = GLI_BIG_GLOBALS -> p_TheZListe -> aDEF_p_tdstTableOfZentryNearestOfWaterPlane + (ulTableCounter << GLI_MaxZEntryPO2);
        p_LastTableEntry = p_TableEntry + GLI_BIG_GLOBALS -> p_TheZListe -> lMaxValue[ulTableCounter];
        p_TableEntry += GLI_BIG_GLOBALS -> p_TheZListe -> lMinValue[ulTableCounter];
        /*p_LastTableEntry = p_TableEntry + GLI_BIG_GLOBALS -> p_TheZListe -> lMaxValue[ulTableCounter];*/
        while (p_TableEntry <= p_LastTableEntry)
        {
            p_CuurentNode = *(p_TableEntry);
            while (p_CuurentNode != NULL)
            {
                if (
                        ( GLI_BIG_GLOBALS->p_stCurrentTexture   != p_CuurentNode->p_TextureOfTheTriangle)
                     || ( GLI_BIG_GLOBALS->lCurrentDrawMask	    != (long) p_CuurentNode->lCurrentDrawMask)
                     || ( GLI_BIG_GLOBALS->p_stLastComputedFog  != p_CuurentNode->p_stFogParams)
                   )
                {
 
                    GLI_AfterDraw();
 
                    GLI_BIG_GLOBALS->lCurrentDrawMask   = p_CuurentNode->lCurrentDrawMask ;
                    GLI_BIG_GLOBALS->p_stCurrentTexture = p_CuurentNode->p_TextureOfTheTriangle;
                    /*GLI_BIG_GLOBALS->hCurrentMaterial   = NULL;*/
                    GLI_BIG_GLOBALS->hCurrentMaterial   = p_CuurentNode->p_stMaterial;
                
                    /*
                     * fog
                     */
                    if (p_CuurentNode->p_stFogParams)
                    {
                        GLI_BIG_GLOBALS->xFogIsOn = 1;
                        GLI_BIG_GLOBALS->p_stActiveFog = p_CuurentNode->p_stFogParams;
                    }
                    else
                    {
                        GLI_BIG_GLOBALS->p_stLastComputedFog = NULL;
                        GLI_BIG_GLOBALS->p_stActiveFog = NULL;
                        GLI_BIG_GLOBALS->xFogIsOn = 0;
                    }
 
                    /*GLI_AfterDraw();*/
                    GLI_BeforeDraw();
 
                    GLI_vDoTransparentTextureSelection(GLI_BIG_GLOBALS );
                }
                if (p_CuurentNode -> lCurrentDrawMask & GLI_C_lIsGouraud )
                    GLI_vDrawZSortedTriangle(p_CuurentNode -> p_ThreePoints);
                else
                    GLI_vDrawZSortedQuad(p_CuurentNode -> p_ThreePoints);
 
                p_CuurentNode = p_CuurentNode -> p_NextNode;
 
            }
            *(p_TableEntry++) = NULL;
        }
    }
 
    GLI_AfterDraw();
    GLI_DRV_xClearViewingList();
}
 
 
 
 
/**********************************************************************************************/
/* Name: GLI_DRV_xSendElementTIToClip_TRIANGLES*/
/* Goal: Draw an element indexed triangles..*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GLI_DRV_xSendElementTIToClip_TRIANGLES( GEO_tdstElementIndexedTriangles *p_stLocalElementIndexedTriangle , GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT)
{
    ACP_tdxIndex xTriangleCounter ;
    
#ifdef SGL2
    long AMirrorIsDetectedSave;
    AMirrorIsDetectedSave = GLI_BIG_GLOBALS->lAMirrorIsDetected;
    GLI_BIG_GLOBALS->lAMirrorIsDetected &= 0xffffffff - 2;
#endif
 
    p_stCurrentElementIndexedTriangle = p_stLocalElementIndexedTriangle;
 
 
 
    GLI_ReComputeClippingMask();
 
    p_stGlobaleMT -> lCurrentDrawMask |= GLI_C_lIsGouraud;
    
    fConstantMirrorZValue = 10.0f;
 
    GLI_M_ClearFuncList();
 
    /* -----------------------------------------------------------------------------------*/
    /* First function*/
    /* ------------------------------------------------------------------------------------*/
    GLI_M_AddFunc(GLI_vComputeXYZ);
	ulFuncMask |= Flag_GLI_vComputeXYZ;
 
    /* -----------------------------------------------------------------------------------*/
    /* Set UV*/
    /* ------------------------------------------------------------------------------------*/
    /*if (p_stGlobaleMT-> p_stCurrentTexture != NULL)*/
    {
        if (!(p_stGlobaleMT->lCurrentDrawMask & GLI_C_lIsNotChromed))
            GLI_M_AddFunc(GLI_vSetChromeUVW);
        else
            GLI_M_AddFunc(GLI_vSetNormalUVW);
    }
    
    /* -----------------------------------------------------------------------------------*/
    /* Fog effect*/
    /* ------------------------------------------------------------------------------------*/
    if (GLI_BIG_GLOBALS->xFogIsOn) 
    {
        GLI_M_AddFunc(GLI_vSetSpecular);
		ulFuncMask |= Flag_GLI_vSetSpecular;
	}
 
    /* ------------------------------------------------------------------------------------*/
    /* MIRROR - WATER CLIPPING - OTHER CLIPPING ..... */
    /* ------------------------------------------------------------------------------------*/
    /* It coould be here*/
 
    /* -----------------------------------------------------------------------------------*/
    /* First CullingZ */
    /* ------------------------------------------------------------------------------------*/
    if (GLI_BIG_GLOBALS -> lClippingModeMask & GLI_C_ClipMaskZ) {
        GLI_M_AddFunc(GLI_FastZCull);
		ulFuncMask |= Flag_GLI_FastZCull;
	}
 
    /* -----------------------------------------------------------------------------------*/
    /* First Mirror Culling*/
    /* ------------------------------------------------------------------------------------*/
    if (!(GLI_BIG_GLOBALS -> lCurrentDrawMask & GLI_C_lNotHideWhatIsUnderWater)) {
        GLI_M_AddFunc(GLI_FastMirrorCulling);
		ulFuncMask |= Flag_GLI_FastMirrorCulling;
	}
 
    /* -----------------------------------------------------------------------------------*/
    /* culing X Y*/
    /* ------------------------------------------------------------------------------------*/
    if (GLI_BIG_GLOBALS -> lClippingModeMask & GLI_C_lCLIP_ALL)
    {
        if ( (GLI_BIG_GLOBALS -> lClippingModeMask & GLI_C_lCLIP_ALL) == GLI_C_lCLIP_ALL ) {
            GLI_M_AddFunc(GLI_bCullingXYALL);
			ulFuncMask |= Flag_GLI_bCullingXYALL;
		}
        else
        {
            switch (GLI_BIG_GLOBALS -> lClippingModeMask & (GLI_C_ClipMaskXMin | GLI_C_ClipMaskXMax ))
            {
            case 0:break;
            case GLI_C_ClipMaskXMin:GLI_M_AddFunc(GLI_bCullingXMin);
									ulFuncMask |= Flag_GLI_bCullingXMin;
									break;
            case GLI_C_ClipMaskXMax:GLI_M_AddFunc(GLI_bCullingXMax);
									ulFuncMask |= Flag_GLI_bCullingXMax;
									break;
            case GLI_C_ClipMaskXMin + GLI_C_ClipMaskXMax:GLI_M_AddFunc(GLI_bCullingXMax_XMin);
									ulFuncMask |= Flag_GLI_bCullingXMax_XMin;
									break;
            }
            switch (GLI_BIG_GLOBALS -> lClippingModeMask & (GLI_C_ClipMaskYMin | GLI_C_ClipMaskYMax ))
            {
            case 0:break;
            case GLI_C_ClipMaskYMin:GLI_M_AddFunc(GLI_bCullingYMin);
									ulFuncMask |= Flag_GLI_bCullingYMin;
									break;
            case GLI_C_ClipMaskYMax:GLI_M_AddFunc(GLI_bCullingYMax);
									ulFuncMask |= Flag_GLI_bCullingYMax;
									break;
            case GLI_C_ClipMaskYMin + GLI_C_ClipMaskYMax:GLI_M_AddFunc(GLI_bCullingYMax_YMin);
									ulFuncMask |= Flag_GLI_bCullingYMax_YMin;
									break;
            }
        }
    }
 
    /* ------------------------------------------------------------------------------------*/
    /* MIRROR - WATER CLIPPING - OTHER CLIPPING ..... Done after culling*/
    /* ------------------------------------------------------------------------------------*/
    if (GLI_BIG_GLOBALS -> lClippingModeMask & GLI_C_ClipMaskWater)
    {
        if (GLI_BIG_GLOBALS -> lCurrentDrawMask & GLI_C_lNotHideWhatIsUnderWater) {
            GLI_M_AddFunc(GLI_FastWaterCLipping);
			ulFuncMask |= Flag_GLI_FastWaterCLipping;
		}
        else {
            GLI_M_AddFunc(GLI_FastMirrorCLipping);
			ulFuncMask |= Flag_GLI_FastMirrorCLipping;
		}
    }
 
    /* ------------------------------------------------------------------------------------*/
    /* Z CLIPPING;*/
    /* ------------------------------------------------------------------------------------*/
    if (GLI_BIG_GLOBALS -> lClippingModeMask & GLI_C_ClipMaskZ) {
        GLI_M_AddFunc(GLI_vZClipping);
		ulFuncMask |= Flag_GLI_vZClipping;
	}
 
    
    /* ------------------------------------------------------------------------------------*/
    /* BACKFACE INIT;*/
    /* ------------------------------------------------------------------------------------*/
    if (p_stGlobaleMT -> lCurrentDrawMask & GLI_C_lIsTestingBackface)
    {
        if ((p_stGlobaleMT -> lHierachDrawMask  & GLI_C_lIsNotDrawingInMirror) ?
			(p_stGlobaleMT -> lCurrentDrawMask & GLI_C_lNotInvertBackfaces) :
			!(p_stGlobaleMT -> lCurrentDrawMask & GLI_C_lNotInvertBackfaces) ) {
            GLI_M_AddFunc(GLI_TestBackfaceClockwise);
			ulFuncMask |= Flag_GLI_TestBackfaceClockwise;
		}
        else { /* reverse */
            GLI_M_AddFunc(GLI_TestBackfaceCounterClockwize);
			ulFuncMask |= Flag_GLI_TestBackfaceCounterClockwize;
		}
    }
 
    /* ------------------------------------------------------------------------------------*/
    /* XY CLIPPING..*/
    /* ------------------------------------------------------------------------------------*/
#define GLI_C_lCUT_ALL (GLI_C_CutMaskXMin | GLI_C_CutMaskXMax | GLI_C_CutMaskYMin | GLI_C_CutMaskYMax )
    if (GLI_BIG_GLOBALS -> lClippingModeMask & GLI_C_lCUT_ALL)
    {
        switch (GLI_BIG_GLOBALS -> lClippingModeMask & (GLI_C_CutMaskXMin | GLI_C_CutMaskXMax ))
        {
        case 0:break;
        case GLI_C_CutMaskXMin + GLI_C_CutMaskXMax:GLI_M_AddFunc(GLI_XMaxCLipping);
												   ulFuncMask |= Flag_GLI_XMaxCLipping;
		/* STM - fallthrough - was already here*/
        case GLI_C_CutMaskXMin:GLI_M_AddFunc(GLI_XMinCLipping);
							   ulFuncMask |= Flag_GLI_XMinCLipping;
							   break;
        case GLI_C_CutMaskXMax:GLI_M_AddFunc(GLI_XMaxCLipping);
							   ulFuncMask |= Flag_GLI_XMaxCLipping;
							   break;
        }
        switch (GLI_BIG_GLOBALS -> lClippingModeMask & (GLI_C_CutMaskYMin | GLI_C_CutMaskYMax ))
        {
        case 0:break;
        case GLI_C_CutMaskYMin + GLI_C_CutMaskYMax:GLI_M_AddFunc(GLI_YMinCLipping);
												   ulFuncMask |= Flag_GLI_YMinCLipping;
		/* STM - fallthrough - was already here*/
        case GLI_C_CutMaskYMax:GLI_M_AddFunc(GLI_YMaxCLipping);
							   ulFuncMask |= Flag_GLI_YMaxCLipping;
								break;
        case GLI_C_CutMaskYMin:GLI_M_AddFunc(GLI_YMinCLipping);
							   ulFuncMask |= Flag_GLI_YMinCLipping;
								break;
        }
    }
 
    /* ------------------------------------------------------------------------------------*/
    /* COMPUTE COLOR & UVW INIT;*/
    /* ------------------------------------------------------------------------------------*/
    if (p_stGlobaleMT-> p_stCurrentTexture != NULL)
    {
        /*
		if (GLI_BIG_GLOBALS->lAMirrorIsDetected & 2) 
        {
            GLI_M_AddFunc(GLI_vComputeMirrorUVW);
		    ulFuncMask |= Flag_GLI_vComputeMirrorUVW;
		}
        else
		*/
        {
            if ( p_stGlobaleMT->p_stCurrentTexture->lIncrementIsEnable )
            {
                fAddU = p_stGlobaleMT-> p_stCurrentTexture -> fAddU;
                fAddV = p_stGlobaleMT-> p_stCurrentTexture -> fAddV;
                if ((fAddU != 0.0f) || (fAddV != 0.0f)) 
                {
                    GLI_M_AddFunc(GLI_vComputeMovingUVW);
				    ulFuncMask |= Flag_GLI_vComputeMovingUVW;
				}
                else 
                {
                    GLI_M_AddFunc(GLI_vComputeNormalUVW);
				    ulFuncMask |= Flag_GLI_vComputeNormalUVW;
				}
            }
            else
            {
                GLI_M_AddFunc(GLI_vComputeNormalUVW);
				ulFuncMask |= Flag_GLI_vComputeNormalUVW;
            }
        }
 
        /* ------------------------------------------------------------------------------------*/
        /* special function for mirror texture*/
        /* ------------------------------------------------------------------------------------*/
        if (p_stGlobaleMT->p_stCurrentTexture->ucCylingMode & GLI_C_lMirrorU )
            GLI_M_AddFunc(GLI_vAlignUForMirrorTexture);
        if (p_stGlobaleMT->p_stCurrentTexture->ucCylingMode & GLI_C_lMirrorV )
            GLI_M_AddFunc(GLI_vAlignVForMirrorTexture);
        
    };
 
    
 
    /* ------------------------------------------------------------------------------------*/
    /* Draw Triangle Func init*/
    /* ------------------------------------------------------------------------------------*/
    GLI_vAddDrawFunc();

    /* ------------------------------------------------------------------------------------*/
    /* Add empty func */
    /* ------------------------------------------------------------------------------------*/
    GLI_M_AddFunc( GLI_fn_LastFunc );

    /* ------------------------------------------------------------------------------------*/
    /* GO */
    /* ------------------------------------------------------------------------------------*/
    GLI_BeforeDraw();
    {
		p_stCurrentTriangle   = p_stLocalElementIndexedTriangle -> d_stListOfFacesTripled;
		p_stCurrentTriangleUV = p_stLocalElementIndexedTriangle -> d_stListOfFacesTripledIndexUV;
		xTriangleCounter = p_stLocalElementIndexedTriangle -> xNbFaces;
 
        /*{
            
        /*
        if (xTriangleCounter == 24) 
        {
            if ( (GLI_BIG_GLOBALS->p_stCurrentTexture) && (strnicmp(GLI_BIG_GLOBALS->p_stCurrentTexture->a255_cFileName + 28, "petard", 6) == 0) )
            {
                long                lPointIndex;
                MTH3D_tdstVector    *pstPoint;
                float               dY, dX, dZ;
 
                pstPoint = GLI_BIG_GLOBALS->p_stObj->d_stListOfPoints + 53;
                if (pstPoint->xY < -.5)
                {
                    lPointIndex = 12;
                    while (lPointIndex--);
                    {
                        dX = 0.005 * pstPoint->xX / (pstPoint->xY + 0.1);
                        pstPoint->xX -= dX;
                        dZ = 0.005 * (pstPoint->xZ - 0.1) / (pstPoint->xY + 0.1);
                        pstPoint->xZ-= dZ;
                        pstPoint->xY += 0.005;
                        pstPoint++;
                    }
                }
 
            }
        }
        }
        */
 
/*		if (ulFuncMask == MaskBigFunc1)*/
/*			BigFunc1(xTriangleCounter);*/
/*		else */
		{
			/* normal */
			while ( xTriangleCounter -- )
			{
#if !defined(PRESS_DEMO)
				PRF_MDRV_vSetIndependantVariable( PRF_C_ulIdpDisplayedTriangle , 0 );
#endif /* PRESS_DEMO */
				GLI_M_CallFirstFunc();
#if !defined(PRESS_DEMO)
				if( PRF_MDRV_lGetIndependantVariable( PRF_C_ulIdpDisplayedTriangle ) )
				{
					PRF_MDRV_vIncreaseVariable( PRF_C_ulVarFaces + PRF_MDRV_lGetIndependantVariable( PRF_C_ulIdpDynOrSta ), PRF_C_pvDisplayed, 1 );
					PRF_MDRV_vSetIndependantVariable( PRF_C_ulIdpDisplayedFaces, 1 );
				}
#endif /* PRESS_DEMO */
				p_stCurrentTriangle ++;
				p_stCurrentTriangleUV ++;
			}
		}
    }
    GLI_AfterDraw();
 
#ifdef SGL2
    GLI_BIG_GLOBALS->lAMirrorIsDetected  = AMirrorIsDetectedSave ;
#endif
}
 
/**********************************************************************************************/
/* Name: GLI_DRV_xSendSpriteToClip_TRIANGLES*/
/* Goal: Clip a sprite and draw it*/
/* Code: Vincent Lhullier*/
/* OPTIMMIZED : No*/
/**********************************************************************************************/
void GLI_DRV_xSendSpriteToClip_TRIANGLES( GLI_tdstAligned2DVector *a4_st2DVertex, GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT)
{
    ACP_tdst2DUVValues      stUV[3];
    GEO_tdstTripledIndex    stTriangle[2] = { {0,1,2}, {3,2,0} };
 
    p_stGlobaleMT->lCurrentDrawMask |= GLI_C_lIsGouraud;
   
    GLI_M_ClearFuncList();
 
    /* -----------------------------------------------------------------------------------*/
    /* Fog effect*/
    /* ------------------------------------------------------------------------------------*/
    if (GLI_BIG_GLOBALS->xFogIsOn) 
        GLI_M_AddFunc(GLI_vSetSpecular);
 
    /* -----------------------------------------------------------------------------------*/
    /* First CullingZ */
    /* ------------------------------------------------------------------------------------*/
    GLI_M_AddFunc(GLI_FastZCull);
    GLI_M_AddFunc(GLI_bCullingXYALL);
    GLI_M_AddFunc(GLI_vZClipping);
    GLI_M_AddFunc(GLI_XMaxCLipping);
    GLI_M_AddFunc(GLI_XMinCLipping);
    GLI_M_AddFunc(GLI_YMaxCLipping);
    GLI_M_AddFunc(GLI_YMinCLipping);
    GLI_M_AddFunc(GLI_vComputeNormalUVW);
 
    /* ------------------------------------------------------------------------------------*/
    /* Draw Triangle Func init*/
    /* ------------------------------------------------------------------------------------*/
    GLI_vAddDrawFunc();

    /* ------------------------------------------------------------------------------------*/
    /* Add empty func */
    /* ------------------------------------------------------------------------------------*/
    GLI_M_AddFunc( GLI_fn_LastFunc );

    
    /* ------------------------------------------------------------------------------------*/
    /* GO */
    /* ------------------------------------------------------------------------------------*/
    GLI_BeforeDraw();
    {
        SetX( CurrentDestXYZ[0], a4_st2DVertex[0].xX );
        SetY( CurrentDestXYZ[0], a4_st2DVertex[0].xY );
        SetZ( CurrentDestXYZ[0], a4_st2DVertex[0].xOoZ );
        SetX( CurrentDestXYZ[1], a4_st2DVertex[1].xX );
        SetY( CurrentDestXYZ[1], a4_st2DVertex[1].xY );
        SetZ( CurrentDestXYZ[1], a4_st2DVertex[1].xOoZ );
        SetX( CurrentDestXYZ[2], a4_st2DVertex[2].xX );
        SetY( CurrentDestXYZ[2], a4_st2DVertex[2].xY );
        SetZ( CurrentDestXYZ[2], a4_st2DVertex[2].xOoZ );
 
        /*
        {
            char cCounter;
 
            for ( cCounter = 0; cCounter < 4; cCounter++ )
                if ( (a4_st2DVertex[cCounter].xOoZ <= 0) || (a4_st2DVertex[cCounter].xOoZ > 4) )
                    break;
        }
        */
               
	   
        SetPackedColor( CurrentDestXYZ[0], p_stGlobaleMT->ulColorInitForSprite );
	    SetPackedColor( CurrentDestXYZ[1], p_stGlobaleMT->ulColorInitForSprite );
	    SetPackedColor( CurrentDestXYZ[2], p_stGlobaleMT->ulColorInitForSprite );
    
        d_stVirtualUV[0] = &stUV[0];
        d_stVirtualUV[1] = &stUV[1];
        d_stVirtualUV[2] = &stUV[2];
 
        stUV[0].xU = 1.0f;
        stUV[0].xV = 1.0f;
        stUV[1].xU = 0.0f;
        stUV[1].xV = 1.0f;
        stUV[2].xU = 0.0f;
        stUV[2].xV = 0.0f;
 
        p_stCurrentTriangle = stTriangle;
        
        GLI_M_CallFirstFunc();
 
        SetX( CurrentDestXYZ[0], a4_st2DVertex[3].xX);
        SetY( CurrentDestXYZ[0], a4_st2DVertex[3].xY);
        SetZ( CurrentDestXYZ[0], a4_st2DVertex[3].xOoZ);
        SetX( CurrentDestXYZ[1], a4_st2DVertex[2].xX);
        SetY( CurrentDestXYZ[1], a4_st2DVertex[2].xY);
        SetZ( CurrentDestXYZ[1], a4_st2DVertex[2].xOoZ);
        SetX( CurrentDestXYZ[2], a4_st2DVertex[0].xX);
        SetY( CurrentDestXYZ[2], a4_st2DVertex[0].xY);
        SetZ( CurrentDestXYZ[2], a4_st2DVertex[0].xOoZ);
	   
        SetPackedColor( CurrentDestXYZ[0], p_stGlobaleMT->ulColorInitForSprite );
	    SetPackedColor( CurrentDestXYZ[1], p_stGlobaleMT->ulColorInitForSprite );
	    SetPackedColor( CurrentDestXYZ[2], p_stGlobaleMT->ulColorInitForSprite );
    
        d_stVirtualUV[0] = &stUV[0];
        d_stVirtualUV[1] = &stUV[1];
        d_stVirtualUV[2] = &stUV[2];
 
        stUV[0].xU = 1.0f;
        stUV[0].xV = 0.0f;
        stUV[1].xU = 0.0f;
        stUV[1].xV = 0.0f;
        stUV[2].xU = 1.0f;
        stUV[2].xV = 1.0f;
 
        p_stCurrentTriangle++;
        
        GLI_M_CallFirstFunc();
    }
    GLI_AfterDraw();
}
 
/* Only used for tests (infodesign research), because this is definitly NOT optimized. */
void GLI_DRV_xSendSingleTriangleToClip_TRIANGLES( GLI_tdstAligned2DVector *a3_st2DVertex, ACP_tdst2DUVValues *a3_stUV, GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT)
{
    GEO_tdstTripledIndex    stTriangle = {0,1,2};
 
    p_stGlobaleMT->lCurrentDrawMask |= GLI_C_lIsGouraud;
   
    GLI_M_ClearFuncList();
 
    /* -----------------------------------------------------------------------------------*/
    /* Fog effect*/
    /* ------------------------------------------------------------------------------------*/
    if (GLI_BIG_GLOBALS->xFogIsOn) 
        GLI_M_AddFunc(GLI_vSetSpecular);
 
    /* -----------------------------------------------------------------------------------*/
    /* First CullingZ */
    /* ------------------------------------------------------------------------------------*/
    GLI_M_AddFunc(GLI_FastZCull);
    GLI_M_AddFunc(GLI_bCullingXYALL);
    GLI_M_AddFunc(GLI_vZClipping);
    GLI_M_AddFunc(GLI_XMaxCLipping);
    GLI_M_AddFunc(GLI_XMinCLipping);
    GLI_M_AddFunc(GLI_YMaxCLipping);
    GLI_M_AddFunc(GLI_YMinCLipping);
    GLI_M_AddFunc(GLI_vComputeNormalUVW);
 
    /* ------------------------------------------------------------------------------------*/
    /* Draw Triangle Func init*/
    /* ------------------------------------------------------------------------------------*/
    GLI_vAddDrawFunc();
 
    /* ------------------------------------------------------------------------------------*/
    /* Add empty func */
    /* ------------------------------------------------------------------------------------*/
    GLI_M_AddFunc( GLI_fn_LastFunc );
 
    
    /* ------------------------------------------------------------------------------------*/
    /* GO */
    /* ------------------------------------------------------------------------------------*/
    GLI_BeforeDraw();
    {
        SetX( CurrentDestXYZ[0], a3_st2DVertex[0].xX );
        SetY( CurrentDestXYZ[0], a3_st2DVertex[0].xY );
        SetZ( CurrentDestXYZ[0], a3_st2DVertex[0].xOoZ );
        SetX( CurrentDestXYZ[1], a3_st2DVertex[1].xX );
        SetY( CurrentDestXYZ[1], a3_st2DVertex[1].xY );
        SetZ( CurrentDestXYZ[1], a3_st2DVertex[1].xOoZ );
        SetX( CurrentDestXYZ[2], a3_st2DVertex[2].xX );
        SetY( CurrentDestXYZ[2], a3_st2DVertex[2].xY );
        SetZ( CurrentDestXYZ[2], a3_st2DVertex[2].xOoZ );
 
        SetPackedColor( CurrentDestXYZ[0], 0xffffffff );
        SetPackedColor( CurrentDestXYZ[1], 0xffffffff );
        SetPackedColor( CurrentDestXYZ[2], 0xffffffff );
    
        d_stVirtualUV[0] = &a3_stUV[0];
        d_stVirtualUV[1] = &a3_stUV[1];
        d_stVirtualUV[2] = &a3_stUV[2];
 
        p_stCurrentTriangle = &stTriangle;
 
        GLI_M_CallFirstFunc();
    }
    GLI_AfterDraw();
}
 
 
/**********************************************************************************************/
/* Name: GLI_lCullListOfPoints*/
/* Goal: return 0 if it's sure that this list is invisible*/
/* Code: Philippe Vimont */
/* OPTIMMIZED : No*/
/**********************************************************************************************/
long GLI_lCullListOfPoints (GLD_tdstViewportAttributes *p_stVpt,long lNbPoints,GLI_tdstAligned2DVector *p_st2DVertex)
{
    long CullCounter;
    GLI_tdstAligned2DVector *p_VertexCmp;
    *(float *)&fX_CMP_Optimize = 640.0f;
    *(float *)&fY_CMP_Optimize = 480.0f;
 
    p_VertexCmp = p_st2DVertex;
    CullCounter = 0;
    p_st2DVertex[8].xX = 320.0f;
    while ((p_VertexCmp++) -> xX < 0) CullCounter++;
    if (CullCounter == 8) return 0;
    
    p_VertexCmp = p_st2DVertex;
    CullCounter = 0;
    while (*(long *)&(p_VertexCmp++)->xX > fX_CMP_Optimize) CullCounter++;
    if (CullCounter == 8) return 0;
    
    p_VertexCmp = p_st2DVertex;
    CullCounter = 0;
    p_st2DVertex[8].xY = 240.0f;
    while ((p_VertexCmp++)->xY < 0) CullCounter++;
    if (CullCounter == 8) return 0;
    
    p_VertexCmp = p_st2DVertex;
    CullCounter = 0;
    while (*(long *)&(p_VertexCmp++)->xY > fY_CMP_Optimize) CullCounter++;
    if (CullCounter == 8) return 0;
    /* mmmmouais..*/
    return (1);
}
 
 
#ifdef __cplusplus
} /*extern "C"*/
#endif
    
