/*
 =======================================================================================
  Name        : Light.c
  Description : function to manage all lights
 =======================================================================================
 */
/*
Tested with LINT
*/
 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#define MTH_LOW
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#include "gli_st.h"
#include "GLI_Defn.h"
#include "light_st.h"
#include "PvObj_st.h"
#include "init_gli.h"
#include "VisuSet.h"
#include "watrplan.h"
#include "linear.h"
#include "vpt3D.h"
#include "light.h"
#include "camera.h"
#include "GliBench.h"
#include "SAI.h"
 
#include "PCS.h"
#include "PO.h"
#include "IPO.h"
 
#include "ISI.h"
 
#include "PRF.h"
 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
#pragma warning( disable : 4133 )
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
/*
 =======================================================================================
	Globals / Externals
 =======================================================================================
 */
GLI_tdstLight           *gs_aDEF_p_CurrentListOfLight[C_lMaxLightInViewport];
long                    gs_CurrentNumberOfLightInViewport;
 
/* test on whole actor */
unsigned char           g_ucTableOfActiveLightsForChar[ C_lMaxLightInViewport ];
 
#ifdef __cplusplus
extern "C"
{
#endif
  
/*
 =======================================================================================
	Manage with table of active light for charachter 
 =======================================================================================
 */
 
/*
 *********************************************************************************************
  Description : set ALL lights activation to the given value
 *********************************************************************************************
 */
void GLI_vResetTableOfActiveLightsForChar(char _cValue)
{
	memset( g_ucTableOfActiveLightsForChar, _cValue, C_lMaxLightInViewport );
}
 
/*
 ********************************************************************************************
  Description : Set the light On/Off for char
 ********************************************************************************************
 */
void GLI_vSetLightActivityForChar( int iNum, unsigned char ucState )
{
	g_ucTableOfActiveLightsForChar[ iNum ] = ucState;
}
 
/*
 ********************************************************************************************
  Description : returns 1 if the light is active
 ********************************************************************************************
 */
ACP_tdxBool GLI_bIsLightActiveForChar( int iNum )
{
	return g_ucTableOfActiveLightsForChar[ iNum ];
}
 
/*
 ********************************************************************************************
  Description : Tests if the ligt affects the sphere
 ********************************************************************************************
 */
ACP_tdxBool GLI_bDoesLightAffectBV( GLI_tdstLight     * p_stLight, MTH3D_tdstVector  * p_stCenter, MTH_tdxReal       xRadius )
{
	switch( p_stLight->lTypeOfLight )
	{
		case GLI_C_lParallelLight:
		case GLI_C_lAmbientLight:
			return 1;
			break;
 
		case GLI_C_lSphericalLight:
		case GLI_C_lHotSpotLight:
			{
				MTH3D_tdstVector stDist, *p_stLightPos = POS_fn_p_stGetTranslationVector(&p_stLight->stMatrix);
				MTH_tdxReal xSquare = MTH_M_xAdd(xRadius, p_stLight->xFar);
  
				MTH3D_M_vSubVector(&stDist, p_stCenter, p_stLightPos);
				return MTH_M_bLess(MTH3D_M_xSqrVector(&stDist), MTH_M_xMul(xSquare, xSquare)) ? 1 : 0;
			}
			break;
 
		case GLI_C_lParallelLight_With_Limit:
			{
				MTH3D_tdstVector stDist, *p_stLightPos = POS_fn_p_stGetTranslationVector(&p_stLight->stMatrix);
				MTH_tdxReal xSquare = MTH_M_xAdd(xRadius, p_stLight->xRadius);
  
				MTH3D_M_vSubVector(&stDist, p_stCenter, p_stLightPos);
				return MTH_M_bLess(MTH3D_M_xSqrVector( &stDist ), MTH_M_xMul(xSquare, xSquare)) ? 1 : 0;
			}
			break;
 
		default:
			return 1;
			break;
	}
}
 
/*
 =======================================================================================
	ZBuffer
 =======================================================================================
 */
  
/* 
 * ZBuffer
 */
/* ------------------------------------------------------------------------------- */
/* ----------------------------- N O T  U S E D ---------------------------------- */
/* ------------------------------------------------------------------------------- */
long GLI_vIsLightZbufferLight(GLI_tdstLight *p_stLight)
{
	return (p_stLight->bThisLightIsZBuffered);
}
 
/* ------------------------------------------------------------------------------- */
/* ----------------------------- N O T  U S E D ---------------------------------- */
/* ------------------------------------------------------------------------------- */
void GLI_vSetLightAsZBufferLight(GLI_tdstLight *p_stLight , long bEnbleDisable)
{
	p_stLight->bThisLightIsZBuffered = bEnbleDisable;
}
  
/*
 ***************************************************************************
 Goal: create a zbuffer for ligth
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 
 Order used for the Z - Buffers of sphericals lights :
 X+ , X-,  Y+ , Y- , Z+ , Z-
 
 ***************************************************************************
 */
/* ------------------------------------------------------------------------------- */
/* ----------------------------- N O T  U S E D ---------------------------------- */
/* ------------------------------------------------------------------------------- */
long GLI_lCreateZBufferForLight(void **p_BufferToCreate, long lSizeX,long lSizeY, GLI_tdstLight *p_stLight )
{
	long lSize;
    
	lSize = 0;
    if (p_stLight->lTypeOfLight == GLI_C_lHotSpotLight)
    {
		lSize = (sizeof ( float ) * (lSizeX * (lSizeY + 2)));
    }
    else
    {
		if (p_stLight->lTypeOfLight == GLI_C_lSphericalLight)
		{
			lSize = (sizeof ( float ) * (lSizeX * lSizeY * 6 + lSizeX * 2) );
		}
    }
    if (lSize == 0) 
		return 0;
    
    MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeZBufferForLight , NULL);
	GEO_M_CPAMalloc(*p_BufferToCreate,float *, lSize ,E_uwGEONotEnoughtMemory );
	if (*p_BufferToCreate == NULL)
      return 0;
 
    (float *) *p_BufferToCreate += lSizeX * sizeof ( float );
    GLI_vSetLightAsZBufferLight(p_stLight , 1);
    return lSize;
}
 
/*
 *******************************************************************************************
 Goal: set ZBuffer of a light
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
/* ------------------------------------------------------------------------------- */
/* ----------------------------- N O T  U S E D ---------------------------------- */
/* ------------------------------------------------------------------------------- */
long GLI_bAssignZBufferToLight(GLI_tdstLight *p_stLight , long lZBufferSizeX,long lZBufferSizeY,float *p_ZBuffer)
{
    p_stLight->stZBuffer . p_stZBufferMap = p_ZBuffer;
    p_stLight->stZBuffer . p_stMiddleZBufferMap = &p_ZBuffer[((lZBufferSizeX)>>1) + ((lZBufferSizeY)>>1) * (lZBufferSizeX)];
    p_stLight->stZBuffer . lSizeX = lZBufferSizeX;
    p_stLight->stZBuffer . lSizeY = lZBufferSizeY;
    return 1;
}
  
/* ------------------------------------------------------------------------------- */
/* ----------------------------- N O T  U S E D ---------------------------------- */
/* ------------------------------------------------------------------------------- */
float *GLI_p_GetPtrOfZBuffer(GLI_tdstLight *p_stLight , long lFaceNumberOfCubeForSphericalLight)
{
	return ( p_stLight->stZBuffer . p_stZBufferMap + lFaceNumberOfCubeForSphericalLight * p_stLight->stZBuffer . lSizeX * p_stLight->stZBuffer . lSizeY );
}
 
/* ------------------------------------------------------------------------------- */
/* ----------------------------- N O T  U S E D ---------------------------------- */
/* ------------------------------------------------------------------------------- */
long GLI_p_GetNumberOfIterationForBuildZBufferOfALight(GLI_tdstLight *p_stLight )
{
    if (p_stLight->lTypeOfLight == GLI_C_lHotSpotLight) 
		return 1;
    if (p_stLight->lTypeOfLight == GLI_C_lSphericalLight) 
		return 6;
	return 0;
}
 
/*
 *******************************************************************************************
 Goal:
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
/* ------------------------------------------------------------------------------- */
/* ----------------------------- N O T  U S E D ---------------------------------- */
/* ------------------------------------------------------------------------------- */
BOOL GLI_bLightBufferisNotBuilding(GLI_tdstLight *p_stLight)
{
    return 0;
}
 
 
/*
 =======================================================================================
	List of ligth
 =======================================================================================
 */
 
/*
 *******************************************************************************************
 Goal: add a light in the list of light in viewport
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
void GLI_vAddLightToViewport(struct GLD_tdstViewportAttributes_ *p_stVpt , GLI_tdstLight *p_stLight )
{
	if (gs_CurrentNumberOfLightInViewport == C_lMaxLightInViewport) 
		return;
    gs_aDEF_p_CurrentListOfLight [gs_CurrentNumberOfLightInViewport++] = p_stLight;
}
 
/*
 *******************************************************************************************
 Goal: pop n lights in the list of light in viewport
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
void GLI_vPopLightsInViewport(struct GLD_tdstViewportAttributes_ *p_stVpt , unsigned long lNbLightsToPop)
{
    gs_CurrentNumberOfLightInViewport -= lNbLightsToPop;
    if (gs_CurrentNumberOfLightInViewport < 0) 
		gs_CurrentNumberOfLightInViewport = 0;
}
 
/*
 *******************************************************************************************
 Goal: clear the list of light in the viewport
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
void GLI_vClearListOfLightInViewport (struct GLD_tdstViewportAttributes_ *p_stVpt)
{
    gs_CurrentNumberOfLightInViewport = 0;
}
 
/*
 *******************************************************************************************
 Goal: Set all ligth in list on or off
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
void GLI_xSetViewportLightsOnOff(unsigned char bOnOff) 
{
	int i;
      
    for (i=0;i<gs_CurrentNumberOfLightInViewport;i++)
		gs_aDEF_p_CurrentListOfLight [i]->bValid = bOnOff;
}
 
/*
 =======================================================================================
	Creation of light 
 =======================================================================================
 */
void GLI_xCreateLight ( GLI_tdstLight **h_stLight , long lTypeOfLight )
{
    MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeGliLight , NULL);
	GEO_M_CPAMalloc(*h_stLight,GLI_tdstLight *,sizeof ( GLI_tdstLight) ,E_uwGEONotEnoughtMemory );
    if ( (*h_stLight) == NULL) 
		return;
      
    (*h_stLight)->lTypeOfLight = lTypeOfLight;
    /*POS_fn_vSetIdentityMatrix ( &(*h_stLight)->stMatrix );*/
    (*h_stLight)->b_lOnOff = 1;
    (*h_stLight)->stColor.xR = 0.8f;
    (*h_stLight)->stColor.xG = 0.8f;
    (*h_stLight)->stColor.xB = 0.8f;
    (*h_stLight)->stColor.xA = 0.8f;
 
	(*h_stLight)->stZBuffer . p_stZBufferMap = NULL;
 
    (*h_stLight)->bValid = 1;
    (*h_stLight)->bIsPainting = 0;
    GLI_vSetObjectLighted(*h_stLight,GLI_C_LightMap | GLI_C_LightPerso);
 
    (*h_stLight)->stBackgroundColor.xR = 0.0f;
    (*h_stLight)->stBackgroundColor.xG = 0.0f;
    (*h_stLight)->stBackgroundColor.xB = 0.0f;
    (*h_stLight)->stBackgroundColor.xA = 0.0f;
}
 
void GLI_vCopyLight(struct GLI_tdstLight_ *p_stLightDst,struct GLI_tdstLight_ *p_stLightSrc)
{
	memcpy(p_stLightDst,p_stLightSrc,sizeof(struct GLI_tdstLight_));
}
 
unsigned long GLI_ulGetLightSize()
{
	return sizeof(GLI_tdstLight);
}
 
 
 
/*
 =======================================================================================
	Save light
 =======================================================================================
 */
void GLI_vStoreLightForInit(struct GLI_tdstLight_ *p_stLight, SAI_tdeFlags eUserFlags)
{
	SAI_fn_bInsertLongInTable((void*)&p_stLight->b_lOnOff, eUserFlags);
    SAI_fn_bInsertLongInTable((void*)&p_stLight->lTypeOfLight,eUserFlags);
    SAI_fn_bInsertMTHRealInTable((void*)&p_stLight->xFar,eUserFlags);
    SAI_fn_bInsertMTHRealInTable((void*)&p_stLight->xNear,eUserFlags);
    SAI_fn_bInsertMTHRealInTable((void*)&p_stLight->xLittleAlpha,eUserFlags);
    SAI_fn_bInsertMTHRealInTable((void*)&p_stLight->xBigAlpha,eUserFlags); 
    SAI_fn_bInsertMTHRealInTable((void*)&p_stLight->xLittleTangent,eUserFlags);
    SAI_fn_bInsertMTHRealInTable((void*)&p_stLight->xBigTangent,eUserFlags);
    SAI_fn_bInsertMTHRealInTable((void*)&p_stLight->stColor.xR,eUserFlags);
    SAI_fn_bInsertMTHRealInTable((void*)&p_stLight->stColor.xG,eUserFlags);
    SAI_fn_bInsertMTHRealInTable((void*)&p_stLight->stColor.xB,eUserFlags);
    SAI_fn_bInsertMTHRealInTable((void*)&p_stLight->stColor.xA,eUserFlags);
	SAI_fn_bInsertCharInTable((void*)&p_stLight->ucObjectLighted,eUserFlags);
}
 
void GLI_vRemoveLightForInit(struct GLI_tdstLight_ *p_stLight,SAI_tdeFlags eUserFlags)
{
	SAI_fn_bRemoveValueFromTable((void*)&p_stLight->b_lOnOff,eUserFlags);
    SAI_fn_bRemoveValueFromTable((void*)&p_stLight->lTypeOfLight,eUserFlags);
    SAI_fn_bRemoveValueFromTable((void*)&p_stLight->xFar,eUserFlags);
    SAI_fn_bRemoveValueFromTable((void*)&p_stLight->xNear,eUserFlags);
    SAI_fn_bRemoveValueFromTable((void*)&p_stLight->xLittleAlpha,eUserFlags);
    SAI_fn_bRemoveValueFromTable((void*)&p_stLight->xBigAlpha,eUserFlags);
    SAI_fn_bRemoveValueFromTable((void*)&p_stLight->xLittleTangent,eUserFlags);
    SAI_fn_bRemoveValueFromTable((void*)&p_stLight->xBigTangent,eUserFlags);
    SAI_fn_bRemoveValueFromTable((void*)&p_stLight->stColor.xR,eUserFlags);
    SAI_fn_bRemoveValueFromTable((void*)&p_stLight->stColor.xG,eUserFlags);
    SAI_fn_bRemoveValueFromTable((void*)&p_stLight->stColor.xB,eUserFlags);
    SAI_fn_bRemoveValueFromTable((void*)&p_stLight->stColor.xA,eUserFlags);
	SAI_fn_bRemoveValueFromTable((void*)&p_stLight->ucObjectLighted,eUserFlags);
}
 
void GLI_vReInitLight(struct GLI_tdstLight_ *p_stLight,SAI_tdeFlags eUserFlags)
{
	SAI_fn_bInitOneValueWhen((void*)&p_stLight->b_lOnOff,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->lTypeOfLight,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->xFar,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->xNear,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->xLittleAlpha,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->xBigAlpha,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->xLittleTangent,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->xBigTangent,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->stColor.xR,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->stColor.xG,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->stColor.xB,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->stColor.xA,eUserFlags);
    SAI_fn_bInitOneValueWhen((void*)&p_stLight->ucObjectLighted,eUserFlags);
}
 
/*
 =======================================================================================
	Ligth structure access function
 =======================================================================================
 */
 
/*
 * other function used by access function
 */
void GLI_vComputeLight_SphereBox(struct	GLI_tdstLight_ *p_stLight)
{
	MTH3D_tdstVector stDist;
  
	if( p_stLight && (p_stLight->lTypeOfLight == GLI_C_lParallelLight_With_Limit) )
	{
		MTH3D_M_vMiddleVector( &p_stLight->xCenterBox, &p_stLight->xExter_Max_Pos, &p_stLight->xExter_Min_Pos );
		MTH3D_M_vSubVector( &stDist, &p_stLight->xExter_Max_Pos, &p_stLight->xExter_Min_Pos );
		p_stLight->xRadius = MTH_M_xDiv( MTH3D_M_xNormVector( &stDist ), MTH_C_2 );
	}
}
 
 
/*
 * Light state
 */
void GLI_xSetLightState ( GLI_tdstLight *p_stLight , long b_lOnOff )
{
	p_stLight->b_lOnOff = b_lOnOff;
}
    
void GLI_xGetLightState ( GLI_tdstLight *p_stLight , long *pb_lOnOff )
{
	*pb_lOnOff = p_stLight->b_lOnOff;
}
 
/*
 * light color
 */
void GLI_xSetLightColor ( GLI_tdstLight *p_stLight, struct GEO_tdstColor_ *p_stColor )
{
	p_stLight->stColor = *p_stColor;
}
    
void GLI_xGetLightColor ( GLI_tdstLight *p_stLight , struct GEO_tdstColor_ *p_stColor )
{
	*p_stColor = p_stLight->stColor;
}
 
/*
 * light matrix
 */
void GLI_xGetLightMatrix ( GLI_tdstLight *p_stLight, POS_tdstCompletePosition *p_stMatrix )
{
	*p_stMatrix = p_stLight->stMatrix;
}
    
void GLI_xSetLightMatrix ( GLI_tdstLight *p_stLight, POS_tdstCompletePosition *p_stMatrix )
{
	p_stLight->stMatrix = *p_stMatrix;
}
 
MTH3D_tdstVector *GLI_p_stGetLightTranslation(GLI_tdstLight *p_stLight)
{
	return POS_fn_p_stGetTranslationVector(&p_stLight->stMatrix);
}
 
 
/*
 * near far parameters
 */
void GLI_vSetLightNearFar ( GLI_tdstLight *p_stLight, MTH_tdxReal xNear, MTH_tdxReal xFar )
{
	p_stLight->xNear = xNear;
    p_stLight->xFar = xFar;
}
    
void GLI_vGetLightNearFar ( GLI_tdstLight *p_stLight, MTH_tdxReal *p_xNear, MTH_tdxReal *p_xFar )
{
	*p_xNear = p_stLight->xNear;
	*p_xFar = p_stLight->xFar;
}
 
/* ligth tangent
 *
 */
void GLI_vSetLightAlphas ( GLI_tdstLight *p_stLight, MTH_tdxReal xLittleAlpha, MTH_tdxReal xBigAlpha)
{
      p_stLight->xLittleAlpha = xLittleAlpha;
      p_stLight->xBigAlpha = xBigAlpha;
      p_stLight->xLittleTangent = MTH_M_xTan( xLittleAlpha * 0.5 );
      p_stLight->xBigTangent = MTH_M_xTan( xBigAlpha * 0.5 );
}
    
void GLI_vGetLightAlphas ( GLI_tdstLight *p_stLight, MTH_tdxReal *p_xLittleAlpha, MTH_tdxReal *p_xBigAlpha)
{
	*p_xLittleAlpha = p_stLight->xLittleAlpha;
	*p_xBigAlpha = p_stLight->xBigAlpha;
}
    
/*
 * light type
 */
long GLI_lGetLightType ( GLI_tdstLight *p_stLight )
{
	return (p_stLight->lTypeOfLight );
}
 
void GLI_vSetLightType ( GLI_tdstLight *p_stLight ,long lNewType)
{
	p_stLight->lTypeOfLight = lNewType;
}
 
 
 
/*
 * Painting light flag
 */
void GLI_vSetPaintingLightFlag (GLI_tdstLight *p_stLight, long bIsPainting) 
{
	p_stLight->bIsPainting = (unsigned char)bIsPainting;
}
    
unsigned char GLI_ucGetPaintingLightFlag (GLI_tdstLight *p_stLight) 
{
	return (p_stLight->bIsPainting);
}
 
void GLI_vSetPaintLight( struct GLI_tdstLight_ * p_stLight)
{
	p_stLight->bIsPainting=1;
}
 
/*
 * Alpha light flag
 */
void GLI_vSetAlphaLightFlag (GLI_tdstLight *p_stLight, long bIsAlpha) 
{
	p_stLight->ucIsAlpha = (unsigned char)bIsAlpha;
}
 
unsigned char GLI_ucGetAlphaLightFlag (GLI_tdstLight *p_stLight) 
{
	return (p_stLight->ucIsAlpha);
}
 
void GLI_vSetAlphaLight( struct GLI_tdstLight_ * p_stLight)
{
	p_stLight->ucIsAlpha=1;
}
 
    
/*
 * background color
 */
void GLI_xSetLightBackgroundColor ( GLI_tdstLight *p_stLight , struct GEO_tdstColor_ *p_stColor )
{
	p_stLight->stBackgroundColor = *p_stColor;
}
    
void GLI_xGetLightBackgroundColor ( GLI_tdstLight *p_stLight , struct GEO_tdstColor_ *p_stColor )
{
	*p_stColor = p_stLight->stBackgroundColor;
}
 
/* 
 * Light intensity
 */
void GLI_vSetLight_Intensity_Min_Max ( GLI_tdstLight *p_stLight, MTH_tdxReal xIntensity_Min, MTH_tdxReal xIntensity_Max )
{
	p_stLight->xIntensity_Min = xIntensity_Min;
    p_stLight->xIntensity_Max = xIntensity_Max;
}
    
void GLI_vGetLight_Intensity_Min_Max ( GLI_tdstLight *p_stLight, MTH_tdxReal *xIntensity_Min, MTH_tdxReal *xIntensity_Max )
{
	*xIntensity_Min = p_stLight->xIntensity_Min;
	*xIntensity_Max = p_stLight->xIntensity_Max;
}
 
/* 
 * ligth min/max pos 
 */ 
void GLI_vSetLight_Inter_Min_Pos ( GLI_tdstLight *p_stLight, MTH3D_tdstVector xInter_Min_Pos)
{
	p_stLight->xInter_Min_Pos = xInter_Min_Pos;
    GLI_vComputeLight_SphereBox( p_stLight );
}
    
void GLI_vGetLight_Inter_Min_Pos ( GLI_tdstLight *p_stLight, MTH3D_tdstVector * xInter_Min_Pos )
{
	*xInter_Min_Pos = p_stLight->xInter_Min_Pos;
}
    
void GLI_vSetLight_Inter_Max_Pos ( GLI_tdstLight *p_stLight, MTH3D_tdstVector xInter_Max_Pos)
{
	p_stLight->xInter_Max_Pos = xInter_Max_Pos;
	GLI_vComputeLight_SphereBox( p_stLight );
}
    
void GLI_vGetLight_Inter_Max_Pos ( GLI_tdstLight *p_stLight, MTH3D_tdstVector * xInter_Max_Pos )
{
	*xInter_Max_Pos = p_stLight->xInter_Max_Pos;
}
    
void GLI_vSetLight_Exter_Min_Pos ( GLI_tdstLight *p_stLight, MTH3D_tdstVector xExter_Min_Pos)
{
	p_stLight->xExter_Min_Pos = xExter_Min_Pos;
	GLI_vComputeLight_SphereBox( p_stLight );
}
    
void GLI_vGetLight_Exter_Min_Pos ( GLI_tdstLight *p_stLight, MTH3D_tdstVector * xExter_Min_Pos )
{
	*xExter_Min_Pos = p_stLight->xExter_Min_Pos;
}
    
void GLI_vSetLight_Exter_Max_Pos ( GLI_tdstLight *p_stLight, MTH3D_tdstVector xExter_Max_Pos)
{
	p_stLight->xExter_Max_Pos = xExter_Max_Pos;
	GLI_vComputeLight_SphereBox( p_stLight );
}
    
void GLI_vGetLight_Exter_Max_Pos ( GLI_tdstLight *p_stLight, MTH3D_tdstVector * xExter_Max_Pos )
{
	*xExter_Max_Pos = p_stLight->xExter_Max_Pos;
}
 
/*
 * Object lighted
 */
unsigned char GLI_ucGetObjectLighted( struct GLI_tdstLight_ *p_stLight) 
{
	return p_stLight->ucObjectLighted;
}
 
void GLI_vSetLightMap( struct GLI_tdstLight_ *p_stLight , unsigned char bLightMap) 
{
	if (bLightMap)
		p_stLight->ucObjectLighted |= GLI_C_LightMap;
	else
		p_stLight->ucObjectLighted &= 0xFF ^ GLI_C_LightMap;
}
void GLI_vSetLightPerso( struct GLI_tdstLight_ *p_stLight , unsigned char bLightPerso) 
{
	if (bLightPerso)
		p_stLight->ucObjectLighted |= GLI_C_LightPerso;
	else
		p_stLight->ucObjectLighted &= 0xFF ^ GLI_C_LightPerso;
}
 
void GLI_vSetObjectLighted( struct GLI_tdstLight_ *p_stLight , unsigned char ucObjectLighted) 
{
	p_stLight->ucObjectLighted = ucObjectLighted;
}
 
/* 
 * Fog parameters 
 */
void GLI_fn_vFogSetNear(GLI_tdstLight *p_stLight, MTH_tdxReal _xReal)		  
{
	p_stLight->xNear = _xReal;
}
 
MTH_tdxReal	GLI_fn_xFogGetNear(GLI_tdstLight *p_stLight)							            
{
	return p_stLight->xNear;
}
 
void GLI_fn_vFogSetFar(GLI_tdstLight *p_stLight, MTH_tdxReal _xReal)	  	  
{
	p_stLight->xFar = _xReal;
}
 
MTH_tdxReal	GLI_fn_xFogGetFar(GLI_tdstLight *p_stLight)								            
{
	return p_stLight->xFar;
}
 
void GLI_fn_vFogSetInfinite(GLI_tdstLight *p_stLight, MTH_tdxReal _xReal)	
{
	p_stLight->xLittleAlpha = _xReal;
}
 
MTH_tdxReal	GLI_fn_xFogGetInfinite(GLI_tdstLight *p_stLight)						          
{
	return p_stLight->xLittleAlpha;
}
 
void GLI_fn_vFogSetBlendNear(GLI_tdstLight *p_stLight, MTH_tdxReal _xReal)	
{
	p_stLight->xBigAlpha = _xReal;
}
 
MTH_tdxReal	GLI_fn_xFogGetBlendNear(GLI_tdstLight *p_stLight)						          
{
	return p_stLight->xBigAlpha;
}
 
void GLI_fn_vFogSetBlendFar(GLI_tdstLight *p_stLight, MTH_tdxReal _xReal)	
{
	p_stLight->xIntensity_Min = _xReal;
}
 
MTH_tdxReal	GLI_fn_xFogGetBlendFar(GLI_tdstLight *p_stLight)						          
{
	return p_stLight->xIntensity_Min;
}
 
 
/*
 =======================================================================================
	Spherical light 
 =======================================================================================
 */
 
/*
 * global for spherical ligth computing
 */
static void             (* GLI_vAddColorFunction)(void);
static MTH_tdxReal      gs_xCoef;
static GEO_tdstColor    *gs_p_stLightColor;
static GEO_tdstColor    *gs_p_stColor;
static MTH3D_tdstVector	stPositionOfTheLightInTheObjectMatrix;
 
/*
 *******************************************************************************************
 Goal: Return 1 if object interact with spherical light
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
long GLI_INTERNAL_FAST_CALLING_CONV GLI_bIsObjectIntersectWithSphericalLight(GLI_tdstLight *p_stLight ,  GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	MTH3D_tdstVector stLocalVect;
    MTH_tdxReal      xDist, xDist2;
    long             lResult = 0xF;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    if( p_stGlobaleMT->stRadiusOfCurrentBoundingSphere == 0.0f )
      return 0xF;
 
    MTH3D_M_vSubVector( &stLocalVect, &p_stLight->stMatrix.stTranslationVector, &p_stGlobaleMT->stCenterOfCurrentBoundingSphere );
    xDist = MTH3D_M_xNormVector( &stLocalVect );
 
    xDist2 = xDist - p_stGlobaleMT->stRadiusOfCurrentBoundingSphere;
    if (xDist2 > p_stLight->xFar)
        return 0;
    /*
    if (xDist2 > p_stLight->xNear)
        lResult = 12;
    else if (xDist2 > 0)
        lResult = 14;
    else
        lResult = 15;
        */
 
    xDist2 = xDist + p_stGlobaleMT->stRadiusOfCurrentBoundingSphere;
    if (xDist2 < p_stLight->xNear )
        lResult &= 3;
    /*
    else if (xDist2 < p_stLight->xFar)
        lResult &= 7;
    else 
        lResult &= 0xF;
        */
 
    return lResult;
}
 
/*
 *******************************************************************************************
 Goal: compute effect of a spherical ligth on object
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
static void GLI_vAddRGBAColorMulCoef(void)
{
    gs_p_stColor->xR += MTH_M_xRealToFloat( gs_p_stLightColor->xR * gs_xCoef );
    gs_p_stColor->xG += MTH_M_xRealToFloat( gs_p_stLightColor->xG * gs_xCoef );
	gs_p_stColor->xB += MTH_M_xRealToFloat( gs_p_stLightColor->xB * gs_xCoef );
	gs_p_stColor->xA += MTH_M_xRealToFloat( gs_p_stLightColor->xA * gs_xCoef );
}
 
static void GLI_vAddRGBColorMulCoef(void)
{
    gs_p_stColor->xR += MTH_M_xRealToFloat( gs_p_stLightColor->xR * gs_xCoef );
    gs_p_stColor->xG += MTH_M_xRealToFloat( gs_p_stLightColor->xG * gs_xCoef );
	gs_p_stColor->xB += MTH_M_xRealToFloat( gs_p_stLightColor->xB * gs_xCoef );
}
 
static void GLI_vAddAColorMulCoef(void)
{
	gs_p_stColor->xA += MTH_M_xRealToFloat( gs_p_stLightColor->xA * gs_xCoef );
}
/*EVL*/
 
void GLI_vSendObjectToSphericalLightNoScale( GLI_tdstLight *p_stLight,GEO_tdstGeometricObject *p_stObject, GEO_tdstColor *p_stColorRLID, GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    MTH3D_tdstVector				stVect2;
    MTH_tdxReal					xDX, xOODelta, xFar2, xNear2;
	MTH3D_tdstVector            *p_stLastVertex;
    MTH3D_tdstVector            *p_stObjVertex;
    MTH3D_tdstVector            *p_stObjNormal;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    /*
	 * pre compute constant
	 */
    xNear2 = p_stLight->xNear * p_stLight->xNear;
    xFar2 = p_stLight->xFar * p_stLight->xFar;
    xOODelta = ( xNear2 != xFar2 ) ? (1.0f / (xFar2 - xNear2)) : 1.0f;
 
    /*
	 * init loop var
	 */
    p_stObjVertex = p_stObject->d_stListOfPoints;
    p_stLastVertex = p_stObjVertex + p_stObject->xNbPoints;
    p_stObjNormal = p_stObject->d_stListOfPointsNormals;
    
    for ( ; p_stObjVertex < p_stLastVertex ; gs_p_stColor++, p_stObjVertex++, p_stObjNormal++ )
    {
		MTH3D_M_vSubVector( &stVect2 , p_stObjVertex , &stPositionOfTheLightInTheObjectMatrix );
 
		if ( ((xDX = stVect2.xX * stVect2.xX) < xFar2 ) && ((xDX += stVect2.xY * stVect2.xY) < xFar2 ) )
		{
			xDX += stVect2.xZ * stVect2.xZ;
			if (xDX < xNear2)
			{
                gs_xCoef = MTH3D_M_xDotProductVector( &stVect2 , p_stObjNormal );
		        if (gs_xCoef >= 0.0)
					continue;
                gs_xCoef *=  -MTH_M_xInvSqrt(xDX);
			}
			else if (xDX < xFar2)
			{
				gs_xCoef = MTH3D_M_xDotProductVector( &stVect2 ,p_stObjNormal );
				if (gs_xCoef >= 0.0)
					continue;
                gs_xCoef *= ( xDX - xFar2 ) * xOODelta * MTH_M_xInvSqrt(xDX);
			}
			else 
				continue;
 
            GLI_vAddColorFunction();
		}
	}
}
 
void GLI_vSendObjectToSphericalLight( GLI_tdstLight *p_stLight,GEO_tdstGeometricObject *p_stObject, GEO_tdstColor *p_stColorRLID, GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    MTH3D_tdstVector				stVect2;
    POS_tdstCompletePosition	stMatrix;
    MTH_tdxReal					xDX, xOODelta, xFar2, xNear2, xMaxZoomOfObjectMatrix;
    MTH3D_tdstVector				stPositionOfTheLightInTheCameraMatrix;
	GLI_tdstAligned3DVector		*p_stVertex, *p_stLastVertex;
    MTH3D_tdstVector            *p_stObjVertex;
    MTH3D_tdstVector            *p_stObjNormal;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    /*
     * get current matrix scale
     */
    xMaxZoomOfObjectMatrix = POS_fn_xGetMaxScale(p_stGlobaleMT->gs_st_CurrentMatrix);
    
    if ( MTH_M_bEqualWithEpsilon( xMaxZoomOfObjectMatrix, 1, 0.05 ) )
    {
        GLI_vSendObjectToSphericalLightNoScale( p_stLight, p_stObject, p_stColorRLID, p_stGlobaleMT );
        return;
    }
 
    /*
	 * pre compute constant
	 */
    xNear2 = p_stLight->xNear * p_stLight->xNear;
    xFar2 = p_stLight->xFar * p_stLight->xFar;
    xOODelta = ( xNear2 != xFar2 ) ? (xMaxZoomOfObjectMatrix / (xFar2 - xNear2)) : xMaxZoomOfObjectMatrix;
 
   	/*
   	 * compute position of ligth into camera system axis
     */
   	POS_fn_vMulMatrixMatrix ( &stMatrix  , p_stGlobaleMT->gs_st_CameraMatrix, &p_stLight -> stMatrix);
    POS_fn_vGetTranslationVector ( &stMatrix  , &stPositionOfTheLightInTheCameraMatrix );
    
	/*
	 * init loop var
	 */
	p_stVertex      = p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint;
    p_stLastVertex  = p_stVertex + p_stObject->xNbPoints;
    p_stObjVertex   = p_stObject->d_stListOfPoints;
    p_stObjNormal   = p_stObject->d_stListOfPointsNormals;
    
    for ( ; p_stVertex < p_stLastVertex ; p_stVertex++, gs_p_stColor++, p_stObjVertex++, p_stObjNormal++ )
    {
		MTH3D_M_vSubVector( &stVect2 , &stPositionOfTheLightInTheCameraMatrix, p_stVertex );
 
		if ( ((xDX = stVect2.xX * stVect2.xX) < xFar2 ) && ((xDX += stVect2.xY * stVect2.xY) < xFar2 ) )
		{
			xDX += stVect2 . xZ * stVect2 . xZ;
			if (xDX < xNear2)
			{
				if (xDX !=0)
				{
					MTH3D_M_vSubVector( &stVect2 , p_stObjVertex , &stPositionOfTheLightInTheObjectMatrix );
 
                    gs_xCoef = MTH3D_M_xDotProductVector( &stVect2 , p_stObjNormal );
					if (gs_xCoef >= 0.0)
						continue;
                    gs_xCoef *=  -xMaxZoomOfObjectMatrix * MTH_M_xInvSqrt(xDX);
 
				}
				else
					gs_xCoef = 1.0;
			}
			else if (xDX < xFar2)
			{
				MTH3D_M_vSubVector( &stVect2 , p_stObjVertex, &stPositionOfTheLightInTheObjectMatrix );
				
				gs_xCoef = MTH3D_M_xDotProductVector( &stVect2 ,p_stObjNormal );
				if (gs_xCoef >= 0.0)
					continue;
                gs_xCoef *= ( xDX - xFar2 ) * xOODelta * MTH_M_xInvSqrt(xDX);
			}
			else 
				continue;
 
            GLI_vAddColorFunction();
		}
	}
}
 
void GLI_vSendObjectNearOfSphericalLight( GLI_tdstLight *p_stLight,GEO_tdstGeometricObject *p_stObject, GEO_tdstColor *p_stColorRLID, GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    MTH3D_tdstVector				stVect2;
    MTH3D_tdstVector            *p_stObjVertex, *p_stLast, *p_stObjNormal;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	/*
	 * init loop var
	 */
    p_stObjVertex   = p_stObject->d_stListOfPoints;
    p_stLast        = p_stObjVertex + p_stObject->xNbPoints;  
    p_stObjNormal   = p_stObject->d_stListOfPointsNormals;
 
    gs_p_stColor      = p_stColorRLID;
    gs_p_stLightColor = &p_stLight->stColor;
    
    for ( ; p_stObjVertex < p_stLast ; gs_p_stColor++, p_stObjVertex++, p_stObjNormal++ )
    {
		MTH3D_M_vSubVector( &stVect2 , p_stObjVertex , &stPositionOfTheLightInTheObjectMatrix );
        gs_xCoef = MTH3D_M_xDotProductVector( &stVect2 , p_stObjNormal );
		if (gs_xCoef >= 0.0)
		    continue;
        gs_xCoef = MTH_M_xNeg( MTH_M_xDiv( gs_xCoef, MTH3D_M_xNormVector( &stVect2) ) );
 
        GLI_vAddColorFunction();
	}
}
 
/*
 *******************************************************************************************
 Goal: Compute result of a spherical painting light
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
void GLI_vSendObjectToSphericalPaintingLight
	(
		GLI_tdstLight							*p_stLight ,
		GEO_tdstGeometricObject					*p_stObject ,
		GEO_tdstColor							*p_stColorRLID ,
		GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT
	)
{
	MTH3D_tdstVector				stVect, stVect2;
	POS_tdstCompletePosition	stMatrix;
	MTH_tdxReal					xDX, xCoef, xOODelta, xFar2, xNear2, xMaxZoomOfObjectMatrix;
	GLI_tdstAligned3DVector		*p_stVertex, *p_stLastVertex;
 
	/*
	 * pre compute constant
	 */
    xNear2 = p_stLight->xNear * p_stLight->xNear;
    xFar2 = p_stLight->xFar * p_stLight->xFar;
    xOODelta = ( xNear2 != xFar2 ) ? (1.0f / (xFar2 - xNear2)) : 1.0f;
	xMaxZoomOfObjectMatrix = POS_fn_xGetMaxScale(p_stGlobaleMT->gs_st_CurrentMatrix);
 
	/*
	 * compute position of ligth into camera system axis
	 */
	POS_fn_vMulMatrixMatrix ( &stMatrix, p_stGlobaleMT->gs_st_CameraMatrix, &p_stLight->stMatrix);
    POS_fn_vGetTranslationVector ( &stMatrix  , &stVect );
    
	/*
	 * init loop var
	 */
	p_stVertex = p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint;
	p_stLastVertex = p_stVertex + p_stObject->xNbPoints;
    
	for (  ; p_stVertex < p_stLastVertex ; p_stVertex++, p_stColorRLID++)
    {
		MTH3D_M_vSubVector( &stVect2 , &stVect, p_stVertex );
 
		if ( ((xDX = stVect2.xX * stVect2.xX) < xFar2 ) && ((xDX += stVect2.xY * stVect2.xY) < xFar2 ) )
		{
			xDX += stVect2 . xZ * stVect2 . xZ;
			if (xDX < xNear2)
			{
				if (xDX !=0)
					xCoef = xMaxZoomOfObjectMatrix;
				else
					xCoef = 1.0;
			}
			else if (xDX < xFar2)
			{
				xCoef = ( xFar2 - xDX ) * xOODelta * xMaxZoomOfObjectMatrix;
			}
			else 
				continue;
 
			if ( p_stLight->ucIsAlpha == 1)
			{
				p_stColorRLID->xA += MTH_M_xRealToFloat ( p_stLight->stColor.xA * xCoef );
			}
			else
			{
				p_stColorRLID->xR += MTH_M_xRealToFloat ( p_stLight->stColor.xR * xCoef );
				p_stColorRLID->xG += MTH_M_xRealToFloat ( p_stLight->stColor.xG * xCoef );
				p_stColorRLID->xB += MTH_M_xRealToFloat ( p_stLight->stColor.xB * xCoef );
				if ( p_stLight->ucIsAlpha == 0 )
					p_stColorRLID->xA += MTH_M_xRealToFloat ( p_stLight->stColor.xA * xCoef );
			}
		}
	}
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : main function to manage with spherical ligth
 ----------------------------------------------------------------------------------------
 */
void GLI_vSendObjectToSphericalLightMain( GLI_tdstLight *p_stLight,GEO_tdstGeometricObject *p_stObject, GEO_tdstColor *p_stColorRLID, GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT )
{
    long lLigthningFlag;
 
    if (lLigthningFlag = GLI_bIsObjectIntersectWithSphericalLight( p_stLight,p_stGlobaleMT ))
	{
	    if ( p_stLight->bIsPainting )
        {
		    GLI_vSendObjectToSphericalPaintingLight(p_stLight ,p_stObject ,p_stColorRLID ,p_stGlobaleMT);
        }
		else
        {
            /*
             * set good function
             */
	        if ( p_stLight->ucIsAlpha == 1)
                GLI_vAddColorFunction = GLI_vAddAColorMulCoef;
	        else if ( p_stLight->ucIsAlpha == 2 )
                GLI_vAddColorFunction = GLI_vAddRGBColorMulCoef;
            else
                GLI_vAddColorFunction = GLI_vAddRGBAColorMulCoef;
 
            gs_p_stColor      = p_stColorRLID;
            gs_p_stLightColor = &p_stLight->stColor;
 
            /*
             * compute position of light into object local matrix
             */
            if (!(p_stGlobaleMT -> lClippingModeMask & GLI_C_IsObjectMatrixAlreadyInverted))
            {
                POS_fn_vInvertMatrix(&p_stGlobaleMT -> gs_st_CurrentMatrixInverted,p_stGlobaleMT ->gs_st_CurrentMatrix);
                p_stGlobaleMT -> lClippingModeMask |= GLI_C_IsObjectMatrixAlreadyInverted;
            }
            MTH3D_M_vMulMatrixVectorWithoutBuffer( &stPositionOfTheLightInTheObjectMatrix , &p_stGlobaleMT->gs_st_CurrentMatrixInverted.stTransformMatrix , &p_stLight->stMatrix.stTranslationVector );
            MTH3D_M_vAddVector( &stPositionOfTheLightInTheObjectMatrix, &p_stGlobaleMT->gs_st_CurrentMatrixInverted.stTranslationVector, &stPositionOfTheLightInTheObjectMatrix );
 
            /*
			if (mytest)
            {
                if ((lLigthningFlag & 0xC) == 0)
                {
                    GLI_vSendObjectNearOfSphericalLight( p_stLight ,p_stObject ,p_stColorRLID ,p_stGlobaleMT );
                }
                else
                {
			        GLI_vSendObjectToSphericalLight( p_stLight ,p_stObject ,p_stColorRLID ,p_stGlobaleMT);
                }
            }
            else*/
            {
                GLI_vSendObjectToSphericalLight( p_stLight ,p_stObject ,p_stColorRLID ,p_stGlobaleMT);
            }
        }
    }
}
 
  
/*
 =======================================================================================
	hotspot light 
 =======================================================================================
 */
  
/*
 *******************************************************************************************
 Goal: Return 1 if object interact with hot spot light
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
long GLI_INTERNAL_FAST_CALLING_CONV GLI_bIsObjectIntersectWithHotSpotLight(GLI_tdstLight *p_stLight ,GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT )
{
    MTH3D_tdstVector stLocalVect;
    MTH_tdxReal      xDist;
    
    if( p_stGlobaleMT->stRadiusOfCurrentBoundingSphere == 0.0f )
      return 1;
 
    POS_fn_vGetTranslationVector( &p_stLight->stMatrix, &stLocalVect );
    MTH3D_M_vSubVector( &stLocalVect, &stLocalVect, &p_stGlobaleMT->stCenterOfCurrentBoundingSphere );
    xDist = MTH3D_M_xNormVector( &stLocalVect );
    if( xDist < (p_stLight->xFar + p_stGlobaleMT->stRadiusOfCurrentBoundingSphere) ) 
      return 1;
 
	return 0;
}
 
/*
 *******************************************************************************************
 Goal:
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
void GLI_vSendObjectToHotSpotLight
	(
		GLI_tdstLight *p_stLight ,
		GEO_tdstGeometricObject *p_stObject ,
		GEO_tdstColor *p_stColorRLID ,
		GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT
	)
{
    float	                    aDEF_AValueTable[C_lMaxVertexPerObject];
    long                      lVertexIndex;
    MTH3D_tdstVector            stVect;
    POS_tdstCompletePosition  stMatrix;
    MTH_tdxReal               xDX, xDY, xDZ, xTg, xCoef, xOODelta, xOODeltaTg, xDistance, xFar2, xNear2;
    MTH_tdxReal               xLocalDX, xLocalDY, xLocalDZ;
    signed long               CX, CY;
    MTH3D_tdstVector            stX, stY, stZ, stK;
    float                     fXScalarVect, fYScalarVect, fZScalarVect, fSaveDistanceLocal;
 
    GLI_M_vBenchAdd( lNumberOfHotSpotLightedVertices, p_stObject->xNbPoints);
 
    xFar2  = p_stLight->xFar * p_stLight->xFar;
    xNear2 = p_stLight->xNear* p_stLight->xNear;
    
    if ((p_stLight->xFar - p_stLight->xNear) != 0)
      xOODelta = 1.0f / (xFar2 - xNear2);
    else
      xOODelta = 1.0f;
    
    if ((p_stLight->xBigTangent - p_stLight->xLittleTangent) != 0)
      xOODeltaTg = 1.0f / (p_stLight->xBigTangent - p_stLight->xLittleTangent);
    else
      xOODeltaTg = 1.0f;
    
    POS_fn_vInvertIsoMatrix ( &stMatrix  , p_stGlobaleMT->gs_st_CurrentMatrix);
    POS_fn_vMulMatrixMatrix ( &stMatrix  , &stMatrix, &p_stLight->stMatrix);
    POS_fn_vGetRotationMatrix ( &stMatrix , &stK, &stY , &stX);
    
    POS_fn_vMulMatrixMatrix ( &stMatrix  , p_stGlobaleMT->gs_st_CameraMatrix, &p_stLight->stMatrix);
    POS_fn_vGetTranslationVector ( &stMatrix  , &stVect );
    POS_fn_vGetRotationMatrix ( &stMatrix , &stX, &stY , &stZ);
    
    GLI_xSerialDotProductAligned ( ASM_CAST p_stObject->xNbPoints ,
      ASM_CAST p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint ,
      ASM_CAST aDEF_AValueTable ,
      ASM_CAST (&stX),
      ASM_CAST (sizeof(MTH_tdxReal)));
    
    fXScalarVect = MTH3D_M_xDotProductVector( &stVect , &stX );
    fYScalarVect = MTH3D_M_xDotProductVector( &stVect , &stY );
    fZScalarVect = MTH3D_M_xDotProductVector( &stVect , &stZ );
    if (p_stLight->stZBuffer . p_stZBufferMap != NULL)
    {
      for ( lVertexIndex = 0;lVertexIndex < p_stObject->xNbPoints;lVertexIndex  ++ , p_stColorRLID ++)
      {
        xLocalDX = xDX = fXScalarVect - aDEF_AValueTable [lVertexIndex];
        aDEF_AValueTable [lVertexIndex] = 0.0F;
        if ((xDX < p_stLight->xFar) && (xDX > 0.0))
        {
          xLocalDY = xDY = fYScalarVect - MTH3D_M_xDotProductVector( (p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint + lVertexIndex ) , &stY );
          if ( ( xDY < p_stLight->xFar) && (xDY > -p_stLight->xFar) )
          {
            xLocalDZ = xDZ = fZScalarVect - MTH3D_M_xDotProductVector( (p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint + lVertexIndex ) , &stZ );
            if ( ( xDZ < p_stLight->xFar) && (xDZ > -p_stLight->xFar) )
            {
              xDX = xDX * xDX;
              xDY = xDY * xDY;
              xDZ = xDZ * xDZ;
              if (xDX != 0)
                xTg = (xDZ + xDY) * MTH_M_xInv(xDX);
              else continue;
              if (xTg < p_stLight->xBigTangent )
              {
                fSaveDistanceLocal = xDistance = xDZ + xDY + xDX;
                if ( xDistance > xFar2) continue;
                if ( xDistance < xNear2)
                  xCoef = 1.0;
                else
                  xCoef = -( xDistance - xFar2 ) * xOODelta;
 
                if ( xTg > p_stLight->xLittleTangent )
                  xCoef = xCoef  * -( xTg - p_stLight->xBigTangent ) * xOODeltaTg;
                
                if ( p_stLight->bIsPainting )
				{
					if (xDistance !=0)
					{
	                  xDistance = xDistance < 0.0 ? -xDistance : xDistance;
	                  xDistance = xDistance * MTH3D_M_xNormVector(&stK);
					}
					else
					{
					 xDistance = 1.0f;
					}
				}
				else
				{
					if (xDistance !=0)
					  xDistance = (MTH3D_M_xDotProductVector( &stK ,p_stObject->d_stListOfPointsNormals + lVertexIndex ) + 1.0f ) * 0.5f;
					else
					  xDistance = 1.0f;
				}
 
                if (xDistance > 0.0f)
                {
                  xCoef = xCoef  * xDistance;
                  xLocalDX = MTH_M_xInv(xLocalDX);
                  CX = (long)(xLocalDY * p_stLight->stZBuffer . fCoefX  * xLocalDX );
                  CY = (long)(xLocalDZ * p_stLight->stZBuffer . fCoefY  * xLocalDX );
                  if ((CX>-(p_stLight->stZBuffer . lSizeX>>1)) && (CX<(p_stLight->stZBuffer . lSizeX>>1)))
                  {
                    if ((CY>-(p_stLight->stZBuffer . lSizeY>>1)) && (CY<(p_stLight->stZBuffer . lSizeY>>1)))
                    {
                      xLocalDY = p_stLight->stZBuffer . p_stMiddleZBufferMap[CY*p_stLight->stZBuffer . lSizeX + CX];
                      xLocalDX = xLocalDX;
                      if (xLocalDX >= xLocalDY)
                      {
                        aDEF_AValueTable [lVertexIndex] = fSaveDistanceLocal;
                        xCoef = xCoef  * xDistance;
 
                        if ( p_stLight->ucIsAlpha == 1 )
                        {
                          p_stColorRLID ->xA += MTH_M_xRealToFloat ( p_stLight->stColor.xA * xCoef );
                        }
                        else
                        {
                          p_stColorRLID ->xR += MTH_M_xRealToFloat ( p_stLight->stColor.xR * xCoef );
                          p_stColorRLID ->xG += MTH_M_xRealToFloat ( p_stLight->stColor.xG * xCoef );
                          p_stColorRLID ->xB += MTH_M_xRealToFloat ( p_stLight->stColor.xB * xCoef );
                  		  if ( p_stLight->ucIsAlpha == 0 )
						  {
							p_stColorRLID ->xA += MTH_M_xRealToFloat ( p_stLight->stColor.xA * xCoef );
						  }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    else /* NO Z Buffer*/
    {
      for ( lVertexIndex = 0;lVertexIndex < p_stObject->xNbPoints;lVertexIndex  ++ , p_stColorRLID ++)
      {
        xLocalDX = xDX = fXScalarVect - aDEF_AValueTable [lVertexIndex];
        aDEF_AValueTable [lVertexIndex] = 0.0F;
        if ((xDX < p_stLight->xFar) && (xDX > 0.0))
        {
          xLocalDY = xDY = fYScalarVect - MTH3D_M_xDotProductVector( (p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint + lVertexIndex ) , &stY );
          if ( ( xDY < p_stLight->xFar) && (xDY > -p_stLight->xFar) )
          {
            xLocalDZ = xDZ = fZScalarVect - MTH3D_M_xDotProductVector( (p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint + lVertexIndex ) , &stZ );
            if ( ( xDZ < p_stLight->xFar) && (xDZ > -p_stLight->xFar) )
            {
              xDX = xDX * xDX;
              xDY = xDY * xDY;
              xDZ = xDZ * xDZ;
              if (xDX != 0)
                xTg = (xDZ + xDY) * MTH_M_xInv(xDX);
              else continue;
              if (xTg < p_stLight->xBigTangent )
              {
                fSaveDistanceLocal = xDistance = xDZ + xDY + xDX;
                if ( xDistance > xFar2) continue;
                if ( xDistance < xNear2)
                  xCoef = 1.0;
                else
                  xCoef = -( xDistance - xFar2 ) * xOODelta;
 
                if ( xTg > p_stLight->xLittleTangent )
                  xCoef = xCoef  * -( xTg - p_stLight->xBigTangent ) * xOODeltaTg;
 
                if ( p_stLight->bIsPainting )
				{
					if (xDistance !=0)
					{
	                  xDistance = xDistance < 0.0 ? -xDistance : xDistance;
	                  xDistance = xDistance * MTH3D_M_xNormVector(&stK);
					}
					else
					{
					 xDistance = 1.0f;
					}
				}
				else
				{
					if (xDistance !=0)
					  xDistance = (MTH3D_M_xDotProductVector( &stK ,p_stObject->d_stListOfPointsNormals + lVertexIndex ) + 1.0f ) * 0.5f;
					else
					  xDistance = 1.0f;
				}
                
                if (xDistance > 0.0f)
                {
                  aDEF_AValueTable [lVertexIndex] = fSaveDistanceLocal;
                  xCoef = xCoef  * xDistance;
                  if ( p_stLight->ucIsAlpha == 1 )
                  {
                    p_stColorRLID->xA += MTH_M_xRealToFloat ( p_stLight->stColor.xA * xCoef );
                  }
                  else
                  {
                    p_stColorRLID->xR += MTH_M_xRealToFloat ( p_stLight->stColor.xR * xCoef );
                    p_stColorRLID->xG += MTH_M_xRealToFloat ( p_stLight->stColor.xG * xCoef );
                    p_stColorRLID->xB += MTH_M_xRealToFloat ( p_stLight->stColor.xB * xCoef );
   					if ( p_stLight->ucIsAlpha == 0 )
					{
						p_stColorRLID->xA += MTH_M_xRealToFloat ( p_stLight->stColor.xA * xCoef );
					}
                  }
                }
              }
            }
          }
        }
      }
    }
}
 
    
/*
 =======================================================================================
	Ambient light 
 =======================================================================================
 */
    
/*
 *******************************************************************************************
 Goal: Compute the ambient light.
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
void GLI_vSendObjectToAmbientLight( GLI_tdstLight *p_stLight, GEO_tdstGeometricObject *p_stObject , GEO_tdstColor *p_stColorRLIA , GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT )
{
	if ( p_stLight->ucIsAlpha == 1)
	{
		p_stColorRLIA ->xA += p_stLight->stColor.xA;
	}
	else
	{
		p_stColorRLIA ->xR += p_stLight->stColor.xR;
		p_stColorRLIA ->xG += p_stLight->stColor.xG;
		p_stColorRLIA ->xB += p_stLight->stColor.xB;
		if ( p_stLight->ucIsAlpha == 0)
		{
			p_stColorRLIA ->xA += p_stLight->stColor.xA;
		}
	}
}
 
/*
 =======================================================================================
	parrallel light 
 =======================================================================================
 */
    
/*
 *******************************************************************************************
 Goal: Compute effect of a parrallel ligth on object
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
void GLI_vSendObjectToParallelLight( GLI_tdstLight *p_stLight , GEO_tdstGeometricObject *p_stObject , GEO_tdstColor *p_stColorRLID , GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT )
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    float	                  aDEF_AValueTable[C_lMaxVertexPerObject];
    GEO_tdstColor             *p_stFirstColor,*p_stLastColor;
    float                     *p_ValuesTable, *p_fLast, *p_fVertexNormal;
    MTH3D_tdstVector            stVect, stVect2;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
 
    GLI_M_vBenchAdd( lNumberOfParallelLightedVertices, p_stObject->xNbPoints);
 
    p_ValuesTable = &p_stLight->stMatrix.stRotationMatrix.stCol_0.xZ;
    MTH3D_M_vSetVectorElements (&stVect2, *p_ValuesTable, *(p_ValuesTable + 3), *(p_ValuesTable + 6) );
        
	/*
	 * le code ci-dessus est faux.
	 * La direction de la lumiere est donnee par la 3eme colonne de la matrice, et non par la 3eme ligne !!!!!!
	 * il faut remplacer les 2 lignes ci-dessus par :
	 *
	 * MTH3D_M_vCopyVector(&stVect2,&p_stLight->stMatrix.stRotationMatrix.stCol_2);
	 *
	 */

    p_ValuesTable = &p_stGlobaleMT->gs_st_CurrentMatrix->stRotationMatrix.stCol_0.xX;
    stVect.xX = stVect2.xX * *(p_ValuesTable++);
    stVect.xX += stVect2.xY * *(p_ValuesTable++);
    stVect.xX += stVect2.xZ * *(p_ValuesTable++);
    stVect.xY = stVect2.xX * *(p_ValuesTable++);
    stVect.xY += stVect2.xY * *(p_ValuesTable++);
    stVect.xY += stVect2.xZ * *(p_ValuesTable++);
    stVect.xZ = stVect2.xX * *(p_ValuesTable++);
    stVect.xZ += stVect2.xY * *(p_ValuesTable++);
    stVect.xZ += stVect2.xZ * *(p_ValuesTable++);
    
    p_ValuesTable = aDEF_AValueTable;
    p_fLast = p_ValuesTable + p_stObject->xNbPoints;
    p_fVertexNormal = p_stObject->d_stListOfPointsNormals;
 
    for (; p_ValuesTable < p_fLast; )
    {
        *p_ValuesTable      = stVect.xX * *p_fVertexNormal++;
        *p_ValuesTable      += stVect.xY * *p_fVertexNormal++;
        *p_ValuesTable++    += stVect.xZ * *p_fVertexNormal++;
    }
    
    p_stFirstColor = p_stColorRLID;
    p_stLastColor = p_stFirstColor + p_stObject->xNbPoints;
    p_ValuesTable = aDEF_AValueTable;
 
    if ( p_stLight->ucIsAlpha == 0 )
    {
        for (;p_stFirstColor < p_stLastColor;p_stFirstColor ++ , p_ValuesTable++)
        {
            if ( *((long *) p_ValuesTable) & 0x80000000 )
            {
			    p_stFirstColor->xR -= *p_ValuesTable * p_stLight->stColor.xR;
				p_stFirstColor->xG -= *p_ValuesTable * p_stLight->stColor.xG;
				p_stFirstColor->xB -= *p_ValuesTable * p_stLight->stColor.xB;
				p_stFirstColor->xA -= *p_ValuesTable * p_stLight->stColor.xA;
		    }
        }
    }
    else if ( p_stLight->ucIsAlpha == 1 )
    {
        for (;p_stFirstColor < p_stLastColor;p_stFirstColor ++ , p_ValuesTable++)
        {
            if ( *((long *) p_ValuesTable) & 0x80000000 )
			    p_stFirstColor->xA -= *p_ValuesTable * p_stLight->stColor.xA;
	    }
    }
    else
    {
        for (;p_stFirstColor < p_stLastColor;p_stFirstColor ++ , p_ValuesTable++)
        {
            if ( *((long *) p_ValuesTable) & 0x80000000 )
            {
			    p_stFirstColor->xR -= *p_ValuesTable * p_stLight->stColor.xR;
				p_stFirstColor->xG -= *p_ValuesTable * p_stLight->stColor.xG;
				p_stFirstColor->xB -= *p_ValuesTable * p_stLight->stColor.xB;
		    }
	    }
    }
 
    /*old code
    for (;p_stFirstColor < p_stLastColor;p_stFirstColor ++ , p_ValuesTable++)
    {
        if ( *p_ValuesTable <= 0.0 )
        {
		    if ( p_stLight->ucIsAlpha == 1 )
			{
			    p_stFirstColor->xA -= *p_ValuesTable * p_stLight->stColor.xA;
			}
			else
			{
			    p_stFirstColor->xR -= *p_ValuesTable * p_stLight->stColor.xR;
				p_stFirstColor->xG -= *p_ValuesTable * p_stLight->stColor.xG;
				p_stFirstColor->xB -= *p_ValuesTable * p_stLight->stColor.xB;
				if ( p_stLight->ucIsAlpha == 0 )
				{
				    p_stFirstColor->xA -= *p_ValuesTable * p_stLight->stColor.xA;
				}
			}	
		}
	}
    */
}
 
 
/*
 =======================================================================================
	parralel light within a box
 =======================================================================================
 */
 
/*
 *******************************************************************************************
 Goal:
 Code: Marc Trabucato / 18/02/98
 OPTIMMIZED : No
 *******************************************************************************************
 */
MTH_tdxReal GLI_xGetParallelBoxCoefficient( MTH_tdxReal xCoord, MTH_tdxReal xMinExtern, MTH_tdxReal xMinIntern, MTH_tdxReal xMaxIntern, MTH_tdxReal xMaxExtern)
{
  MTH_tdxReal xCoef = MTH_C_ONE;
  MTH_tdxReal xDist , xTemp;
  
  if( MTH_M_bInRangeEqual( xCoord, xMinExtern, xMaxExtern ) )
  {
    if( MTH_M_bLess( xCoord, xMinIntern ) )
    {
      xDist = MTH_M_xSub( xMinIntern, xMinExtern );
      if( MTH_M_bDifferentZero( xDist ) )
      {
        xTemp = MTH_M_xSub( xCoord, xMinExtern );
        xCoef = MTH_M_xDiv ( xTemp, xDist );
      }
    }
    else if ( MTH_M_bGreater( xCoord, xMaxIntern ) )
    {
      xDist = MTH_M_xSub( xMaxIntern, xMaxExtern );
      if( MTH_M_bDifferentZero( xDist ) )
      {
        xTemp = MTH_M_xSub( xCoord, xMaxExtern );
        xCoef = MTH_M_xDiv ( xTemp, xDist );
      }
    }
  }
  else
    xCoef = MTH_C_ZERO;
  
  return xCoef;
}
 
/*
 *******************************************************************************************
 Goal:
 Code: Marc Trabucato / 18/02/98
 OPTIMMIZED : No
 *******************************************************************************************
 */
MTH_tdxReal GLI_xGetParallelBoxAlpha( GLI_tdstLight *p_stLight , MTH3D_tdstVector *p_stPoint, MTH3D_tdstVector *p_stNormal )
{
  MTH_tdxReal xAlpha, xCoef, xCoef2, xCoefX, xCoefY, xCoefZ;
  MTH_tdxReal xPointZ, xNormalZ, xIntensity;
  
  xPointZ  = MTH3D_M_xGetZofVector( p_stPoint );
  xNormalZ = MTH3D_M_xGetZofVector( p_stNormal );
  
  if ( !p_stLight->bIsPainting )
  {
    if( MTH_M_xSign( xPointZ ) == MTH_M_xSign( xNormalZ ) )			
		return MTH_C_ZERO;
  }
  
  /* compute X coef */
  xCoefX = GLI_xGetParallelBoxCoefficient( MTH3D_M_xGetXofVector( p_stPoint ),
    MTH3D_M_xGetXofVector( & p_stLight->xExter_Min_Pos ),
    MTH3D_M_xGetXofVector( & p_stLight->xInter_Min_Pos ),
    MTH3D_M_xGetXofVector( & p_stLight->xInter_Max_Pos ),
    MTH3D_M_xGetXofVector( & p_stLight->xExter_Max_Pos ) );
  
  if( MTH_M_bEqualZero( xCoefX ) )         return MTH_C_ZERO;
  
  /* compute Y coef */
  xCoefY = GLI_xGetParallelBoxCoefficient( MTH3D_M_xGetYofVector( p_stPoint ),
    MTH3D_M_xGetYofVector( & p_stLight->xExter_Min_Pos ),
    MTH3D_M_xGetYofVector( & p_stLight->xInter_Min_Pos ),
    MTH3D_M_xGetYofVector( & p_stLight->xInter_Max_Pos ),
    MTH3D_M_xGetYofVector( & p_stLight->xExter_Max_Pos ) );
  
  if( MTH_M_bEqualZero( xCoefY ) )         return MTH_C_ZERO;
  
  /* compute Z coef */
  xCoefZ = GLI_xGetParallelBoxCoefficient( MTH3D_M_xGetZofVector( p_stPoint ),
    MTH3D_M_xGetZofVector( & p_stLight->xExter_Min_Pos ),
    MTH3D_M_xGetZofVector( & p_stLight->xInter_Min_Pos ),
    MTH3D_M_xGetZofVector( & p_stLight->xInter_Max_Pos ),
    MTH3D_M_xGetZofVector( & p_stLight->xExter_Max_Pos ) );
  
  if( MTH_M_bEqualZero( xCoefZ ) )         return MTH_C_ZERO;
  
  xCoef		= MTH_M_xMax( xCoefX, xCoefY );
  xCoef2		= MTH_M_xSub( MTH_C_ONE, xCoef );
  xIntensity	= MTH_M_xMulAddMul( xCoef, p_stLight->xIntensity_Max, xCoef2, p_stLight->xIntensity_Min );
  
  xCoef2 = MTH_M_xSub( MTH_C_ONE, xCoefZ );
  xAlpha = MTH_M_xMulAddMul( xCoefZ, xIntensity, xCoef2, p_stLight->xIntensity_Min );
  
  return xAlpha;
}
 
/*
 *******************************************************************************************
 Goal:
 Code: Marc Trabucato 16/02/98
 OPTIMMIZED : No
 *******************************************************************************************
 */
void GLI_vSendObjectToParallelLightOtherType(   GLI_tdstLight                           *p_stLight ,
                                             GEO_tdstGeometricObject                 *p_stObject ,
                                             GEO_tdstColor                           *p_stColorRLID ,
                                             GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT )
{
  float	                      aDEF_AValueTable[C_lMaxVertexPerObject];
  long                        lVertexIndex;
  MTH3D_tdstVector              stVect;
  MTH_tdxReal                 xDX , xTemp , xAlpha , xMaxZoomOfObjectMatrix, xRadius2;
  MTH3D_tdstVector              stPositionOfTheCenterLightInTheCameraMatrix, stPosOfBVInCameraMatrix;
  MTH3D_tdstVector              stCurrentPointInTheLightMatrix;
  MTH3D_tdstVector              stCurrentNormalInTheLightMatrix;
  MTH3D_tdstVector              stTempVertex;
  POS_tdstCompletePosition	  stMatrixLightToCamera, stMatrixCameraToLight, stMatrixObjectToLight, stTempMatrix;
  BOOL					            	bComputeSecondLevelMatrix;
  MTH_tdxReal				        	*p_ValuesTable;
 
  bComputeSecondLevelMatrix = FALSE;
  /*POS_fn_vSetIdentityMatrix ( &stMatrixLightToCamera );*/
  POS_fn_vMulMatrixMatrix   ( &stMatrixLightToCamera , p_stGlobaleMT->gs_st_CameraMatrix, &p_stLight->stMatrix);
  POS_fn_vMulMatrixVertex   ( &stPositionOfTheCenterLightInTheCameraMatrix , &stMatrixLightToCamera  , &p_stLight->xCenterBox );
  POS_fn_vMulMatrixVertex   ( &stPosOfBVInCameraMatrix , p_stGlobaleMT->gs_st_CameraMatrix, &p_stGlobaleMT->stCenterOfCurrentBoundingSphere );
  
  xMaxZoomOfObjectMatrix      = POS_fn_xGetMaxScale( p_stGlobaleMT->gs_st_CurrentMatrix );
  xRadius2					= MTH_M_xSqr( p_stLight->xRadius );
  
  /* uses Bounding Volume if exists */
  if( MTH_M_bDifferentZero( p_stGlobaleMT->stRadiusOfCurrentBoundingSphere ) )
  {
    /* compute the distance between object bounding volume center and light center sphere */
    MTH3D_M_vSubVector( &stVect, &stPositionOfTheCenterLightInTheCameraMatrix , &stPosOfBVInCameraMatrix );
    xTemp = MTH3D_M_xNormVector( &stVect );
    /* add radius */
    xDX = MTH_M_xAdd( p_stGlobaleMT->stRadiusOfCurrentBoundingSphere, p_stLight->xRadius );
    if( MTH_M_bGreater( xDX, xTemp ) )
      return;
  }
 
  GLI_M_vBenchAdd( lNumberOfParallelLightedVertices, p_stObject->xNbPoints);
  
	for ( lVertexIndex = 0 , p_ValuesTable = aDEF_AValueTable;
  lVertexIndex < p_stObject->xNbPoints;
  lVertexIndex++ ,p_stColorRLID++, p_ValuesTable++ )
  {
	MTH3D_M_vSubVector( &stVect , &stPositionOfTheCenterLightInTheCameraMatrix, (p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint + lVertexIndex) );
    /*
     *  stVect : position relative du i-ème point et de la lumière (dans le repère de la caméra)
     */
    xDX = MTH_M_xSqr( stVect . xX );
    if (MTH_M_bLess( xDX, xRadius2 ))
    {
      xTemp = MTH_M_xSqr( stVect . xY );
      xDX   = MTH_M_xAdd( xDX, xTemp );
      if (MTH_M_bLess( xDX, xRadius2 ))
      {
        xTemp = MTH_M_xSqr( stVect . xZ );
        xDX   = MTH_M_xAdd( xDX, xTemp );
        if (MTH_M_bLess( xDX, xRadius2 ))
        {
          /* in the sphere */
          if( !bComputeSecondLevelMatrix )
          {
            POS_fn_vInvertMatrix     ( &stMatrixCameraToLight , &stMatrixLightToCamera );
            POS_fn_vInvertMatrix     ( &stTempMatrix , &p_stLight->stMatrix);
			POS_fn_vMulMatrixMatrix     ( &stMatrixObjectToLight, p_stGlobaleMT->gs_st_CurrentMatrix, &stTempMatrix );
            bComputeSecondLevelMatrix	= TRUE;
          }
 
          MTH3D_M_vSetVectorElements( &stTempVertex, (p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint + lVertexIndex)->xX,
            (p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint + lVertexIndex)->xY,
            (p_stGlobaleMT->GLI_TurnedScaledDisplecedPoint + lVertexIndex)->xZ );
          POS_fn_vMulMatrixVertex ( &stCurrentPointInTheLightMatrix, &stMatrixCameraToLight, &stTempVertex );
          POS_fn_vMulMatrixVector ( &stCurrentNormalInTheLightMatrix, &stMatrixObjectToLight, (p_stObject->d_stListOfPointsNormals + lVertexIndex) );
          xAlpha = GLI_xGetParallelBoxAlpha( p_stLight, &stCurrentPointInTheLightMatrix, &stCurrentNormalInTheLightMatrix );
          
          if ( p_stLight->bIsPainting )
            xAlpha = MTH_M_bLessZero( xAlpha ) ? MTH_M_xNeg( xAlpha ) : xAlpha;
		  else          
			xAlpha = MTH_M_xMul( xAlpha, MTH_M_xAbs( MTH3D_M_xGetZofVector( &stCurrentNormalInTheLightMatrix ) ) );
          
          if (MTH_M_bGreaterZero( xAlpha ))
          {
            p_stColorRLID->xR += MTH_M_xRealToFloat ( MTH_M_xMul( p_stLight->stColor.xR , xAlpha) );
            p_stColorRLID->xG += MTH_M_xRealToFloat ( MTH_M_xMul( p_stLight->stColor.xG , xAlpha) );
            p_stColorRLID->xB += MTH_M_xRealToFloat ( MTH_M_xMul( p_stLight->stColor.xB , xAlpha) );
            p_stColorRLID->xA += MTH_M_xRealToFloat ( MTH_M_xMul( p_stLight->stColor.xA , xAlpha) );
          }
        }
      }
    }
  }
}
 
 
/*
 =======================================================================================
	For all light 
 =======================================================================================
 */
 
/*
 *******************************************************************************************
 Goal:
 Code: Ionut Grozea ROMTEAM 02.05.1998
 OPTIMMIZED : No
 *******************************************************************************************
 */
#ifdef ACTIVE_EDITOR
void GLI_vComputeAlphaFromPLGFile(GEO_tdstGeometricObject *p_stObject ,GEO_tdstColor *p_stColorRLID )
{
	SCR_tdst_Link_Table		*p_stGeomLinkTable;
	SCR_tdst_Link_Value		*p_stGeomLinkValue;
 	char					*szLinkName;
	char					szObjFile[SCR_CV_ui_Cfg_MaxLenName],	
							szObjName[SCR_CV_ui_Cfg_MaxLenName];
	int						iCount;
	long					lVertexIndex;
	
	p_stGeomLinkTable = GLI_p_stGetLinkTableOfGeometric();
	p_stGeomLinkValue = SCR_fnp_st_Link_SearchValue( p_stGeomLinkTable, (unsigned long) p_stObject);
	szLinkName  = p_stGeomLinkValue ? SCR_M_p_sz_Link_GetKey( p_stGeomLinkValue ) : NULL;
	if ( szLinkName != NULL )
	{
		SCR_fn_v_RdL0_SplitSectionName(szLinkName, szObjFile, NULL, szObjName);
		for(iCount=0;iCount<m_ObjectColorStruct.iNrObjects;iCount++)
		{
			if (strcmp(m_ObjectColorStruct.objColor->csName,szObjName) ==0)
			{
				for ( lVertexIndex = 0 ; lVertexIndex < p_stObject->xNbPoints ; lVertexIndex  ++ ,p_stColorRLID++)
				{
					p_stColorRLID->xA = m_ObjectColorStruct.objColor->xVertexColor[lVertexIndex].xRed;
				}
 
			}
		}
	}
}
#endif
 
/*
 *******************************************************************************************
 Goal:
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
void GLI_vSendObjectToLights
	( 
		GLI_tdstLight **p_stLight,
        GEO_tdstGeometricObject *p_stObject ,
        GEO_tdstColor *p_stColorRLID ,
        GEO_tdstColor *p_stColorRLIS ,
        GEO_tdstColor *p_stColorRLIA ,
        long lNumberOfLights,
        GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobaleMT
	)
{
	long lLightsCounter;
 
	p_stColorRLIA->xR = 0.0f;
	p_stColorRLIA->xG = 0.0f;
	p_stColorRLIA->xB = 0.0f;
	p_stColorRLIA->xA = 0.0f;
 

	/* treatment for dynamic lights only */
	for ( lLightsCounter = 0; lLightsCounter < lNumberOfLights; lLightsCounter ++ , p_stLight ++ )
	{
		if ( (*p_stLight)->b_lOnOff && (*p_stLight)->bValid && g_ucTableOfActiveLightsForChar[ lLightsCounter ] )
		{
            if ((*p_stLight)->lTypeOfLight == GLI_C_lAmbientLight)
            {
                GLI_vSendObjectToAmbientLight((*p_stLight) ,p_stObject ,p_stColorRLIA ,p_stGlobaleMT);
            }
            else if ( (*p_stLight)->lTypeOfLight == GLI_C_lSphericalLight)
            {
                GLI_vSendObjectToSphericalLightMain((*p_stLight) ,p_stObject ,p_stColorRLID ,p_stGlobaleMT);
            }
            else if ((*p_stLight)->lTypeOfLight == GLI_C_lParallelLight)
            {
                GLI_vSendObjectToParallelLight((*p_stLight) ,p_stObject ,p_stColorRLID ,p_stGlobaleMT );
            }
            else if ((*p_stLight)->lTypeOfLight == GLI_C_lParallelLight_With_Limit)
            {
                GLI_vSendObjectToParallelLightOtherType((*p_stLight) ,p_stObject ,p_stColorRLID ,p_stGlobaleMT);
            }
            else if ((*p_stLight)->lTypeOfLight == GLI_C_lHotSpotLight)
            {
                if (GLI_bIsObjectIntersectWithHotSpotLight((*p_stLight) ,p_stGlobaleMT ))
						GLI_vSendObjectToHotSpotLight((*p_stLight) ,p_stObject ,p_stColorRLID ,p_stGlobaleMT);
            }
		}
	}
    
#ifdef ACTIVE_EDITOR
	GLI_vComputeAlphaFromPLGFile(p_stObject ,p_stColorRLID );
#endif
 
    GLI_vFogWaterPlaneEffect(p_stGlobaleMT,0,p_stObject->xNbPoints);
}
 
/*
 =======================================================================================
	Other (RLI buffer, Init) 
 =======================================================================================
 */
 
void GLI_vCopyRLI2ComputeBuffer( GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobalsParrameters, GEO_tdstColor *p_stColorRLID , long xStart , long lNumber)
{
	if (p_stColorRLID == NULL)
		memset( p_stGlobalsParrameters->GLI_aDEF_stColorsRLID  + xStart, 0, lNumber * sizeof( GEO_tdstColor ) );
    else
		memcpy( p_stGlobalsParrameters->GLI_aDEF_stColorsRLID  + xStart, p_stColorRLID, lNumber * sizeof( GEO_tdstColor ) );
}
 
void GLI_vCopyRLI2ComputeBufferISI( GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobalsParrameters, ISI_tdstColor *p_stColorRLID , long xStart , long lNumber)
{
	ISI_ColISIToGEO(p_stGlobalsParrameters->GLI_aDEF_stColorsRLID  + xStart, p_stColorRLID, lNumber);
}
 
void GLI_vInitSpecularAndAmbiamt(GLI_tdstInternalGlobalValuesFor3dEngine *p_stGlobalsParrameters)
{
	p_stGlobalsParrameters->GLI_aDEF_stColorsRLIA.xR = 0.0f;
	p_stGlobalsParrameters->GLI_aDEF_stColorsRLIA.xG = 0.0f;
	p_stGlobalsParrameters->GLI_aDEF_stColorsRLIA.xB = 0.0f;
	p_stGlobalsParrameters->GLI_aDEF_stColorsRLIA.xA = 0.0f;
}
 
/*
 *******************************************************************************************
 Goal:
 Code: Philippe Vimont /1.0
 OPTIMMIZED : No
 *******************************************************************************************
 */
void GLI_vSpecularOn()
{
}
void GLI_vSpecularOff()
{
}
 
#ifdef __cplusplus
} /* extern "C" */
#endif
