/*
Tested with LINT
*/
#define MTH_LOW
 
#include "gli_st.h"
#include "GLI_Defn.h"
#include "mater_st.h"
#include "light_st.h"
#include "PvObj_st.h"
#include "material.h"
#include "GeoSprit.h"
#include "proj.h"
#include "linear.h"
#include "vpt3D.h"
#include "camera.h"
#include "DLLInter.h"
 
#include "sprite.h"

#include "GLI.h"
#include "sct.h"

#ifdef __cplusplus
extern "C" 
{
#endif
 
 
/*
 =======================================================================================
    External & prototypes     
 =======================================================================================
 */

extern GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BIG_GLOBALS;
extern ACP_tdxHandleOfMaterial                  gs_hDefaultMaterial;

extern void             GLI_vDoMaterialSelection(GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT);
extern ACP_tdxBool      HIE_fn_bIsSegmentIntersectedInCameraSector (POS_tdstCompletePosition *p_stCameraPos, POS_tdstCompletePosition *p_stSPOPos) ;
extern float            GLI_vGetGlobalAlpha(void) ;
extern void             GLI_vSetGlobalAlpha(float) ;
extern unsigned long    fn_ulGetTrameNumber(void) ;

/*
 * for AGO 
 */
extern unsigned char    g_bHasTextureAnimationFinished ;
extern MTH_tdxReal      g_BaseTimeForParticleAnimation ;
extern unsigned char    g_bHasTextureAnimationFinished ;
extern unsigned char    g_bTakeCareOfAnimationCoordination ;
extern unsigned char    g_bOneShotAnim ;

 
/*
 =======================================================================================
     Globals
 =======================================================================================
 */
/*
 * for lens flare
 */
tdstLensFlareTab    g_stLensFlare ;
void                *gp_vLensFlareRef = NULL;
 
/*
 =======================================================================================
     Function for Lens flare
 =======================================================================================
 */

void GLI_vSetLensFlareRef ( void *p_vRef ) 
{
    gp_vLensFlareRef = p_vRef ;
}

char GLI_cRegisterLensFlare (void *p_vRef) 
{
    long i ;
 
    if ( p_vRef == NULL )
        return (-1) ;
 
    for ( i=0 ; i<g_stLensFlare.lNumberOfLensFlare ; i++ )
    {
        if ( g_stLensFlare.p_vReference[i] == p_vRef ) 
        {
            return ((char)i) ;
        }
    }
 
    if ( g_stLensFlare.lNumberOfLensFlare < GLI_C_MaxLensFlare) 
    {
        g_stLensFlare.p_vReference[g_stLensFlare.lNumberOfLensFlare] = p_vRef ;
        g_stLensFlare.lApparitionTrame[g_stLensFlare.lNumberOfLensFlare] = fn_ulGetTrameNumber() ;
        g_stLensFlare.lCounter[g_stLensFlare.lNumberOfLensFlare] = 0 ;
        g_stLensFlare.bIntersect[g_stLensFlare.lNumberOfLensFlare] = 0 ;
        g_stLensFlare.lNumberOfLensFlare++ ;
        return (g_stLensFlare.lNumberOfLensFlare - 1) ;
    }
    
    return (-1) ;
}
 
void GLI_vUnregisterLensFlare(void *p_vRef)
{
    int i ;
 
    if ( p_vRef == NULL )
        return ;
 
    for ( i=0 ; i<g_stLensFlare.lNumberOfLensFlare ; i++ )
    {
        if ( g_stLensFlare.p_vReference[i] == p_vRef ) 
        {
            if ( i+1 < g_stLensFlare.lNumberOfLensFlare ) 
            {
                memcpy ( &g_stLensFlare.p_vReference[i], &g_stLensFlare.p_vReference[i+1], (g_stLensFlare.lNumberOfLensFlare-i)*sizeof(void *) ) ;
            }
            g_stLensFlare.lNumberOfLensFlare -- ;
            break ;
        }
    }  
}

long GLI_lLensFlareExist(void *p_vRef) 
{
    long i ;
    
    if ( p_vRef == NULL )
        return (-1) ;
 
    for ( i=0 ; i<g_stLensFlare.lNumberOfLensFlare ; i++ )
    {
        if ( g_stLensFlare.p_vReference[i] == p_vRef ) 
            return (i) ;
    }
    return (-1) ;
}

void GLI_vInitLensFlare (void) 
{
  g_stLensFlare.lNumberOfLensFlare = 0 ;
}

/*
 ----------------------------------------------------------------------------------------
  Description   : Draw specific sprite : lens flare as in Unreal game
  Author        : JM Drouaud
  ---------------------------------------------------------------------------------------
 */
void GLI_vDrawLensFlare 
        ( 
            GLD_tdstViewportAttributes *p_stVpt ,
            GEO_tdstGeometricObject *p_stObj ,
            GEO_tdstIndexedSprite *p_stISpr ,
            GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT
        ) 
{
    GLI_tdstAligned3DVector stScaledPt[3];
    GLI_tdstAligned2DVector a4_st2DVertex[4];
    ACP_tdxIndex            xSpriteNumber;
    unsigned long           xSaveDrawMsk;
    unsigned long           lTrame ;
    char                    cLensFlare ;
    float                   alpha, percent ;
    ACP_tdxBool             bIntersected ;
    
    cLensFlare = (char) GLI_lLensFlareExist( gp_vLensFlareRef );
    lTrame = fn_ulGetTrameNumber() ;            
  
    if ( ( (lTrame & 0x1) ^ (cLensFlare & 0x1) ) ) 
    {
        bIntersected = HIE_fn_bIsSegmentIntersectedInCameraSector (p_stGlobaleMT->gs_st_CameraMatrix, p_stGlobaleMT->gs_st_CurrentMatrix) ;
        if ( cLensFlare >= 0 ) 
        {
            if ( g_stLensFlare.bIntersect[cLensFlare] != bIntersected )
                g_stLensFlare.lCounter[cLensFlare] = 0 ;
 
            g_stLensFlare.bIntersect[cLensFlare] = bIntersected ;
        }
    }
    else 
    {            
        if ( cLensFlare >= 0 ) 
        {
            if ( lTrame - g_stLensFlare.lApparitionTrame[cLensFlare] < GLI_C_lMaxTimeForLensFlare ) 
            {
                bIntersected = g_stLensFlare.bIntersect[cLensFlare] ;
            }
            else 
            {
                bIntersected = HIE_fn_bIsSegmentIntersectedInCameraSector (p_stGlobaleMT->gs_st_CameraMatrix, p_stGlobaleMT->gs_st_CurrentMatrix) ;
                if ( g_stLensFlare.bIntersect[cLensFlare] != bIntersected )
                    g_stLensFlare.lCounter[cLensFlare] = 0 ;
                g_stLensFlare.bIntersect[cLensFlare] = bIntersected ;
            }
        }
        else 
        {
            return ;
        }
    }
    percent = 1.0f ;
  
    if ( bIntersected ) 
    {
        lTrame -= g_stLensFlare.lApparitionTrame[cLensFlare] ;
        if ( cLensFlare >= 0 ) 
        {
            if ( lTrame < GLI_C_lMaxTimeForLensFlare ) 
            {
                percent = (float)(GLI_C_lMaxTimeForLensFlare -  lTrame) / GLI_C_lMaxTimeForLensFlare ;
            }
            else 
            {
                GLI_vUnregisterLensFlare (gp_vLensFlareRef) ;
                return ;
            }
        }
        else 
        {
            return ;
        }
    }
    else 
    {
        cLensFlare = GLI_cRegisterLensFlare(gp_vLensFlareRef) ;
        g_stLensFlare.lApparitionTrame[cLensFlare] = lTrame ;
        if ( g_stLensFlare.lCounter[cLensFlare] < 4 ) 
        {
            percent = (float)(g_stLensFlare.lCounter[cLensFlare]) / GLI_C_lMaxTimeForLensFlare ;
            g_stLensFlare.lCounter[cLensFlare]++ ;
        }
   }   
 
    xSpriteNumber = 0;
  
    stScaledPt[0].xX = p_stISpr -> hSprite -> d_xSizeOfSprite[xSpriteNumber].xX;
    stScaledPt[0].xY = 0.0;
    stScaledPt[1].xX = 0.0;
    stScaledPt[1].xY = -p_stISpr -> hSprite -> d_xSizeOfSprite[xSpriteNumber].xY;
  
    if (!POS_fn_ulIsNotScaledMatrix ( &p_stGlobaleMT -> gs_st_CurrentMatrixMultiplyedWithCameraMatrix))
    {
        MTH_tdxReal xScaleX;
        MTH_tdxReal xScaleY;
        xScaleX = POS_fn_xGetXScale(&(p_stGlobaleMT->gs_st_CurrentMatrixMultiplyedWithCameraMatrix));
        xScaleY = POS_fn_xGetYScale(&(p_stGlobaleMT->gs_st_CurrentMatrixMultiplyedWithCameraMatrix));
    
        stScaledPt[0].xX = xScaleX * p_stISpr -> hSprite -> d_xSizeOfSprite[xSpriteNumber].xX;
        stScaledPt[1].xY = xScaleY * (-p_stISpr -> hSprite -> d_xSizeOfSprite[xSpriteNumber].xY);
    }
  
    a4_st2DVertex [0] . xX = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX + (stScaledPt[0] . xX + stScaledPt[1] . xX)*percent);
    a4_st2DVertex [0] . xY = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY + (stScaledPt[0] . xY + stScaledPt[1] . xY)*percent);
    a4_st2DVertex [1] . xX = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX + (-stScaledPt[0] . xX + stScaledPt[1] . xX)*percent);
    a4_st2DVertex [1] . xY = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY + (-stScaledPt[0] . xY + stScaledPt[1] . xY)*percent);
    a4_st2DVertex [2] . xX = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX + (-stScaledPt[0] . xX - stScaledPt[1] . xX)*percent);
    a4_st2DVertex [2] . xY = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY + (-stScaledPt[0] . xY - stScaledPt[1] . xY)*percent);
    a4_st2DVertex [3] . xX = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX + (stScaledPt[0] . xX - stScaledPt[1] . xX)*percent);
    a4_st2DVertex [3] . xY = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY + (stScaledPt[0] . xY - stScaledPt[1] . xY)*percent);
 
    if ( percent < 100 ) 
    {
        alpha = GLI_vGetGlobalAlpha() * percent ;
        GLI_vSetGlobalAlpha( alpha ) ;
    }
 
    p_stGlobaleMT -> hCurrentMaterial = GMT_fn_hGetVisualMaterial(p_stISpr -> hSprite -> d_hMaterial[xSpriteNumber]);
  
    xSaveDrawMsk = p_stGlobaleMT -> lHierachDrawMask ;
    p_stGlobaleMT -> lHierachDrawMask &= ~GLI_C_lIsTestingBackface;
    p_stGlobaleMT->ulSpecularColorForSprite = ((unsigned long *) p_stGlobaleMT->GLI_aDEF_stColorsRLIS)[p_stISpr -> xCenterPoint];
    GLI_vDoMaterialSelection(p_stGlobaleMT);
    GLI_DRV_vSendSpriteToClip( a4_st2DVertex , MTH_M_xLongToReal(1), p_stGlobaleMT);   
 
    gp_vLensFlareRef = NULL ;
    p_stGlobaleMT -> lHierachDrawMask = xSaveDrawMsk;
}

/*
 =======================================================================================
    Indexed sprite functions
 =======================================================================================
 */

/*
 ----------------------------------------------------------------------------------------
  Description   : Draw indexed sprite
                  This function assumes that scale is always diagonal
  Author        : Steve McCalla
  ---------------------------------------------------------------------------------------
 */
void GLI_vDrawIndexedSprite 
    ( 
        GLD_tdstViewportAttributes *p_stVpt ,
        GEO_tdstGeometricObject *p_stObj ,
        GEO_tdstIndexedSprite *p_stISpr ,
        GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT
    )
{
    GLI_tdstAligned3DVector stScaledPt[3];
    GLI_tdstAligned2DVector a4_st2DVertex  [4];
    GLI_tdstAligned2DVector a2_st2DVertexLocal[3];
    ACP_tdxIndex            xSpriteNumber;
    MTH_tdxReal             xTempZ;
    unsigned long           xSaveDrawMsk;
    
    xSpriteNumber = 0;
    
    if (    (p_stISpr -> hSprite == NULL)  
         || ( (p_stGlobaleMT->GLI_ScreenPoint + p_stISpr->xCenterPoint)->xOoZ < 0.0f)
         || ( p_stISpr->hSprite->d_xSpriteDrawMode[xSpriteNumber] & GEO_C_lSpriteDrawDisable) )
        return;
 
    assert (p_stISpr->hSprite->xNbSprites == 1);
    assert (!(p_stISpr->hSprite->d_xSpriteDrawMode[xSpriteNumber] & GEO_C_lSpriteDrawMode2DRotativ));
    assert (p_stISpr->stSize.xX == 1.0);
    assert (p_stISpr->stSize.xY == 1.0);
 
    stScaledPt[0].xX = p_stISpr->hSprite->d_xSizeOfSprite[xSpriteNumber].xX;
    stScaledPt[0].xY = 0.0;
    stScaledPt[1].xX = 0.0;
    stScaledPt[1].xY = -p_stISpr->hSprite->d_xSizeOfSprite[xSpriteNumber].xY;
    stScaledPt[2].xX = 0.0;
    stScaledPt[2].xY = 0.0;
 
    if ( (p_stISpr->hSprite->d_xSpriteDrawMode[xSpriteNumber] & GEO_C_lSpriteDrawModeLensFlare) ) 
    {
        GLI_vDrawLensFlare(p_stVpt, p_stObj, p_stISpr, p_stGlobaleMT) ;
        return ;
    }
 
    if (!POS_fn_ulIsNotScaledMatrix ( &p_stGlobaleMT -> gs_st_CurrentMatrixMultiplyedWithCameraMatrix))
    {
        MTH_tdxReal xScaleX;
        MTH_tdxReal xScaleY;
        xScaleX = POS_fn_xGetXScale(&(p_stGlobaleMT->gs_st_CurrentMatrixMultiplyedWithCameraMatrix));
        xScaleY = POS_fn_xGetYScale(&(p_stGlobaleMT->gs_st_CurrentMatrixMultiplyedWithCameraMatrix));

        stScaledPt[0].xX = xScaleX * p_stISpr->hSprite->d_xSizeOfSprite[xSpriteNumber].xX;
        stScaledPt[1].xY = xScaleY * (-p_stISpr->hSprite->d_xSizeOfSprite[xSpriteNumber].xY);
    }
 
    xTempZ = p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint[p_stISpr->xCenterPoint].xZ;
 
    stScaledPt[0].xZ = xTempZ;
    stScaledPt[1].xZ = xTempZ;
    stScaledPt[2].xZ = xTempZ;
 
    if (p_stISpr->hSprite->d_xSpriteDrawMode[xSpriteNumber] & GEO_C_lSpriteDrawMode2DScaled) 
    {
        GLI_xSerialProjectionNoTrans ( (( GLI_tdstSpecificAttributesFor3D *)p_stVpt->p_vSpecificToXD)->p_stCam, 3, stScaledPt, a2_st2DVertexLocal);
		a4_st2DVertex[0].xX = p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xX - a2_st2DVertexLocal[0].xX - a2_st2DVertexLocal[1].xX + a2_st2DVertexLocal[2].xX;
		a4_st2DVertex[0].xY = p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xY - a2_st2DVertexLocal[0].xY - a2_st2DVertexLocal[1].xY + a2_st2DVertexLocal[2].xY;
		a4_st2DVertex[1].xX = p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xX + a2_st2DVertexLocal[0].xX - a2_st2DVertexLocal[1].xX + a2_st2DVertexLocal[2].xX;
		a4_st2DVertex[1].xY = p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xY + a2_st2DVertexLocal[0].xY - a2_st2DVertexLocal[1].xY + a2_st2DVertexLocal[2].xY;
		a4_st2DVertex[2].xX = p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xX + a2_st2DVertexLocal[0].xX + a2_st2DVertexLocal[1].xX + a2_st2DVertexLocal[2].xX;
		a4_st2DVertex[2].xY = p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xY + a2_st2DVertexLocal[0].xY + a2_st2DVertexLocal[1].xY + a2_st2DVertexLocal[2].xY;
		a4_st2DVertex[3].xX = p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xX - a2_st2DVertexLocal[0].xX + a2_st2DVertexLocal[1].xX + a2_st2DVertexLocal[2].xX;
		a4_st2DVertex[3].xY = p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xY - a2_st2DVertexLocal[0].xY + a2_st2DVertexLocal[1].xY + a2_st2DVertexLocal[2].xY;
	}
	else 
    {
		a4_st2DVertex[0].xX = (float)(p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xX + stScaledPt[0].xX + stScaledPt[1].xX);
		a4_st2DVertex[0].xY = (float)(p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xY + stScaledPt[0].xY + stScaledPt[1].xY);
		a4_st2DVertex[1].xX = (float)(p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xX - stScaledPt[0].xX + stScaledPt[1].xX);
		a4_st2DVertex[1].xY = (float)(p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xY - stScaledPt[0].xY + stScaledPt[1].xY);
		a4_st2DVertex[2].xX = (float)(p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xX - stScaledPt[0].xX - stScaledPt[1].xX);
		a4_st2DVertex[2].xY = (float)(p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xY - stScaledPt[0].xY - stScaledPt[1].xY);
		a4_st2DVertex[3].xX = (float)(p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xX + stScaledPt[0].xX - stScaledPt[1].xX);
		a4_st2DVertex[3].xY = (float)(p_stGlobaleMT->GLI_ScreenPoint[ p_stISpr->xCenterPoint ].xY + stScaledPt[0].xY - stScaledPt[1].xY);
	}
 
    p_stGlobaleMT -> hCurrentMaterial = GMT_fn_hGetVisualMaterial(p_stISpr -> hSprite -> d_hMaterial[xSpriteNumber]);

    xSaveDrawMsk = p_stGlobaleMT->lHierachDrawMask ;
    p_stGlobaleMT->lHierachDrawMask &= ~GLI_C_lIsTestingBackface;
        
    p_stGlobaleMT->ulSpecularColorForSprite = ((unsigned long *) p_stGlobaleMT->GLI_aDEF_stColorsRLIS)[p_stISpr->xCenterPoint];
    GLI_vDoMaterialSelection(p_stGlobaleMT);
    GLI_DRV_vSendSpriteToClip( a4_st2DVertex , p_stGlobaleMT->GLI_ScreenPoint[p_stISpr->xCenterPoint].xOoZ, p_stGlobaleMT);

    p_stGlobaleMT->lHierachDrawMask = xSaveDrawMsk;
}

/*
 ----------------------------------------------------------------------------------------
  Description   : pick indexed sprite
                  return's !0 if p_stScreenCoord is in the sprite.
  ---------------------------------------------------------------------------------------
 */
#define GLI_M_bIsOnTheLeft(a,b) ( (a4_st2DVertex[b].xY - a4_st2DVertex[a].xY) * (p_stScreenCoord->xX - a4_st2DVertex[a].xX) > (a4_st2DVertex[b].xX - a4_st2DVertex[a].xX) * (p_stScreenCoord->xY - a4_st2DVertex[a].xY) )
 
long GLI_vPickIndexedSprite 
    ( 
        GLD_tdstViewportAttributes *p_stVpt ,
        GEO_tdstGeometricObject *p_stObj ,
        GEO_tdstIndexedSprite *p_stISpr , 
        MTH2D_tdstVector *p_stScreenCoord,
        GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT
    )
{
#ifdef _DEBUG
    ACP_tdxHandleOfMaterial hVisualMat;
    GLI_tdstAligned3DVector stScaledPt[3];
    GLI_tdstAligned2DVector a4_st2DVertex  [4];
    GLI_tdstAligned2DVector a2_st2DVertexLocal[3];
    ACP_tdxIndex            xSpriteNumber;
 	MTH_tdxReal             xTempZ; /* make this a MTH_XXX something or another*/

	xSpriteNumber = 0;
    
	if ((p_stISpr -> hSprite == NULL) || ((p_stGlobaleMT -> GLI_ScreenPoint + p_stISpr -> xCenterPoint) -> xOoZ < 0.0f) || (p_stISpr -> hSprite -> d_xSpriteDrawMode[xSpriteNumber] & GEO_C_lSpriteDrawDisable))
		return 0;
 
	assert (p_stISpr -> hSprite -> xNbSprites == 1);
	assert (!(p_stISpr -> hSprite -> d_xSpriteDrawMode[xSpriteNumber] & GEO_C_lSpriteDrawMode2DRotativ));
    assert (p_stISpr -> stSize.xX == 1.0);
    assert (p_stISpr -> stSize.xY == 1.0);
 
	stScaledPt[0].xX = p_stISpr -> hSprite -> d_xSizeOfSprite[xSpriteNumber].xX;
	stScaledPt[0].xY = 0.0;
	stScaledPt[1].xX = 0.0;
	stScaledPt[1].xY = -p_stISpr -> hSprite -> d_xSizeOfSprite[xSpriteNumber].xY;
	stScaledPt[2].xX = 0.0;
	stScaledPt[2].xY = 0.0;
 
	if (!POS_fn_ulIsNotScaledMatrix ( &p_stGlobaleMT -> gs_st_CurrentMatrixMultiplyedWithCameraMatrix))
	{
		MTH_tdxReal xScaleX;
		MTH_tdxReal xScaleY;
		xScaleX = POS_fn_xGetXScale(&(p_stGlobaleMT->gs_st_CurrentMatrixMultiplyedWithCameraMatrix));
		xScaleY = POS_fn_xGetYScale(&(p_stGlobaleMT->gs_st_CurrentMatrixMultiplyedWithCameraMatrix));
 
		stScaledPt[0].xX = xScaleX * p_stISpr -> hSprite -> d_xSizeOfSprite[xSpriteNumber].xX;
		stScaledPt[1].xY = xScaleY * (-p_stISpr -> hSprite -> d_xSizeOfSprite[xSpriteNumber].xY);
	}
 
	xTempZ = p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint[p_stISpr->xCenterPoint].xZ;
 
	stScaledPt[0].xZ = xTempZ;
	stScaledPt[1].xZ = xTempZ;
	stScaledPt[2].xZ = xTempZ;
 
	if (p_stISpr -> hSprite -> d_xSpriteDrawMode[xSpriteNumber] & GEO_C_lSpriteDrawMode2DScaled) 
    {
 
		GLI_xSerialProjectionNoTrans ( (( GLI_tdstSpecificAttributesFor3D *)p_stVpt->p_vSpecificToXD)->p_stCam, 3, stScaledPt, a2_st2DVertexLocal);
		a4_st2DVertex [0] . xX = p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX - a2_st2DVertexLocal[0] . xX - a2_st2DVertexLocal[1] . xX + a2_st2DVertexLocal[2] . xX ;
		a4_st2DVertex [0] . xY = p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY - a2_st2DVertexLocal[0] . xY - a2_st2DVertexLocal[1] . xY + a2_st2DVertexLocal[2] . xY ;
		a4_st2DVertex [1] . xX = p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX + a2_st2DVertexLocal[0] . xX - a2_st2DVertexLocal[1] . xX + a2_st2DVertexLocal[2] . xX ;
		a4_st2DVertex [1] . xY = p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY + a2_st2DVertexLocal[0] . xY - a2_st2DVertexLocal[1] . xY + a2_st2DVertexLocal[2] . xY ;
		a4_st2DVertex [2] . xX = p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX + a2_st2DVertexLocal[0] . xX + a2_st2DVertexLocal[1] . xX + a2_st2DVertexLocal[2] . xX ;
		a4_st2DVertex [2] . xY = p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY + a2_st2DVertexLocal[0] . xY + a2_st2DVertexLocal[1] . xY + a2_st2DVertexLocal[2] . xY ;
		a4_st2DVertex [3] . xX = p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX - a2_st2DVertexLocal[0] . xX + a2_st2DVertexLocal[1] . xX + a2_st2DVertexLocal[2] . xX ;
		a4_st2DVertex [3] . xY = p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY - a2_st2DVertexLocal[0] . xY + a2_st2DVertexLocal[1] . xY + a2_st2DVertexLocal[2] . xY ;
	}
	else 
    {
		a4_st2DVertex [0] . xX = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX + stScaledPt[0] . xX + stScaledPt[1] . xX);
		a4_st2DVertex [0] . xY = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY + stScaledPt[0] . xY + stScaledPt[1] . xY);
		a4_st2DVertex [1] . xX = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX - stScaledPt[0] . xX + stScaledPt[1] . xX);
		a4_st2DVertex [1] . xY = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY - stScaledPt[0] . xY + stScaledPt[1] . xY);
		a4_st2DVertex [2] . xX = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX - stScaledPt[0] . xX - stScaledPt[1] . xX);
		a4_st2DVertex [2] . xY = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY - stScaledPt[0] . xY - stScaledPt[1] . xY);
		a4_st2DVertex [3] . xX = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xX + stScaledPt[0] . xX - stScaledPt[1] . xX);
		a4_st2DVertex [3] . xY = (float)(p_stGlobaleMT->GLI_ScreenPoint  [p_stISpr -> xCenterPoint] . xY + stScaledPt[0] . xY - stScaledPt[1] . xY);
	}
    
    hVisualMat=GMT_fn_hGetVisualMaterial(p_stISpr -> hSprite -> d_hMaterial[xSpriteNumber]);
    if (GLI_M_bIsOnTheLeft(0,1))
        if (GLI_M_bIsOnTheLeft(1,2))
            if (GLI_M_bIsOnTheLeft(2,3))
                if (GLI_M_bIsOnTheLeft(3,0))
                    return ( 1 );
  
#endif
    return(0);
}


/*
 =======================================================================================
    2D Sprite
 =======================================================================================
 */
 
/*
 ----------------------------------------------------------------------------------------
  Description   : draw 2D sprite
  ---------------------------------------------------------------------------------------
 */
void GLI_vDraw2DSprite( GLD_tdstViewportAttributes *p_stVpt ,MTH_tdxReal  xXMin,MTH_tdxReal  xXMax,MTH_tdxReal  xYMin,MTH_tdxReal  xYMax,ACP_tdxHandleOfMaterial hMaterial)
{
    GLI_tdstAligned2DVector     a4_st2DVertex  [5];
    GEO_tdstColor               stLocalColor;
    
    stLocalColor.xG = stLocalColor.xB = stLocalColor.xR = 0.0f;
    GLI_xSetMaterialAmbientCoef(hMaterial , &stLocalColor);
    stLocalColor.xG = stLocalColor.xB = stLocalColor.xR = 1.0f;
    GLI_xSetMaterialDiffuseCoef(hMaterial , &stLocalColor);
    stLocalColor.xG = stLocalColor.xB = stLocalColor.xR = 0.0f;
    GLI_xSetMaterialSpecularCoef(hMaterial , 0 , &stLocalColor);
 
    a4_st2DVertex[0].xX = (float)(long)xXMin;
    a4_st2DVertex[0].xY = (float)(long)xYMin;
    a4_st2DVertex[0].xOoZ =1.0f;
    a4_st2DVertex[1].xX = (float)(long)xXMax;
    a4_st2DVertex[1].xY = (float)(long)xYMin;
    a4_st2DVertex[1].xOoZ =1.0f;
    a4_st2DVertex[2].xX = (float)(long)xXMax;
    a4_st2DVertex[2].xY = (float)(long)xYMax;
    a4_st2DVertex[2].xOoZ =1.0f;
    a4_st2DVertex[3].xX = (float)(long)xXMin;
    a4_st2DVertex[3].xY = (float)(long)xYMax;
    a4_st2DVertex[3].xOoZ =1.0f;
    GLI_BIG_GLOBALS->hCurrentMaterial = hMaterial;
    GLI_BIG_GLOBALS->hCurrentMaterial->xMaterialType = 0xFFFFFFFF - GLI_C_lIsTestingBackface;
    GLI_BIG_GLOBALS->lCurrentDrawMask = 0xFFFFFFFF - GLI_C_lIsTestingBackface;
    GLI_BIG_GLOBALS->lHierachDrawMask = 0xFFFFFFFF - GLI_C_lIsTestingBackface;
    GLI_vDoMaterialSelection(GLI_BIG_GLOBALS );
    GLI_DRV_vSendSpriteToClip( a4_st2DVertex , 1.0f/*1.0f / GLI_C_xZClippingNear*/, GLI_BIG_GLOBALS);
}
  
/*
 ----------------------------------------------------------------------------------------
  Description   : draw 2D sprite with UV mapping coordinates
  ---------------------------------------------------------------------------------------
 */
void GLI_vDraw2DSpriteWithUV
    ( 
        GLD_tdstViewportAttributes *p_stVpt ,
        MTH_tdxReal  xXMin,
        MTH_tdxReal  xXMax,
        MTH_tdxReal  xYMin,
        MTH_tdxReal  xYMax,
        MTH_tdxReal  xUMin,
        MTH_tdxReal  xUMax,
        MTH_tdxReal  xVMin,
        MTH_tdxReal  xVMax,
        ACP_tdxHandleOfMaterial hMaterial
    )
{
    GLI_tdstAligned2DVector a4_st2DVertex  [5];
    MTH_tdxReal             a4_stUVVertex  [10];
    GEO_tdstColor           stLocalColor;
    
    stLocalColor.xG = stLocalColor.xB = stLocalColor.xR = 0.0f;
    GLI_xSetMaterialAmbientCoef(hMaterial , &stLocalColor);
    stLocalColor.xG = stLocalColor.xB = stLocalColor.xR = 1.0f;
    GLI_xSetMaterialDiffuseCoef(hMaterial , &stLocalColor);
    stLocalColor.xG = stLocalColor.xB = stLocalColor.xR = 0.0f;
    GLI_xSetMaterialSpecularCoef(hMaterial , 0 , &stLocalColor);
 
    a4_st2DVertex[0].xX = (float)(long)xXMin;
    a4_st2DVertex[0].xY = (float)(long)xYMin;
    a4_st2DVertex[0].xOoZ =1.0f;
    a4_st2DVertex[1].xX = (float)(long)xXMax;
    a4_st2DVertex[1].xY = (float)(long)xYMin;
    a4_st2DVertex[1].xOoZ =1.0f;
    a4_st2DVertex[2].xX = (float)(long)xXMax;
    a4_st2DVertex[2].xY = (float)(long)xYMax;
    a4_st2DVertex[2].xOoZ =1.0f;
    a4_st2DVertex[3].xX = (float)(long)xXMin;
    a4_st2DVertex[3].xY = (float)(long)xYMax;
    a4_st2DVertex[3].xOoZ =1.0f;

    a4_stUVVertex[0]   = xUMin;
    a4_stUVVertex[0+1] = xVMin;
    a4_stUVVertex[2]   = xUMax;
    a4_stUVVertex[2+1] = xVMin;
    a4_stUVVertex[4]   = xUMax;
    a4_stUVVertex[4+1] = xVMax;
    a4_stUVVertex[6]   = xUMin;
    a4_stUVVertex[6+1] = xVMax;
    
    GLI_BIG_GLOBALS->hCurrentMaterial = hMaterial;
    GLI_BIG_GLOBALS->hCurrentMaterial->xMaterialType = 0xFFFFFFFF - GLI_C_lIsTestingBackface;
    GLI_BIG_GLOBALS->lCurrentDrawMask = 0xFFFFFFFF - GLI_C_lIsTestingBackface;
    GLI_BIG_GLOBALS->lHierachDrawMask = 0xFFFFFFFF - GLI_C_lIsTestingBackface;
    
    GLI_vDoMaterialSelection(GLI_BIG_GLOBALS );
    //GLI_DRV_vSendSpriteToClipWithUV ( a4_st2DVertex ,a4_stUVVertex ,1.0f / GLI_C_xZClippingNear,GLI_BIG_GLOBALS);
    GLI_DRV_vSendSpriteToClipWithUV ( a4_st2DVertex ,a4_stUVVertex , 1.0f, GLI_BIG_GLOBALS);
}

/*
 ----------------------------------------------------------------------------------------
  Description   : draw 2D sprite but coordinates are percent of screen
  ---------------------------------------------------------------------------------------
 */

char            g_GLI_bForceAAAColor = 0;
unsigned char   g_GLI_ForcedAAAColor[3];

float           GLI_g_fZValueForSprite = 1.0f;

void GLI_vDraw2DSpriteWithPercent( GLD_tdstViewportAttributes *_p_stViewport, float XMin, float YMin, float XMax, float YMax, ACP_tdxHandleOfMaterial hMaterial)
{
    float                   x1, x2, y1, y2; 
    GLI_tdstAligned2DVector a4_st2DVertex[4];

    x1 = (XMin / 100.0f) * _p_stViewport->dwWidth;
    x2 = (XMax / 100.0f) * _p_stViewport->dwWidth;
    y1 = (YMin / 100.0f) * _p_stViewport->dwHeight;
    y2 = (YMax / 100.0f) * _p_stViewport->dwHeight;

    a4_st2DVertex[0].xX = x2;
    a4_st2DVertex[0].xY = y1;
    a4_st2DVertex[0].xOoZ =1.0f;
    a4_st2DVertex[1].xX = x1;
    a4_st2DVertex[1].xY = y1;
    a4_st2DVertex[1].xOoZ =1.0f;
    a4_st2DVertex[2].xX = x1;
    a4_st2DVertex[2].xY = y2;
    a4_st2DVertex[2].xOoZ =1.0f;
    a4_st2DVertex[3].xX = x2;
    a4_st2DVertex[3].xY = y2;
    a4_st2DVertex[3].xOoZ =1.0f;

    GLI_BIG_GLOBALS->hCurrentMaterial = hMaterial;
    GLI_BIG_GLOBALS->lCurrentDrawMask =
    GLI_BIG_GLOBALS->lHierachDrawMask =
    GLI_BIG_GLOBALS->hCurrentMaterial->xMaterialType = 0xFFFFFFFF - GLI_C_lIsTestingBackface - GLI_C_lIsNotGrided /* - GLI_C_lIsEnableZSorting*/ ;

    GLI_vDoMaterialSelection(GLI_BIG_GLOBALS );

    if( g_GLI_bForceAAAColor )
    {
		/* Keep computed alpha */
		GLI_BIG_GLOBALS->ulColorInitForSprite &= 0xff000000;
		/* Force color */
        GLI_BIG_GLOBALS->ulColorInitForSprite |= g_GLI_ForcedAAAColor[0] << 16 | g_GLI_ForcedAAAColor[1] << 8 | g_GLI_ForcedAAAColor[2];
    }
    GLI_DRV_vSendSpriteToClip( a4_st2DVertex , GLI_g_fZValueForSprite/*1.0f / GLI_C_xZClippingNear*/, GLI_BIG_GLOBALS);
}

/*
 ----------------------------------------------------------------------------------------
  Description   : Display a black transparent rectangle 
  in :  a3_fPosition  -> X,Y in percent of screen size (Z is ignored) of UpperLeft
        a3_fDirection -> X,Y in percent of screen size (Z is ignored) of LowerRight
        Transparency  -> Opacity of the black frame
 ----------------------------------------------------------------------------------------
 */
void GLI_vDisplayFrame(	float *a3_fPosition, float *a3_fDirection, float _f_Transparency, GLD_tdstViewportAttributes *_p_stViewport )
{
    float f_SaveAlpha;

    f_SaveAlpha = GLI_vGetGlobalAlpha();
    GLI_vSetGlobalAlpha( _f_Transparency );

    gs_hDefaultMaterial->stAmbient.xR = gs_hDefaultMaterial->stAmbient.xG = gs_hDefaultMaterial->stAmbient.xB = 0;
    GLI_vDraw2DSpriteWithPercent( _p_stViewport, a3_fPosition[0], a3_fPosition[1], a3_fDirection[0], a3_fDirection[1] , gs_hDefaultMaterial );

    GLI_vSetGlobalAlpha( f_SaveAlpha );
}
  

/*
 =======================================================================================
    Special functions for AGO
 =======================================================================================
 */
  
/*
 ----------------------------------------------------------------------------------------
  Description   : draw a sprite (used by ago)
 ----------------------------------------------------------------------------------------
 */
int GLI_vDrawWorldSprite
    (
        float                      *a3_fPosition, 
        void                       *pVisualMaterial,
		float                       fscaleX, 
        float                       fscaleY, 
        GLD_tdstViewportAttributes *_p_stViewport, 
		unsigned long               AnimTime
    )
{
    GLI_tdstCamera          *p_stCam ;
    MTH3D_tdstVector        stSrc, stDest;
    unsigned long           xSaveDrawMsk;
    float                   xOoZ;
    GLI_tdstAligned2DVector st2DDest, st2DVertex[4] ;
    GLI_tdstAligned3DVector stScaledPt[3];
    GLI_tdstAligned2DVector a3_st2DVertexLocal[3];
  
    p_stCam = (( GLI_tdstSpecificAttributesFor3D *)_p_stViewport->p_vSpecificToXD)->p_stCam ;
 
	g_bTakeCareOfAnimationCoordination = 1;
	g_BaseTimeForParticleAnimation = (float)AnimTime;
	g_bOneShotAnim=1;
    g_bHasTextureAnimationFinished = 0 ;
  
    stSrc.xX = a3_fPosition[0];
    stSrc.xY = a3_fPosition[1];
    stSrc.xZ = a3_fPosition[2];
  
    POS_fn_vMulMatrixVertex( &stDest, &(p_stCam->stMatrix), &stSrc);
    GLI_xSerialProjection (p_stCam, 1, (GLI_tdstAligned3DVector *)&stDest, &st2DDest ) ;
    xOoZ = stDest.xZ ;
 
    stScaledPt[0].xX = fscaleX ;
    stScaledPt[0].xY = 0.0f ;
    stScaledPt[0].xZ = xOoZ ;
    stScaledPt[1].xX = 0.0f ;
    stScaledPt[1].xY = -fscaleY ;
    stScaledPt[1].xZ = xOoZ ;
    stScaledPt[2].xX = 0.0f ;
    stScaledPt[2].xY = 0.0f ;
    stScaledPt[2].xZ = xOoZ ;
 
	GLI_xSerialProjectionNoTrans ( p_stCam, 3, stScaledPt, a3_st2DVertexLocal);
 
    st2DVertex[0].xX = (float)(st2DDest.xX - a3_st2DVertexLocal[0].xX - a3_st2DVertexLocal[1].xX + a3_st2DVertexLocal[2].xX);
    st2DVertex[0].xY = (float)(st2DDest.xY - a3_st2DVertexLocal[0].xY - a3_st2DVertexLocal[1].xY + a3_st2DVertexLocal[2].xY);
    st2DVertex[1].xX = (float)(st2DDest.xX + a3_st2DVertexLocal[0].xX - a3_st2DVertexLocal[1].xX + a3_st2DVertexLocal[2].xX);
    st2DVertex[1].xY = (float)(st2DDest.xY + a3_st2DVertexLocal[0].xY - a3_st2DVertexLocal[1].xY + a3_st2DVertexLocal[2].xY);
    st2DVertex[2].xX = (float)(st2DDest.xX + a3_st2DVertexLocal[0].xX + a3_st2DVertexLocal[1].xX + a3_st2DVertexLocal[2].xX);
    st2DVertex[2].xY = (float)(st2DDest.xY + a3_st2DVertexLocal[0].xY + a3_st2DVertexLocal[1].xY + a3_st2DVertexLocal[2].xY);
    st2DVertex[3].xX = (float)(st2DDest.xX - a3_st2DVertexLocal[0].xX + a3_st2DVertexLocal[1].xX + a3_st2DVertexLocal[2].xX);
    st2DVertex[3].xY = (float)(st2DDest.xY - a3_st2DVertexLocal[0].xY + a3_st2DVertexLocal[1].xY + a3_st2DVertexLocal[2].xY);
	   
	g_bTakeCareOfAnimationCoordination=1;
	g_BaseTimeForParticleAnimation = (float)AnimTime;
	g_bOneShotAnim=1;
    g_bHasTextureAnimationFinished = 0 ;
 
    GLI_BIG_GLOBALS->hCurrentMaterial = (ACP_tdxHandleOfMaterial) pVisualMaterial;
    xSaveDrawMsk = GLI_BIG_GLOBALS->lHierachDrawMask ;
    GLI_BIG_GLOBALS->lHierachDrawMask = 0xFFFFFFFF - GLI_C_lIsTestingBackface - GLI_C_lIsNotGrided ;
    /*GLI_BIG_GLOBALS -> lCurrentDrawMask = GLI_BIG_GLOBALS->lHierachDrawMask ;*/
    GLI_vDoMaterialSelection(GLI_BIG_GLOBALS);
  
	*(long *) &GLI_BIG_GLOBALS->xWaterPlaneDistance = 0;
    if ( ( st2DDest.xOoZ > 0 ) && ( st2DDest.xOoZ <= 4 ) )
		GLI_DRV_vSendSpriteToClip( st2DVertex, st2DDest.xOoZ, GLI_BIG_GLOBALS);
    
    GLI_BIG_GLOBALS->lHierachDrawMask = xSaveDrawMsk ;
	g_bTakeCareOfAnimationCoordination=0;
	g_bOneShotAnim=0;  
  
    return (g_bHasTextureAnimationFinished) ;
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : draw a sprite on horizontal plane (World Z axis is a normal of sprite)
 ----------------------------------------------------------------------------------------
 */
int GLI_vDrawWorldPlanarSprite
    ( 
        float                      *a3_fPosition, 
        void                       *pVisualMaterial,
		float                       fscaleX, 
        float                       fscaleY, 
        GLD_tdstViewportAttributes *_p_stViewport, 
		unsigned long               AnimTime
    )
{
	GLI_tdstCamera          *p_stCam ;
    unsigned long           xSaveDrawMsk;
    MTH3D_tdstVector          st3DVertex[5] ;
    GLI_tdstAligned3DVector st3DTurnedVertex[5] ;
    GLI_tdstAligned2DVector st2DVertex[5] ;
 
	p_stCam = (( GLI_tdstSpecificAttributesFor3D *)_p_stViewport->p_vSpecificToXD)->p_stCam ;
 
    st3DVertex[0].xX = a3_fPosition[0] - fscaleX ;
    st3DVertex[0].xY = a3_fPosition[1] - fscaleY ;
    st3DVertex[0].xZ = a3_fPosition[2] ;
    st3DVertex[1].xX = a3_fPosition[0] + fscaleX ;
    st3DVertex[1].xY = a3_fPosition[1] - fscaleY ;
    st3DVertex[1].xZ = a3_fPosition[2] ;
    st3DVertex[2].xX = a3_fPosition[0] + fscaleX ;
    st3DVertex[2].xY = a3_fPosition[1] + fscaleY ;
    st3DVertex[2].xZ = a3_fPosition[2] ;
    st3DVertex[3].xX = a3_fPosition[0] - fscaleX ;
    st3DVertex[3].xY = a3_fPosition[1] + fscaleY ;
    st3DVertex[3].xZ = a3_fPosition[2] ;
    st3DVertex[4].xX = a3_fPosition[0] ;
    st3DVertex[4].xY = a3_fPosition[1] ;
    st3DVertex[4].xZ = a3_fPosition[2] ;
 
    memcpy( st3DTurnedVertex, GLI_BIG_GLOBALS->GLI_TurnedScaledDisplecedPoint, 5 );
  
    GLI_xSerialLinearOp ( 5, st3DVertex, GLI_BIG_GLOBALS->GLI_TurnedScaledDisplecedPoint, &(p_stCam->stMatrix) ) ;
    GLI_xSerialProjection (p_stCam ,5 , GLI_BIG_GLOBALS->GLI_TurnedScaledDisplecedPoint, st2DVertex ) ;
 
	g_bTakeCareOfAnimationCoordination  = 1;
	g_BaseTimeForParticleAnimation      = (float)AnimTime;
	g_bOneShotAnim                      = 1;
    g_bHasTextureAnimationFinished      = 0 ;
 
    GLI_BIG_GLOBALS->hCurrentMaterial = (ACP_tdxHandleOfMaterial) pVisualMaterial;
    xSaveDrawMsk = GLI_BIG_GLOBALS->lHierachDrawMask ;
    GLI_BIG_GLOBALS->lHierachDrawMask &= (~GLI_C_lIsTestingBackface & ~GLI_C_lIsNotGrided);
    GLI_BIG_GLOBALS->lCurrentDrawMask = GLI_BIG_GLOBALS->lHierachDrawMask ;
    GLI_vDoMaterialSelection( GLI_BIG_GLOBALS );
  
    *(long *) &GLI_BIG_GLOBALS->xWaterPlaneDistance = 1;
    GLI_DRV_vSendSpriteToClip( st2DVertex,  st2DVertex[4].xOoZ, GLI_BIG_GLOBALS);
    *(long *) &GLI_BIG_GLOBALS->xWaterPlaneDistance = 0;
 
    memcpy( GLI_BIG_GLOBALS->GLI_TurnedScaledDisplecedPoint, st3DTurnedVertex, 5 );
    
    GLI_BIG_GLOBALS->lHierachDrawMask   = xSaveDrawMsk ;
	g_bTakeCareOfAnimationCoordination  = 0;
	g_bOneShotAnim                      = 0;
 
 
 
  return (g_bHasTextureAnimationFinished) ;
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : draw a sprite on plane given by 2 vectors
 ----------------------------------------------------------------------------------------
 */
int GLI_vDrawWorldOrthoPlanarSprite
    (
        float                      *a3_fPosition,
		void                       *pVisualMaterial,
		float                       fscaleX,
		float                       fscaleY,
		GLD_tdstViewportAttributes *_p_stViewport,
		unsigned long               AnimTime,
		MTH3D_tdstVector           *p_stV1,
        MTH3D_tdstVector           *p_stV2
    )
{
	GLI_tdstCamera             *p_stCam ;
	unsigned long               xSaveDrawMsk;
	MTH3D_tdstVector              st3DVertex[5] ;
	GLI_tdstAligned3DVector     st3DTurnedVertex[5] ;
	GLI_tdstAligned2DVector     st2DVertex[5] ;
	float                       x1,x2,y1,y2,z1,z2;
	
	p_stCam = (( GLI_tdstSpecificAttributesFor3D *)_p_stViewport->p_vSpecificToXD)->p_stCam ;
	
	x1=(fscaleX*p_stV1->xX);
	y1=(fscaleX*p_stV1->xY);
	z1=(fscaleX*p_stV1->xZ);
	
	x2=(fscaleY*p_stV2->xX);
	y2=(fscaleY*p_stV2->xY);
	z2=(fscaleY*p_stV2->xZ);
	
	
	st3DVertex[0].xX = a3_fPosition[0] - x1+x2 ;
	st3DVertex[0].xY = a3_fPosition[1] - y1+y2 ;
	st3DVertex[0].xZ = a3_fPosition[2] - z1+z2;
	st3DVertex[1].xX = a3_fPosition[0] + x1+x2 ;
	st3DVertex[1].xY = a3_fPosition[1] + y1+y2;
	st3DVertex[1].xZ = a3_fPosition[2] + z1+z2;
	st3DVertex[2].xX = a3_fPosition[0] + x1-x2 ;
	st3DVertex[2].xY = a3_fPosition[1] + y1-y2 ;
	st3DVertex[2].xZ = a3_fPosition[2] + z1-z2;
	st3DVertex[3].xX = a3_fPosition[0] - x1-x2 ;
	st3DVertex[3].xY = a3_fPosition[1] - y1-y2 ;
	st3DVertex[3].xZ = a3_fPosition[2] - z1-z2;
	st3DVertex[4].xX = a3_fPosition[0] ;
	st3DVertex[4].xY = a3_fPosition[1] ;
	st3DVertex[4].xZ = a3_fPosition[2] ;
 
    memcpy( st3DTurnedVertex, GLI_BIG_GLOBALS->GLI_TurnedScaledDisplecedPoint, 5 * sizeof( GLI_tdstAligned3DVector ) );
	GLI_xSerialLinearOp ( 5, st3DVertex, GLI_BIG_GLOBALS->GLI_TurnedScaledDisplecedPoint, &(p_stCam->stMatrix) ) ;
    GLI_xSerialProjection (p_stCam ,5 , GLI_BIG_GLOBALS->GLI_TurnedScaledDisplecedPoint, st2DVertex ) ;
	
	g_bTakeCareOfAnimationCoordination=1;
	g_BaseTimeForParticleAnimation = (float)AnimTime;
	g_bOneShotAnim=1;
	g_bHasTextureAnimationFinished = 0 ;
	
	GLI_BIG_GLOBALS->hCurrentMaterial = (ACP_tdxHandleOfMaterial) pVisualMaterial;
	xSaveDrawMsk = GLI_BIG_GLOBALS->lHierachDrawMask ;
	GLI_BIG_GLOBALS->lHierachDrawMask &= (~GLI_C_lIsTestingBackface & ~GLI_C_lIsNotGrided);
	GLI_BIG_GLOBALS -> lCurrentDrawMask = GLI_BIG_GLOBALS->lHierachDrawMask ;
	GLI_vDoMaterialSelection(GLI_BIG_GLOBALS);
 
    *(long *) &GLI_BIG_GLOBALS->xWaterPlaneDistance = 1;
	GLI_DRV_vSendSpriteToClip( st2DVertex,  st2DVertex[4].xOoZ, GLI_BIG_GLOBALS);
    *(long *) &GLI_BIG_GLOBALS->xWaterPlaneDistance = 0;
 
    memcpy( GLI_BIG_GLOBALS->GLI_TurnedScaledDisplecedPoint, st3DTurnedVertex, 5 * sizeof( GLI_tdstAligned3DVector ) );
	
	GLI_BIG_GLOBALS->lHierachDrawMask = xSaveDrawMsk ;
	g_bTakeCareOfAnimationCoordination=0;
	g_bOneShotAnim=0;
	
	return (g_bHasTextureAnimationFinished) ;
}
 
ACP_tdxBool fn_bDisplaySky( HIE_tdxHandleToSuperObject hSOSector, HIE_tdxHandleToSuperObject hSOCamera, GLD_tdstViewportAttributes *_p_stViewport )
{
    MTH3D_tdstVector                a3_stVector[3];
    float                           fStartX, fStartY;
    GLI_tdstAligned2DVector         a4_st2DVertex[4];
    MTH_tdxReal                     a8_stUVVertex[8];
    SECT_tdxHandleOfSectorObject    hSectorObject = (SECT_tdxHandleOfSectorObject)HIE_fn_hGetSuperObjectObject( hSOSector );
    long                            lSaveFog;
    static int iDisplaySky = 1;
 
 
    if( ! hSectorObject->pSkyVisualMaterial )
        return FALSE;
 
    if( GetAsyncKeyState( 'L' ) & 0x8000 )
    {
        iDisplaySky = !iDisplaySky;
    }
 
    if( ! iDisplaySky )
        return FALSE;
 
    if( GetAsyncKeyState( 'M' ) & 0x8000 )
    {
        if( GetAsyncKeyState( VK_SHIFT ) & 0x8000 )
            hSectorObject->FogIntensity --;
        else
            hSectorObject->FogIntensity ++;
    }
    
    POS_fn_vGetTransformMatrix(
        HIE_fn_hGetSuperObjectGlobalMatrix(hSOCamera),
        &a3_stVector[0],
        &a3_stVector[1],
        &a3_stVector[2] );

    if( MTH_M_bGreater( MTH3D_M_xGetZofVector( &a3_stVector[0] ), MTH_M_xFloatToReal( 0.9f ) ) )
    {
        fStartX = 0.0f;
    }
    else
    {
        fStartX = -(float)(atan2( MTH3D_M_xGetYofVector( &a3_stVector[0] ), MTH3D_M_xGetXofVector( &a3_stVector[0] ) ) / MTH_C_Pi);
    }
 
    /*fStartX += ((ACP_tdxHandleOfMaterial)hSectorObject->pSkyVisualMaterial)->fAddU;*/

    fStartY = MTH3D_M_xGetZofVector( &a3_stVector[2] ) /*+ ((ACP_tdxHandleOfMaterial)hSectorObject->pSkyVisualMaterial)->fAddV*/;
 
    
    // We fill the destination structure
    a4_st2DVertex[0].xX = (float)_p_stViewport->dwClipLeftInPix;
    a4_st2DVertex[0].xY = (float)_p_stViewport->dwClipTopInPix;
    a4_st2DVertex[1].xX = (float)(_p_stViewport->dwClipRightInPix-1);
    a4_st2DVertex[1].xY = (float)_p_stViewport->dwClipTopInPix;
    a4_st2DVertex[2].xX = (float)(_p_stViewport->dwClipRightInPix-1);
    a4_st2DVertex[2].xY = (float)(_p_stViewport->dwClipBottomInPix-1);
    a4_st2DVertex[3].xX = (float)_p_stViewport->dwClipLeftInPix;
    a4_st2DVertex[3].xY = (float)(_p_stViewport->dwClipBottomInPix-1);
 
    a8_stUVVertex[0] = fStartX;
    a8_stUVVertex[1] = fStartY;
    a8_stUVVertex[2] = fStartX + 1.0f;
    a8_stUVVertex[3] = fStartY;
    a8_stUVVertex[4] = fStartX + 1.0f;
    a8_stUVVertex[5] = fStartY + 1.0f;
    a8_stUVVertex[6] = fStartX;
    a8_stUVVertex[7] = fStartY + 1.0f;
 
    GLI_vSetGlobalAlpha( 255.0f );
    GLI_BIG_GLOBALS->hCurrentMaterial = hSectorObject->pSkyVisualMaterial;
    GLI_BIG_GLOBALS->lCurrentDrawMask =
    GLI_BIG_GLOBALS->lHierachDrawMask =
    GLI_BIG_GLOBALS->hCurrentMaterial->xMaterialType = 0xFFFFFFFF - GLI_C_lIsTestingBackface /*- GLI_C_lIsEnableZSorting - GLI_C_lIsWriteZBuffer - GLI_C_lIsNotComputeSpecular*/;
    /* Set fog to ITERATED_ALPHA */
    lSaveFog = GLI_BIG_GLOBALS->xFogIsOn;
    GLI_BIG_GLOBALS->xFogIsOn = 2;
    GLI_BIG_GLOBALS->ulSpecularColorForSprite = ((unsigned long)hSectorObject->FogIntensity) << 24;
    GLI_vDoMaterialSelection(GLI_BIG_GLOBALS );
 
    GLI_BIG_GLOBALS->ulColorInitForSprite = 
        (GLI_BIG_GLOBALS->ulColorInitForSprite & 0x00ffffff) | (((unsigned long)hSectorObject->FogIntensity) << 24);
 
    GLI_DRV_vSetClipWindow( (float)_p_stViewport->dwClipLeftInPix, (float)_p_stViewport->dwClipRightInPix, (float)_p_stViewport->dwClipTopInPix, (float)_p_stViewport->dwClipBottomInPix, GLI_BIG_GLOBALS );
    GLI_DRV_vSendSpriteToClipWithUV( a4_st2DVertex, a8_stUVVertex,  0.00006103515625f, GLI_BIG_GLOBALS);
 
    GLI_BIG_GLOBALS->xFogIsOn = lSaveFog;
    return TRUE;
}

/*
 * For AGOs
 */
void GLI_vDisplayWorldTriangle(
				GLD_tdstViewportAttributes *_p_stVpt,
				float _a3_coordinates[3][3],
				float _a3_uvs[3][2],
				void *_p_stVisualMaterial)
{
	GLI_tdstCamera          *p_stCam ;
	unsigned long           xSaveDrawMsk;
	GLI_tdstAligned3DVector   st3DTurnedVertex[3] ;
	MTH3D_tdstVector          st3DVertex[3] ;
	GLI_tdstAligned2DVector   st2DVertex[3] ;
	ACP_tdst2DUVValues        stUV[3];

	p_stCam = (( GLI_tdstSpecificAttributesFor3D *)_p_stVpt->p_vSpecificToXD)->p_stCam ;

	MTH3D_M_vSetVectorElements( &st3DVertex[0], _a3_coordinates[0][0], _a3_coordinates[0][1], _a3_coordinates[0][2] );
	MTH3D_M_vSetVectorElements( &st3DVertex[1], _a3_coordinates[1][0], _a3_coordinates[1][1], _a3_coordinates[1][2] );
	MTH3D_M_vSetVectorElements( &st3DVertex[2], _a3_coordinates[2][0], _a3_coordinates[2][1], _a3_coordinates[2][2] );
	stUV[0].xU = _a3_uvs[0][0];
	stUV[0].xV = _a3_uvs[0][1];
	stUV[1].xU = _a3_uvs[1][0];
	stUV[1].xV = _a3_uvs[1][1];
	stUV[2].xU = _a3_uvs[2][0];
	stUV[2].xV = _a3_uvs[2][1];

	GLI_xSerialLinearOp ( 3, st3DVertex, st3DTurnedVertex, &(p_stCam->stMatrix) ) ;
	GLI_xSerialProjection (p_stCam, 3, st3DTurnedVertex, st2DVertex ) ;

	GLI_BIG_GLOBALS->hCurrentMaterial = (ACP_tdxHandleOfMaterial) _p_stVisualMaterial;
	xSaveDrawMsk = GLI_BIG_GLOBALS->lHierachDrawMask ;
	GLI_BIG_GLOBALS->lHierachDrawMask &= (~GLI_C_lIsTestingBackface & ~GLI_C_lIsNotGrided);
	GLI_BIG_GLOBALS->lCurrentDrawMask = GLI_BIG_GLOBALS->lHierachDrawMask ;
	GLI_vDoMaterialSelection( GLI_BIG_GLOBALS );

	GLI_DRV_xSendSingleTriangleToClip_TRIANGLES( st2DVertex,  stUV, GLI_BIG_GLOBALS);

	GLI_BIG_GLOBALS->lHierachDrawMask   = xSaveDrawMsk ;
}
 
 
#if defined(USE_PROFILER) && !defined(RETAIL)

#define C_fYMinForFirstBar 1.0f
#define C_fYMinForSecondBar 8.5f

#define C_fBarWidth  10.0f
#define C_fBarHeight 4.0f

static int gs_iTotalEngineDuration = 0;
static int gs_iFlipDuration = 0;
static int gs_bShowFrameRate = 0;
static float gs_fGlobalAlphaForRasters = 128.0f;
static unsigned long a_ulBarColors[] = { 0x0000ff00, 0x00ff0000, 0x000080ff, 0x000000ff };

void GLI_fn_vPrepareShowFrameRate( int _iTotalEngineDuration, int _iFlipDuration )
{
    gs_iTotalEngineDuration = (_iTotalEngineDuration + 5) / 10;
    gs_iFlipDuration = (_iFlipDuration + 5) / 10;
    gs_bShowFrameRate = 1;
}

void GLI_fn_vShowFrameRate( GLD_tdstViewportAttributes *_p_stViewport )
{
    int iCurrentBar;
    unsigned long ulCurrentColor;
    float  fSaveClipYMin = GLI_BIG_GLOBALS->fYMinClipping;
 
    if( gs_bShowFrameRate )
        gs_bShowFrameRate = 0;
    else
        return;

    GLI_vSetGlobalAlpha( gs_fGlobalAlphaForRasters );
    g_GLI_bForceAAAColor = 1;
    GLI_g_fZValueForSprite = 1.0f;
    gs_hDefaultMaterial->stAmbient.xR = gs_hDefaultMaterial->stAmbient.xG = gs_hDefaultMaterial->stAmbient.xB = 0;
    GLI_BIG_GLOBALS->fYMinClipping = 0.0f;
 
    gs_iFlipDuration += gs_iTotalEngineDuration;
 
    /* Display whole bars */
    for( 
        iCurrentBar = 0;
        gs_iTotalEngineDuration >= 1000; 
        gs_iTotalEngineDuration -= 1000, gs_iFlipDuration-=1000, ++iCurrentBar )
    {
        ulCurrentColor = a_ulBarColors[iCurrentBar & 3];
        g_GLI_ForcedAAAColor[0] = (unsigned char)ulCurrentColor;
        g_GLI_ForcedAAAColor[1] = (unsigned char)(ulCurrentColor >> 8);
        g_GLI_ForcedAAAColor[2] = (unsigned char)(ulCurrentColor >> 16);

        /* First bar : time without flip */
        GLI_vDraw2DSpriteWithPercent( _p_stViewport, (float)(iCurrentBar*C_fBarWidth), C_fYMinForFirstBar, (float)(iCurrentBar*C_fBarWidth+C_fBarWidth), C_fYMinForFirstBar+C_fBarHeight, gs_hDefaultMaterial );
        /* Second bar : time with flip */
        GLI_vDraw2DSpriteWithPercent( _p_stViewport, (float)(iCurrentBar*C_fBarWidth), C_fYMinForSecondBar, (float)(iCurrentBar*C_fBarWidth+C_fBarWidth), C_fYMinForSecondBar+C_fBarHeight, gs_hDefaultMaterial );
    }
 
    if( gs_iTotalEngineDuration != 0 )
    {
        /* Draw the last bar (not a whole one) */
        ulCurrentColor = a_ulBarColors[iCurrentBar & 3];
        g_GLI_ForcedAAAColor[0] = (unsigned char)ulCurrentColor;
        g_GLI_ForcedAAAColor[1] = (unsigned char)(ulCurrentColor >> 8);
        g_GLI_ForcedAAAColor[2] = (unsigned char)(ulCurrentColor >> 16);
 
        /* First bar : time without flip */
        GLI_vDraw2DSpriteWithPercent( 
            _p_stViewport, 
            (float)(iCurrentBar*C_fBarWidth), C_fYMinForFirstBar, 
            (float)(iCurrentBar*C_fBarWidth+(gs_iTotalEngineDuration)/(1000/C_fBarWidth)), C_fYMinForFirstBar+C_fBarHeight, gs_hDefaultMaterial );
    }
 
 
    /* if time with flip is greater than time without flip (common case), we display the remaining time */
    for( 
        ; 
        gs_iFlipDuration >= 1000; 
        gs_iFlipDuration -= 1000, ++iCurrentBar )
    {
        ulCurrentColor = a_ulBarColors[iCurrentBar & 3];
        g_GLI_ForcedAAAColor[0] = (unsigned char)ulCurrentColor;
        g_GLI_ForcedAAAColor[1] = (unsigned char)(ulCurrentColor >> 8);
        g_GLI_ForcedAAAColor[2] = (unsigned char)(ulCurrentColor >> 16);

        /* Second bar : time with flip */
        GLI_vDraw2DSpriteWithPercent( _p_stViewport, (float)(iCurrentBar*C_fBarWidth), C_fYMinForSecondBar, (float)(iCurrentBar*C_fBarWidth+C_fBarWidth), C_fYMinForSecondBar+C_fBarHeight, gs_hDefaultMaterial );
    }
 
    if( gs_iFlipDuration != 0 )
    {
        /* Draw the last bar (not a whole one) */
        ulCurrentColor = a_ulBarColors[iCurrentBar & 3];
        g_GLI_ForcedAAAColor[0] = (unsigned char)ulCurrentColor;
        g_GLI_ForcedAAAColor[1] = (unsigned char)(ulCurrentColor >> 8);
        g_GLI_ForcedAAAColor[2] = (unsigned char)(ulCurrentColor >> 16);

        /* First bar : time without flip */
        GLI_vDraw2DSpriteWithPercent( 
            _p_stViewport, 
            (float)(iCurrentBar*C_fBarWidth), C_fYMinForSecondBar, 
            (float)(iCurrentBar*C_fBarWidth+gs_iFlipDuration/(1000/C_fBarWidth)), C_fYMinForSecondBar+C_fBarHeight, gs_hDefaultMaterial );
    }
 
    if( gs_fGlobalAlphaForRasters < 255.0f )
    {
        GLI_xSendListToViewport( _p_stViewport );
        GLI_xClearViewingList();
    }

    GLI_BIG_GLOBALS->fYMinClipping = fSaveClipYMin;
    g_GLI_bForceAAAColor = 0;
    GLI_vSetGlobalAlpha( 255 );
}
#endif /*RETAIL*/
 
#ifdef __cplusplus
} /*extern "C"*/
#endif
