/* ##C_FILE#
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FILE :          SHADDRAW.C
 
  DESCRIPTION :   Main file for SHW Module
 
	VERSION :       
	1.02 / François Queinnec / Nintendo64 support
	1.01 / Guenaele Mendroux / Level of detail
	1.00 / Philippe Thiébaut / Creation
 
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#define SHW_MAIN
 
/* FQ: This define forces shadows on every object*/
/* without checking for the custom bit..*/
/* usefull to determine wether it's the designer's fault */
/* or the programmer's one when there's no shadow.*/
/* #define SHW_FORCE_SHADOW 1*/
 
#define D_3dData_StructureDefine
#define D_3dData_VariableDefine
 
/* ##INCLUDE#----------------------------------------------------------------------------
Includes Files
---------------------------------------------------------------------------------------*/
 
#define D_3dData_StructureDefine
#define D_3dData_VariableDefine
 
#include "ACP_base.h"
#include "GAM\ToolsCPA.h"
#include "gam.h"
 
#include "GEO.h"
#include "GLI.h"
#include "COL.h"
#include "SPO.h"
#include "LST.h"
#include "MTH.h"
#include "SND.h"
#include "SCR.h"
#include "SCT.h"
/*This is the public section of SHW*/
#include "SHW\ShwCpa.h"
/*Important: ALL GLOBAL MY CONSTANTS ARE HERE !!!*/
#include "SHW\ShwConst.h"
#include "SHW\ShwStruc.h"
#include "SHW\ShwMacro.h"
#include "SHW\ShwHand.h"
#include "SHW\ShwFunct.h"
#include "SHW\ShwProto.h"
/*This is the private section of SHW*/
#include "ShwPriv.h"
#include "GLI\object.h"
 
 
#if (!defined(U64))
#include "SNA.h"
#endif
 
 
#include  "..\..\tempgrp\AI\AiGame\CAM_Base.h"
#include  "..\..\tempgrp\AI\AiGame\CAM_tool.h"
#ifdef USE_IPT_DX5
#include "IPT_DX5.h" /* InPuT (absolutely before GAM.h)*/
#else /* USE_IPT_WIN */
#include "IPT.h" /* InPuT (absolutely before GAM.h)*/
#endif /* USE_IPT_WIN */
#include "PCS.h" /* Physical Collide Set */
#include "RND.h" /* RaNDom*/
#include "FIL.h" /* SeCTor*/
#ifndef D_THROW_PRT
#include "PRT.h"
#endif /* D_THROW_PRT */
 
#include "Mec.h"
/*FQ*/
#ifdef U64
 
/* FQ SHADOW FIX*/
#include "mater_st.h"
#include "objects.h"
#include "sectinfo.h"
#include "MainChar.h"
#include "SPO\HieSpObj.h"
#include "GMT\GmtStruc.h"

/* XB 05/05/99 */
#include "GLI\Specif\u_load.h"
/* End XB 05/05/99 */
#endif
 
extern CPA_EXPORT unsigned long fn_ulStandardGameGetCustomBitsSO (HIE_tdxHandleToSuperObject hSupObj);
extern unsigned long g_ulSpoMask;
 
#include "PRF.h"
 
/* ************************************************************************************/
/* ****************** Nintendo64 Specific Includes & Defines **************************/
/* ************************************************************************************/
#if defined(U64)
 
#include "U_Elt.h" /* We include specific Nin64 Elements*/
#include "Element.h" /* We must include this to properly handle the object format conversion*/
#include "LDR\Specif\getval.h"
#include "LDR\Specif\memload.h"
#include "GLI\Specif\u_VMTLd.h"
#include "h_bitmap.h"
 
/* Here we declare the VTX and GFX Lists*/
Vtx                         *g_p_stVtxListForShadow[SHW_C_xNbMaxOfShadows];
Gfx                         *g_p_stGfxListForShadow[SHW_C_xNbMaxOfShadows];
MTH3D_tdstVector			g_pstPickedPointArray[SHW_C_xNbMaxOfShadows];
extern unsigned short		g_uwGlobalAlpha;
 
/* The structure for the face-definitions*/
POS_tdstCompletePosition g_stTranslationMatrixForGoodScale[SHW_C_xNbMaxOfShadows];
 
#define SHW_C_xNbMaxOfGfxPerShadow          13
#define SHW_C_xU64ScaleForGeometricShadow   1000.0f
#define SHW_C_xU64UVScaleForShadow          1024.0f
#define SHW_C_xZeroForComparisonForN64      0.0001f
#define SHW_C_xOneForComparisonForN64       0.9999f
ACP_tdxHandleOfObject g_hShadowObjectN64[SHW_C_xNbMaxOfShadows];
 
int g_MustDisplayShadow;
char g_UseNormalMatrixStack=0;
 
 
/* This is the shift Z value for the shadow not to be */
/* exactly on the ground, but just a little higher...*/
/* To prevent ZBuffer problems....*/
/* #define SHW_C_ZBiasForZBuffer               0.08f*/
#define SHW_C_ZBiasForZBuffer               0.03f
 
#define SHW_C_ucRedValue    50
#define SHW_C_ucGreenValue  50
#define SHW_C_ucBlueValue   50
#define SHW_C_ucAlphaValue  255
 
#endif /* U64 */
 
 
#if defined(USE_PROFILER) && !defined(PRESS_DEMO)
extern  void HIE_fn_vUpdateRasterForObject( GEO_tdstGeometricObject *p_stObject,
                                            unsigned long _ulRasterObject,
                                            unsigned long _ulRasterFace,
                                            unsigned long _ulRasterElement );
#else
    #define HIE_fn_vUpdateRasterForObject(p_stObject,_ulRasterObject,_ulRasterFace,_ulRasterElement)
#endif /* USE_PROFILER */
 
 
/*****************************************************************/
/************************ Globalvariables ************************/
/*****************************************************************/
GLD_tdstDeviceAttributes    g_stDevAttrib;
ACP_tdxHandleOfMaterial     g_hShadowPolygonVisualMaterial;
GMT_tdxHandleToGameMaterial g_hShadowPolygonGameMaterial;
GMT_tdxHandleToGameMaterial g_hShadowPolygonGameMaterialInit;
short                       g_xIndexOfShadow;
 
/*Array of geometric object that contains the shadow faces to be drawn*/
ACP_tdxHandleOfObject       p_hHandleOfGeometricShadowObject[SHW_C_xNbMaxOfShadows];
ACP_tdxHandleOfElement      g_p_hHandleOfElementForShadow[SHW_C_xNbMaxOfShadows];
 
#define NO_COMPLEX_SHADOW
#define SHW_C_xMinZValueForShadowedFace  MTH_M_xFloatToReal(0.5f)
 
void SHW_fn_vSentToViewPort(struct GLD_tdstViewportAttributes_ *_p_stVpt, HIE_tdxHandleToSuperObject _hHandleOfCharacter,
							HIE_tdxHandleToSuperObject _hSprObjSector, long _lSectorDrawmask, ACP_tdxHandleOfObject _hHandleOfGeometricShadowObject);
 
 
extern char				g_cSinusEffectState;
extern MTH3D_tdstVector	stSinEffectAmp;
 
 
#ifndef NO_COMPLEX_SHADOW
#include "shaddraw.cxx"		/* this file contains all functions to process complex shadows*/
#else

#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC 04/06/99 */
GLI_tdstTexture             *g_p_stTextureOfTextureShadow;
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC 04/06/99 */

#endif
 
 
 
#ifdef U64
 
/*****************************************************************/
/************** Nintendo64 Specific Functions ********************/
/*****************************************************************/
 
 
/* ##F===================================================================================
NAME :          SHW_fn_vCreateElementU64IndexedTriangles
DESCRIPTION :   Create the structure of the element U64IndexedTriangles
                WARNING: ONLY FOR SHW MODULE  !!!
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fn_vCreateElementU64IndexedTriangles (ACP_tdxHandleOfObject hU64ObjectForShadow,
                                               unsigned long uiElement)
{
  GEO_tdstElementU64IndexedTriangles *p_stLocalElement;
  
  hU64ObjectForShadow->d_xListOfElementsTypes[uiElement]=GEO_C_xElementU64IndexedTriangles;
 
  GEO_M_CPAMalloc(hU64ObjectForShadow->d_stListOfElements[uiElement],
		void * ,
		sizeof (GEO_tdstElementU64IndexedTriangles),
		E_uwGEONotEnoughtMemory);
 
  p_stLocalElement = (GEO_tdstElementU64IndexedTriangles *) hU64ObjectForShadow->d_stListOfElements[uiElement];
  p_stLocalElement->p_stVtxList=NULL;
  p_stLocalElement->p_stGfxList=NULL;
  p_stLocalElement->hMaterial=NULL;
 
#if defined(_U64_GLI_BENCH_)
	p_stLocalElement->uwNbFaces = 0L;
	p_stLocalElement->uwSizeOfFacesInBytes = 0L;
#endif /* _U64_GLI_BENCH_ */
}

/* ##F===================================================================================
NAME :          SHW_fn_vAddPointToVtxList
DESCRIPTION :   Add a geometric 3D Vector with UV in the indexed VtxList
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/

  /* ANTI-BUG*/
  /* Sometimes, the PC version sends me some really weird coordinates*/
  /* Then, we simply don't draw shadows !!!*/
/*  if (((ft1>32760.0f) && (ft1<-32760.0f)) || ((ft2>32760.0f) && (ft2<-32760.0)) || ((ft3>32760.0) && (ft3<-32760.0))) 
  {
	  g_MustDisplayShadow=0; return;
  }
  */
 
 
 
/* ##F===================================================================================
NAME :          SHW_fn_vAddAllFacesToGfxList
DESCRIPTION :   Add all faces of the shadow or the footstep in the indexed GfxList
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
 
/*
=========================================================================================
NAME :          SHW_ConvertPCtoN64GeometricObject
DESCRIPTION :   converts a PC geometric Object to a U64 Geometric object
				NOTE : It's only for shadows, with only 1 element 
				(GEO_tdstElementIndexedTriangles -> GEO_tdstElementU64IndexedTriangles)
=========================================================================================
CREATION : François Queinnec
=======================================================================================*/
		
		/*/////////////////////////*/
		/* MEGA ANTI-BUG !!!*/
		/*/////////////////////////*/
/* 
		{
			long lExposant;
#define MIN_VALUE_FOR_EXPOSANT	125
			lExposant=(((*((long *)&(pvPoints->xX)))>>23)&0xFF);
			if (lExposant<MIN_VALUE_FOR_EXPOSANT)  { g_MustDisplayShadow=0; return g_hShadowObjectN64[g_xIndexOfShadow]; }
 
			lExposant=(((*((long *)&(pvPoints->xY)))>>23)&0xFF);
			if (lExposant<MIN_VALUE_FOR_EXPOSANT)  { g_MustDisplayShadow=0; return g_hShadowObjectN64[g_xIndexOfShadow]; }
 
			lExposant=(((*((long *)&(pvPoints->xZ)))>>23)&0xFF);
			if (lExposant<MIN_VALUE_FOR_EXPOSANT)  { g_MustDisplayShadow=0; return g_hShadowObjectN64[g_xIndexOfShadow]; }	
		}
*/
 
 
/*****************************************************************/
/***************** END OF U64 SPECIFIC FUNCTIONS *****************/
/*****************************************************************/
#endif
 
 
 
/* ##F===================================================================================
NAME :          SHW_fn_vInitShadow
DESCRIPTION :   Init of the Array of Geometric Objects for the Characters' shadows
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
/* FQ : */
/* Since the Ultra64 uses VTX and GFX lists*/
/* The GeometricObjects and the Material loading are differents.*/
/* that's why I use an almost completely different function*/
#if defined( U64)
 
/* FQ SHADOW FIX*/
 
GMT_tdstGameMaterial g_stShadowMaterial;
GMT_tdxHandleToGameMaterial g_p_stShadowMaterial=&g_stShadowMaterial;
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void SHW_InitGeometric(ACP_tdxHandleOfObject hShadowObject)
{
 
	register MTH3D_tdstVector *pvPoints;
	register long i;
	register long lNbPoints;
	
	pvPoints=hShadowObject->d_stListOfPoints;
	lNbPoints=SHW_C_xNbMaxOfPointsPerShadow;
 
	for(i=0;i<lNbPoints;i++)
	{
		pvPoints->xX=-33000.0f;
		pvPoints->xY=-33000.0f;
		pvPoints->xZ=-33000.0f;
	}
 
	for(i=0;i<SHW_C_xNbMaxOfShadows;i++)
	{
		g_pstPickedPointArray[i].xX=0.0f;
		g_pstPickedPointArray[i].xY=0.0f;
		g_pstPickedPointArray[i].xZ=0.0f;
	}
} 
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
 
void SHW_fn_vInitShadow(GLD_tdhDevice _hGLDDevice)
{
	ACP_tdxIndex                 xNbMaxOfPoints=SHW_C_xNbMaxOfPointsPerShadow;
	ACP_tdxIndex                 xNbMaxOfFaces=SHW_C_xNbMaxOfFacesPerShadow;
	ACP_tdxIndex                 i;
	ACP_tdxHandleOfObject		 *p_hHandleGeoShwObj;
	ACP_tdxHandleOfElement		 *p_hHandleOfElementForShadow;
 
	ACP_tdxHandleOfMaterial		hVisualMaterial ;
 
	/* FQ SHADOW FIX*/
	U64_tdstFix *p_stFix;
	
	M_PrintfN64(("Initializing Shadows in Fix\n"));
/* XB 23/06/99 */
	//unused _hGLDDevice is NULL
	//if (_hGLDDevice!=NULL) GLD_bGetDeviceAttributes(_hGLDDevice,&g_stDevAttrib);
/* End XB 23/06/99 */
 
	p_stFix =
		(U64_tdstFix *)
			fn_pvLoadFromRomTmpWithSize(
/*XB for new fixfix*/
/*		D_BINSCR_StructFix,*/
			D_BINSCR_StructFixData,
/*		0*/
			0|D_BINSCR_IsInFixFixFat,
/*End XB*/
				sizeof(U64_tdstFix));
 
	g_p_stShadowMaterial->hVisualMaterial=NULL;
	g_p_stShadowMaterial->hMechanicsMaterial=NULL;
	g_p_stShadowMaterial->hSoundMaterial=NULL;
	g_p_stShadowMaterial->hCollideMaterial=NULL;
/* fbolefeysot - 01/10/98*/
/* remove init values in GMT{*/
/*	g_p_stShadowMaterial->p_stInitialValues=NULL;//END fbolefeysot}*/
 
	#ifdef SECTOR_IN_GMT
	g_p_stShadowMaterial->hSectorMaterial=NULL;
	#endif
 
	GLI_xCreateMaterial(&(g_p_stShadowMaterial->hVisualMaterial));
 
	hVisualMaterial=g_p_stShadowMaterial->hVisualMaterial;
 
	hVisualMaterial->xMaterialType = 2047;
#ifndef CONST_VMT
	hVisualMaterial->lSpecularExponent=5;
#endif
 
 
	if (p_stFix->xShadowTextureId==D_BINSCR_InvalidId)
		M_PrintfN64(("p_stFix->xShadowTextureId==D_BINSCR_InvalidId\n"));
 
	g_p_stShadowMaterial->hVisualMaterial->p_stTexture =	(struct GLI_tdstTexture_ *)fn_p_stLoadTexture(p_stFix->xShadowTextureId);
 
	g_p_stShadowMaterial->hVisualMaterial->ulGouraudColor=0;
	
	fn_vFreeRomTmp( (void *)p_stFix );	/* Oliv'*/
	
		/* The material has been loaded, so now we can really initialize */
		/* the shadow variables*/
		g_hShadowPolygonVisualMaterial = g_p_stShadowMaterial->hVisualMaterial;
		g_hShadowPolygonGameMaterial=g_p_stShadowMaterial;
		p_hHandleGeoShwObj = p_hHandleOfGeometricShadowObject;
		p_hHandleOfElementForShadow = g_p_hHandleOfElementForShadow;
		
		for (i=0;i<SHW_C_xNbMaxOfShadows;i++, p_hHandleGeoShwObj++,	p_hHandleOfElementForShadow++)
		{
			GEO_vCreateGeometricObject(p_hHandleGeoShwObj,xNbMaxOfPoints,1);
			GEO_vCreateElementIndexedTriangles(*p_hHandleGeoShwObj,p_hHandleOfElementForShadow,xNbMaxOfFaces,xNbMaxOfPoints);
			GEO_vSetGameMaterialOfIndexedTriangles(*p_hHandleGeoShwObj,*p_hHandleOfElementForShadow,g_hShadowPolygonGameMaterial);
			g_p_stVtxListForShadow[i]=NULL;
			g_p_stGfxListForShadow[i]=NULL;
			g_hShadowObjectN64[i]=NULL;
		}
		
		g_hShadowPolygonGameMaterialInit=g_hShadowPolygonGameMaterial;
 
	/* END OF FQ SHADOW FIX*/
}/*SHW_fn_vInitShadow*/
 
void SHW_fn_vReInitShadowForMapChange(void)
{
	int i;
	for(i=0;i<SHW_C_xNbMaxOfShadows;i++)
	{
		g_p_stVtxListForShadow[i]=NULL;
		g_p_stGfxListForShadow[i]=NULL;
		g_hShadowObjectN64[i]=NULL;
	}
} /*SHW_fn_vReInitShadowForMapChange*/
 
#else /* U64*/
 
/* FQ : This is the PC / General version*/
 
void SHW_fn_vReInitShadowForMapChange(void)
{
}
 
 
void SHW_fn_vInitShadow(GLD_tdhDevice _hGLDDevice)
{
	ACP_tdxIndex                 xNbMaxOfPoints=SHW_C_xNbMaxOfPointsPerShadow;
	ACP_tdxIndex                 xNbMaxOfFaces=SHW_C_xNbMaxOfFacesPerShadow;
	GLI_tdstColor                stShadowPolygonColor;
	ACP_tdxIndex                 i;
	ACP_tdxHandleOfObject		 *p_hHandleGeoShwObj;	
	ACP_tdxHandleOfElement		 *p_hHandleOfElementForShadow;	
 
 
	if (SNA_fn_ucGetLoadType()!=SNA_LOAD_SNAPSHOT) 
 
	{
		GLI_xCreateMaterial(&g_hShadowPolygonVisualMaterial);
		stShadowPolygonColor.xR=MTH_C_ZERO;
		stShadowPolygonColor.xG=MTH_C_ZERO;
		stShadowPolygonColor.xB=MTH_C_ZERO;
		stShadowPolygonColor.xA=MTH_C_ZERO;
#ifndef CONST_VMT
		GLI_xSetMaterialAmbientCoef(g_hShadowPolygonVisualMaterial,&stShadowPolygonColor);
		GLI_xSetMaterialDiffuseCoef(g_hShadowPolygonVisualMaterial,&stShadowPolygonColor);
#endif
		GLI_xSetMaterialSpecularCoef(g_hShadowPolygonVisualMaterial,2,&stShadowPolygonColor);
		GLI_xSetMaterialType(g_hShadowPolygonVisualMaterial,GLI_C_lAllIsEnable);
	}
	
	GLD_bGetDeviceAttributes(_hGLDDevice,&g_stDevAttrib);
 
	if (SNA_fn_ucGetLoadType()!=SNA_LOAD_SNAPSHOT) 
 
	{
		GLI_xSetMaterialTexture(g_hShadowPolygonVisualMaterial,g_p_stTextureOfTextureShadow);
		g_hShadowPolygonGameMaterial=GMT_fn_hCreateGameMaterial();
		GMT_fn_vSetVisualMaterial(g_hShadowPolygonGameMaterial,g_hShadowPolygonVisualMaterial);
 
		p_hHandleGeoShwObj = p_hHandleOfGeometricShadowObject;
		p_hHandleOfElementForShadow = g_p_hHandleOfElementForShadow;
		/*Creation of geometric objects*/
		for (i=0;i<SHW_C_xNbMaxOfShadows;i++, p_hHandleGeoShwObj++,	p_hHandleOfElementForShadow++) 
		{
 
			GEO_vCreateGeometricObject(p_hHandleGeoShwObj,xNbMaxOfPoints,1);
			GEO_vCreateElementIndexedTriangles(*p_hHandleGeoShwObj,p_hHandleOfElementForShadow,xNbMaxOfFaces,xNbMaxOfPoints);
			GEO_vSetGameMaterialOfIndexedTriangles(*p_hHandleGeoShwObj,*p_hHandleOfElementForShadow,g_hShadowPolygonGameMaterial);
		}
	}
	g_hShadowPolygonGameMaterialInit=g_hShadowPolygonGameMaterial;
} /* SHW_fn_vInitShadow*/
 
#endif /* U64*/
 
/* ##F===================================================================================
NAME :          SHW_fn_vInitShadowCounter
DESCRIPTION :   Initialization of the Counter for the Characters' shadows. 
MUST BE RUN AT EACH FRAME
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fn_vInitShadowCounter(void)
{
	g_xIndexOfShadow=0;
}
 
 
/* ##F===================================================================================
NAME :          SHW_fn_vSentToViewPort
DESCRIPTION :   Sent Shadow to the viewport
=========================================================================================
CREATION : Yann Le Guyader
=======================================================================================*/
void SHW_fn_vSentToViewPort
(
	struct GLD_tdstViewportAttributes_		*_p_stVpt,
	HIE_tdxHandleToSuperObject				_hHandleOfCharacter,
	HIE_tdxHandleToSuperObject				_hSprObjSector,
	long									_lSectorDrawmask,
	ACP_tdxHandleOfObject					_hHandleOfGeometricShadowObject
)
{
	register long							lAdditionnalDrawMask = 0;
	register ACP_tdxBool						bTransparenceSetting = FALSE;
	register float							fGlobalAlphaTemp;
 
#if defined(U64) /* FQ: Here we need a special Ultra64 Object...*/
/* XB 05/05/99 */
	/* 	ACP_tdxHandleOfObject _hHandleOfGeometricShadowObjectN64; */
/* End XB 05/05/99 */
	g_hShadowPolygonGameMaterial = g_hShadowPolygonGameMaterialInit;
#else /* defined(U64)*/
	g_hShadowPolygonGameMaterial = fn_x3dDataGetShadowMaterialFromSO(_hHandleOfCharacter);
 
 
	GEO_vSetGameMaterialOfIndexedTriangles(_hHandleOfGeometricShadowObject,g_p_hHandleOfElementForShadow[g_xIndexOfShadow],g_hShadowPolygonGameMaterial);
#endif
 
	HIE_fn_bLoadIdentity();
 
#ifndef U64
	/* Transparence */

	/* if char uses ZFar transparency */
	if( fn_ulStandardGameGetCustomBitsSO(_hHandleOfCharacter) & GAM_C_CustBitUsesTransparencyZone )
	{
		fGlobalAlphaTemp = GLI_vGetGlobalAlpha();
		GLI_vSetGlobalAlpha( 
			MTH_M_xRealToFloat( GEO_xGetZFarTransparencyLevel() ) * 
			HIE_fn_fGetSuperObjectTransparenceLevel(_hHandleOfCharacter) );
		_lSectorDrawmask &= ~GLI_C_lIsNotGrided & ~GLI_C_lNotForceZSorting;
		bTransparenceSetting = TRUE;
	}
	/* else if char is transparent */
	else if ((HIE_fn_lGetSuperObjectDrawMask(_hHandleOfCharacter) & GLI_C_lIsNotGrided) == 0)
	{
		_lSectorDrawmask &= ~GLI_C_lIsNotGrided & ~GLI_C_lNotForceZSorting;
		fGlobalAlphaTemp = GLI_vGetGlobalAlpha();
		GLI_vSetGlobalAlpha( HIE_fn_fGetSuperObjectTransparenceLevel(_hHandleOfCharacter) );
		bTransparenceSetting = TRUE;
	}
	else
#endif
	{
		lAdditionnalDrawMask = - GLI_C_lNotForceZSorting - GLI_C_lIsWriteZBuffer;
	}
 
	PRF_fn_vStopChrono( PRF_C_ulFctDisplayCommon, PRF_C_pvShadow );
	PRF_fn_vStopChrono( PRF_C_ulFctDisplay, PRF_C_pvMisc );
	PRF_fn_vStartChrono( PRF_C_ulFctMainMisc, NULL );
 
    HIE_fn_vUpdateRasterForObject( _hHandleOfGeometricShadowObject, PRF_C_ulVarShwObjects, PRF_C_ulVarShwFaces, PRF_C_ulVarShwElements );
    PRF_fn_vSetIndependantVariable( PRF_C_ulIdpDynOrSta, PRF_C_ulShadow );
    PRF_fn_vSetIndependantVariable( PRF_C_ulIdpDisplayedObjects, 0 );
    PRF_fn_vSetIndependantVariable( PRF_C_ulIdpDisplayedElements, 0 );     /* init flag "faces displayed"*/
 
	PRF_fn_vStopChrono( PRF_C_ulFctMainMisc, NULL );
	PRF_fn_vStartChrono( PRF_C_ulFctDisplaySpecific, PRF_C_pvMisc );
 
 
#if defined(U64)
	/* FQ: Here, we need to convert the Geometric Object on Nintendo64, before we send it to GLI*/
	/* On the U64, we need to convert the coordinates*/
	/* using the Translation vector defined by the picked point.*/
 
	POS_fn_vSetIdentityMatrix(&g_stTranslationMatrixForGoodScale[g_xIndexOfShadow]);  
          
	/* We actualy convert the geometric Object*/
	//_hHandleOfGeometricShadowObjectN64=SHW_ConvertPCtoN64GeometricObject(_hHandleOfGeometricShadowObject);
	// _hHandleOfGeometricShadowObjectN64=;
 
    if (g_MustDisplayShadow)
	{
		int OldValue;
		POS_fn_vSetTranslationVector(&g_stTranslationMatrixForGoodScale[g_xIndexOfShadow],&g_pstPickedPointArray[g_xIndexOfShadow]);
		HIE_fn_bStoreMatrix(&g_stTranslationMatrixForGoodScale[g_xIndexOfShadow]);
		
		/* Then we can send it*/
		OldValue=g_UseNormalMatrixStack;
		g_UseNormalMatrixStack=1;
		GLI_xSendObjectToViewportWithLights (_p_stVpt ,_hHandleOfGeometricShadowObject,(((_lSectorDrawmask | lAdditionnalDrawMask) | 0x4000 /* Forcing Priority Bit 14 */ ) & (~GLI_C_lIsNotGrided))); /* we pop the additionnal matrix */
		g_UseNormalMatrixStack=OldValue;
		
		/* we pop the additionnal matrix*/
		HIE_fn_vPopMatrix();
	}
 
#else /* On PC, we simply call the GLI_xSendObjectToViewportWithLights function*/
 
	GLI_xSendObjectToViewportWithLights (_p_stVpt ,_hHandleOfGeometricShadowObject,_lSectorDrawmask | lAdditionnalDrawMask);
 
#endif /* U64*/
 
 
	PRF_fn_vStopChrono( PRF_C_ulFctDisplaySpecific, PRF_C_pvMisc );
	PRF_fn_vStartChrono( PRF_C_ulFctDisplay, PRF_C_pvMisc );
	/*PRF_fn_vStartChrono( PRF_C_ulFctDisplayCommon, PRF_C_pvSendActor );*/
	PRF_fn_vStartChrono( PRF_C_ulFctDisplayCommon, PRF_C_pvShadow );
 
    if( PRF_fn_lGetIndependantVariable( PRF_C_ulIdpDisplayedElements ) )   /* at least one face has been displayed*/
/* END ANNECY MT }*/
    {
        PRF_fn_vIncreaseVariable( PRF_C_ulVarObjects + PRF_fn_lGetIndependantVariable( PRF_C_ulIdpDynOrSta ), PRF_C_pvDisplayed, 1 );  /* update number of displayed objects*/
        PRF_fn_vSetIndependantVariable( PRF_C_ulIdpDisplayedObjects, 1 ); /* set flag "object displayed" for sector*/
    }
    PRF_fn_vSetIndependantVariable( PRF_C_ulIdpDynOrSta, PRF_C_ulDynamic );
 
	/* restore the old transparence coefficient */
	if (bTransparenceSetting)
		GLI_vSetGlobalAlpha(fGlobalAlphaTemp);
 
	HIE_fn_vPopMatrix();
}
 
/* ##F===================================================================================
NAME :          SHW_fn_vComputeShadowRectangle
DESCRIPTION :   compute the coordinates of shadow in quality = 1
=========================================================================================
CREATION : Fabien Bole-Feysot
=======================================================================================*/
MTH_tdxReal SHW_fn_vComputeZofShadowPoint (MTH3D_tdstVector	*_p_stPickedPoint, 
										   MTH3D_tdstVector	*_p_stGlobalNormalOfPickedFace,
										   MTH_tdxReal		_xInvGlobalNormalxZ,
										   MTH_tdxReal		_xOffsetX,
										   MTH_tdxReal		_xOffsetY)
{
	return (MTH_M_xSub (_p_stPickedPoint->xZ,
						MTH_M_xMul(_xInvGlobalNormalxZ,
								   MTH_M_xAdd(
											  MTH_M_xMul(_p_stGlobalNormalOfPickedFace->xX,
														 MTH_M_xSub(_xOffsetX,_p_stPickedPoint->xX)),
											  MTH_M_xMul(_p_stGlobalNormalOfPickedFace->xY,
														 MTH_M_xSub(_xOffsetY,_p_stPickedPoint->xY))
											 )
								  )
						)		  
		   );
}
 
/* ##F===================================================================================
NAME :          SHW_fn_vDrawShadow
DESCRIPTION :   Draw a Fake Shadow for a Character
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fn_vDrawShadow (	struct GLD_tdstViewportAttributes_ *_p_stVpt,
							HIE_tdxHandleToSuperObject			_hHandleOfCharacter,
							HIE_tdxHandleToSuperObject			_hSprObjSector,
							long								_lSectorDrawmask)
{
	MTH3D_tdstVector                stGlobalNormalOfPickedFace,stStartPicking,stVertexAB,stPickedPoint;
	GEO_tdxHandleToMatrix           hGlobalMatrixOfCharacter;
	MTH_tdxReal                     xCoefAltitude;
#ifndef U64
	GEO_tdstElementIndexedTriangles	*p_stIndexedTriangle; 
#endif
	MTH_tdxReal                     xScaleX;
	MTH_tdxReal                     xScaleY;
	ACP_tdxHandleOfObject			hHandleOfGeometricShadowObject = NULL;
	HIE_tdxHandleToSuperObject		hTest;
	
	
	/*	PRF_fn_vStartChrono(PRF_C_ulGLI8, NULL);*/
	
#ifndef U64
	/* if there is no material for the shadow, there is no shadow*/
	if (fn_x3dDataGetShadowMaterialFromSO(_hHandleOfCharacter) == NULL)
		return;
#endif
	
	/* if bad viewport or not active, no shadow*/
	if( HIE_fn_SO_bIsSuperimposed(_hHandleOfCharacter) ||
		!fn_bf1StandardGameGetIsActive(M_GetMSHandle(_hHandleOfCharacter,StandardGame))
		)
		return;

	/* If character uses ZFar transparency and is too far, no shadow. */
	if( ( fn_ulStandardGameGetCustomBitsSO(_hHandleOfCharacter) & GAM_C_CustBitUsesTransparencyZone )
	    && ( GEO_xGetZFarTransparencyLevel() == MTH_C_ZERO ) )
		return;

 
#ifdef NO_COMPLEX_SHADOW
	/* if quality of shadow is 0, no shadow*/
/*XB ShadowQuality is always 2*/
#ifndef U64
	if (fn_x3dDataGetShadowQualityFromSO(_hHandleOfCharacter) == 0)
		return;
#endif /* U64 */
/*End XB*/
#else
	/* if quality of shadow is 0, no shadow*/
	g_xLevelOfQualityOfShadows = fn_x3dDataGetShadowQualityFromSO(_hHandleOfCharacter);
	if (g_xLevelOfQualityOfShadows == 0)
		return;
	if (g_xGeneralLevelOfQualityOfShadows<g_xLevelOfQualityOfShadows)
		g_xLevelOfQualityOfShadows = g_xGeneralLevelOfQualityOfShadows;
#endif
 
	
#if defined(U64)
	
	g_MustDisplayShadow = 1;
	if (g_hShadowPolygonGameMaterialInit == NULL) 
	{
		M_PrintfN64(("No shadow material loaded at first pass of DrawShadow !!!!\n"));
	}
	
	/*Allocate memory for Gfxlists and VtxLists if not done*/
	if (g_p_stVtxListForShadow[g_xIndexOfShadow]==NULL)
	{
		Vtx *pVtxList;
		Gfx *pGfx;
		g_p_stVtxListForShadow[g_xIndexOfShadow]=(Vtx *)TMP_M_p_Malloc(4*sizeof(Vtx));
		g_p_stGfxListForShadow[g_xIndexOfShadow]=(Gfx *)TMP_M_p_Malloc(5*sizeof(Gfx));

		pVtxList=g_p_stVtxListForShadow[g_xIndexOfShadow];
		pGfx=g_p_stGfxListForShadow[g_xIndexOfShadow];

		pVtxList->v.tc[0]=0;
		pVtxList->v.tc[1]=0;
		pVtxList->v.flag=0;
		pVtxList->v.cn[0]=255;
		pVtxList->v.cn[1]=255;
		pVtxList->v.cn[2]=255;
		pVtxList->v.cn[3]=255;

		pVtxList++;
		pVtxList->v.tc[0]=SHW_C_xU64UVScaleForShadow*2;
		pVtxList->v.tc[1]=0;
		pVtxList->v.flag=0;
		pVtxList->v.cn[0]=255;
		pVtxList->v.cn[1]=255;
		pVtxList->v.cn[2]=255;
		pVtxList->v.cn[3]=255;
				
		pVtxList++;
		pVtxList->v.tc[0]=SHW_C_xU64UVScaleForShadow*2;
		pVtxList->v.tc[1]=SHW_C_xU64UVScaleForShadow*2;
		pVtxList->v.flag=0;
		pVtxList->v.cn[0]=255;
		pVtxList->v.cn[1]=255;
		pVtxList->v.cn[2]=255;
		pVtxList->v.cn[3]=255;

		pVtxList++;
		pVtxList->v.tc[0]=0;
		pVtxList->v.tc[1]=SHW_C_xU64UVScaleForShadow*2;
		pVtxList->v.flag=0;
		pVtxList->v.cn[0]=255;
		pVtxList->v.cn[1]=255;
		pVtxList->v.cn[2]=255;
		pVtxList->v.cn[3]=255;

		pVtxList=g_p_stVtxListForShadow[g_xIndexOfShadow];
		gSPClearGeometryMode(pGfx++,G_CULL_BOTH);
		gSPVertex(pGfx++,OS_K0_TO_PHYSICAL(pVtxList),4,0);
		gDPPipeSync(pGfx++);
		gSP2Triangles(pGfx++,0,3,1,0,1,3,2,0);
		gSPEndDisplayList(pGfx++);
	}
	
#endif
	
	if (g_xIndexOfShadow < SHW_C_xNbMaxOfShadows)
	{
		HIE_tdxHandleToSuperObject						hCurrentPerso,hHandleOfFather;
		SECT_tdxHandleOfElementLstCharacter				hCharacterList;
		SECT_tdxHandleOfElementLstCollisionInteraction	hCollisionElement;
		SECT_tdxHandleOfElementLstActivityInteraction	hInteractionElement;
		long											i,j;
		BOOL											bFound = FALSE;
/* XB 05/05/99 */
	/* 	BOOL											bSectorLimit = FALSE; */
/* End XB 05/05/99 */
 
#ifndef NO_COMPLEX_SHADOW
		if (g_xLevelOfQualityOfShadows == 2)
		{
			SHW_fn_vDrawComplexShadow(_p_stVpt,_hHandleOfCharacter,_hSprObjSector,_lSectorDrawmask);
			return;
		}
#endif
 
		hGlobalMatrixOfCharacter=HIE_fn_hGetSuperObjectGlobalMatrix(_hHandleOfCharacter);
		POS_fn_vGetTranslationVector(hGlobalMatrixOfCharacter, &stStartPicking ) ;
		
		hHandleOfGeometricShadowObject = p_hHandleOfGeometricShadowObject[g_xIndexOfShadow];
		
		xScaleX = MTH_M_xAbs(fn_x3dDataGetShadowScaleXFromSO(_hHandleOfCharacter));
		xScaleY = MTH_M_xAbs(fn_x3dDataGetShadowScaleYFromSO(_hHandleOfCharacter));
		
		/* object detection starts 1.8m upper the actor*/
		stStartPicking.xZ = MTH_M_xAdd(stStartPicking.xZ,MTH_M_xFloatToReal(1.8f));
		/* object are detected 14.5 meters below the actor*/
		MTH3D_M_vSetVectorElements(&stVertexAB,MTH_C_ZERO,MTH_C_ZERO,MTH_M_xFloatToReal(-14.5f));
		
		/* begin with tests on a perso, so reset the mask to scan all objects:*/
		g_ulSpoMask = 0;
		
		/* first, look if the perso is on a platform...*/
		hHandleOfFather = HIE_fn_hGetSuperObjectFather(_hHandleOfCharacter);
		if (HIE_fn_ulGetSuperObjectType(hHandleOfFather) & HIE_C_ulActor)
		{
			/* The perso is on a platform...*/
			/* so detect only on the platform and nowhere else !*/
			if ( (fn_ulStandardGameGetCustomBitsSO(hHandleOfFather) & GAM_C_CustBitShadowOnMe) &&  /* actor accepts shadows*/
				(fn_bf1StandardGameGetIsActive(M_GetMSHandle(hHandleOfFather,StandardGame))) )  /* active*/
			{
				if (HIE_bIntersectSegmentWithFirstSuperObject(&stStartPicking,&stVertexAB,hHandleOfFather,&stPickedPoint,&stGlobalNormalOfPickedFace,&hTest))
				{
					/* intersection found, check normal*/
					bFound |= MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace);
				}
			}
		}
		else
		{
			/* search in dynamic hierarchy of sector*/
			SECT_M_ForEachCharListInSector(_hSprObjSector,hCharacterList,i)
			{
				hCurrentPerso = SECT_GetCharacterInList(hCharacterList);
				if (hCurrentPerso != _hHandleOfCharacter)
				{
					if ( (fn_ulStandardGameGetCustomBitsSO(hCurrentPerso) & GAM_C_CustBitShadowOnMe) &&  /* actor accepts shadows*/
						(fn_bf1StandardGameGetIsActive(M_GetMSHandle(hCurrentPerso,StandardGame))) )  /* active*/
					{
						if (HIE_bIntersectSegmentWithFirstSuperObject(&stStartPicking,&stVertexAB,hCurrentPerso,&stPickedPoint,&stGlobalNormalOfPickedFace,&hTest))
						{
							/* intersection found, check normal*/
							bFound |= MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace);
						}
					}
				}
			}
			
			/* test on a sector, so set global mask to check SPO shadow flag :*/
			g_ulSpoMask = HIE_C_Flag_ulNoShadowOnMe;
			/* search in static hierarchy of sector*/
			if (HIE_bIntersectSegmentWithFirstSuperObject(&stStartPicking,&stVertexAB,_hSprObjSector,&stPickedPoint,&stGlobalNormalOfPickedFace,&hTest))
			{
				bFound |= (MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace));
			}
			
/*			if (!bFound)*/
/*			{*/
				/* didn't find in first sector!!!*/
				/* search in all active sectors for actors...*/
				/* test on actors, so reset global mask*/
				g_ulSpoMask = 0;
				SECT_M_ForEachActivityNodeInActivityInteractionList(_hSprObjSector,hInteractionElement,i)
				{	
					MTH3D_tdstVector			stMin, stMax;
					HIE_tdxHandleToSuperObject	hSector;
					SECT_tdxHandleOfSectorObject	hSectorObject;
					
					/* scan every collision sector*/
					hSector = SECT_GetSectorInActivityList(hInteractionElement);
					hSectorObject = (SECT_tdxHandleOfSectorObject) HIE_fn_hGetSuperObjectObject(hSector);
					/* if the sector border is not in intersection with the segment, don't scan its characters*/
					/* get the border box of the sector*/
					SECT_fn_vGetMinPointInBorder(hSectorObject, &stMin);
					SECT_fn_vGetMaxPointInBorder(hSectorObject, &stMax);
					if (INT_fn_bDetectIntersectSegmentWithBox (&stStartPicking,&stVertexAB,&stMin,&stMax,NULL))
					{
						/* ok, intersection with segment*/
						SECT_M_ForEachCharListInSector(hSector,hCharacterList,j)
						{
							/* scan every character of the collision sector*/
							hCurrentPerso = SECT_GetCharacterInList(hCharacterList);
							if ((fn_ulStandardGameGetCustomBitsSO(hCurrentPerso) & GAM_C_CustBitShadowOnMe) &&		/* accept shadow*/
								(fn_bf1StandardGameGetIsActive(M_GetMSHandle(hCurrentPerso,StandardGame)))) /* active*/
							{
								if( HIE_bIntersectSegmentWithFirstSuperObject(&stStartPicking,&stVertexAB,hCurrentPerso,&stPickedPoint,&stGlobalNormalOfPickedFace,&hTest) )
								{
									/* intersection found, check normal*/
									bFound |= MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace);
								}
							}
						}		
					}
				}
				/* and then in all collision sectors for decor*/
				/* test on a sector, so set global mask to check SPO shadow flag :*/
				g_ulSpoMask = HIE_C_Flag_ulNoShadowOnMe;
				SECT_M_ForEachCollisionNodeInCollisionInteractionList(_hSprObjSector,hCollisionElement,i)
				{	
					HIE_tdxHandleToSuperObject hSector;
					
					hSector = SECT_GetSectorInCollisionList(hCollisionElement);
					if (HIE_bIntersectSegmentWithFirstSuperObject(&stStartPicking,&stVertexAB,hSector,&stPickedPoint,&stGlobalNormalOfPickedFace,&hTest))
					{
						/* intersection found, check normal*/
						bFound |= MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace);
					}
				}
			}
/*		}*/
		
		if (bFound && MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace) )
		{
			/*Temporary point of shadow*/
			MTH3D_tdstVector		stPointOfShadowRectangle;
			/*Vectors used for the orientation of the shadow*/
			MTH3D_tdstVector		stCharacterRotation;
			/*Vectors used to compute picked point * 2*/
			MTH3D_tdstVector		stDblPicked;
#ifndef U64
			/*UV of the points of the shadow*/
			ACP_tdst2DUVValues		stUV; 
			/*Reals used to simplify the calcul of coordinates*/
			MTH_tdxReal				xAX,xAY,xBX; 
#endif
			MTH_tdxReal				xBY;
			/*Real to simplify the next calcul*/
			MTH_tdxReal xInvGlobalNormalxZ=MTH_M_xInv(stGlobalNormalOfPickedFace.xZ);
			
			POS_fn_vGetRotationMatrix(hGlobalMatrixOfCharacter ,&stCharacterRotation,&stPointOfShadowRectangle,&stPointOfShadowRectangle) ;
#ifndef U64
			/*Important: Rotation doesn't have to take in account the Z coef*/
			stCharacterRotation.xZ=MTH_C_ZERO;
			/*If the orientation is only in Z*/
			if ((MTH_M_bLess(MTH_M_xAbs(stCharacterRotation.xX),MTH_M_xFloatToReal(0.1f)))&&
				(MTH_M_bLess(MTH_M_xAbs(stCharacterRotation.xY),MTH_M_xFloatToReal(0.1f))))
			{
				stCharacterRotation.xX=MTH_C_InvSqrt2;
				stCharacterRotation.xY=MTH_C_InvSqrt2;
			}
			MTH3D_M_vNormalizeVector(&stCharacterRotation,&stCharacterRotation);
			/*Formula for scale*/
			xCoefAltitude=MTH_M_xInv(MTH_M_xAdd(MTH_C_ONE,MTH_M_xMul(MTH_M_xFloatToReal(0.3f),MTH_M_xSub(stStartPicking.xZ,stPickedPoint.xZ))));
			
			xScaleX=MTH_M_xMul(xScaleX,xCoefAltitude);
			xScaleY=MTH_M_xMul(xScaleY,xCoefAltitude);
			
			xAX = MTH_M_xMul(xScaleX,stCharacterRotation.xX);
			xAY = MTH_M_xMul(xScaleY,stCharacterRotation.xX);
			xBX = MTH_M_xMul(xScaleX,stCharacterRotation.xY);
			xBY = MTH_M_xMul(xScaleY,stCharacterRotation.xY);
		
			if ( ( (g_cSinusEffectState == 1) && ((HIE_fn_lGetSuperObjectDrawMask(hTest) & GLI_C_lHasNotSinusEffect) == 0) ) || 
				( (g_cSinusEffectState == 2) && (HIE_fn_lGetSuperObjectDrawMask(hTest) & GLI_C_lHasNotSinusEffect) ) ||  
				(g_cSinusEffectState == 3)
				) 
			{
				/* sinus effect --> set shadow at the top of sinus*/
				stPickedPoint.xZ = MTH_M_xAdd(stPickedPoint.xZ,MTH_M_xFloatToReal(stSinEffectAmp.xY));
				/* if shadow higher than rayman, set shadow under rayman*/
				/* 0.3 is distance between rayman and shadow when raymn walks*/
				if (MTH_M_bLess(MTH_M_xSub(stStartPicking.xZ,stPickedPoint.xZ),MTH_M_xFloatToReal(0.3)))
				{
					stPickedPoint.xZ = MTH_M_xSub(stStartPicking.xZ,MTH_M_xFloatToReal(0.3f));
				}
	
			}
			stPickedPoint.xZ = MTH_M_xAdd(stPickedPoint.xZ,MTH_M_xFloatToReal(0.03f));
 
			/*First Point*/
			stPointOfShadowRectangle.xX = MTH_M_xAdd(stPickedPoint.xX,MTH_M_xSub(xAX,xBY));
			stPointOfShadowRectangle.xY = MTH_M_xAdd(stPickedPoint.xY,MTH_M_xAdd(xBX,xAY));
			stPointOfShadowRectangle.xZ = SHW_fn_vComputeZofShadowPoint(&stPickedPoint,&stGlobalNormalOfPickedFace,xInvGlobalNormalxZ,stPointOfShadowRectangle.xX,stPointOfShadowRectangle.xY);
#else /* U64 */

			if (xScaleY>xScaleX) xScaleX=xScaleY;
			/* Since Shadows are always round */
			/*Formula for scale*/
			xCoefAltitude=MTH_M_xInv(MTH_M_xAdd(MTH_C_ONE,MTH_M_xMul(MTH_M_xFloatToReal(0.3f),MTH_M_xSub(stStartPicking.xZ,stPickedPoint.xZ))));
			
			xScaleX=MTH_M_xMul(xScaleX,xCoefAltitude);

			/*xAX */ xBY = xScaleX*(MTH_C_InvSqrt2*2.0f);
			/* xBY = xAX+xAX; */
			
			stPickedPoint.xZ = MTH_M_xAdd(stPickedPoint.xZ,MTH_M_xFloatToReal(0.03f));

			/*First Point*/
			stPointOfShadowRectangle.xX = stPickedPoint.xX;
			stPointOfShadowRectangle.xY = MTH_M_xAdd(stPickedPoint.xY,xBY);
			stPointOfShadowRectangle.xZ = SHW_fn_vComputeZofShadowPoint(&stPickedPoint,&stGlobalNormalOfPickedFace,xInvGlobalNormalxZ,stPointOfShadowRectangle.xX,stPointOfShadowRectangle.xY);

#endif /* U64 */


/*
	Now we automatically create the N64 Geometric object so that we don't have to 
	convert it in N64 format anymore =o)
*/
#ifndef U64 /* 
				PC VERSION : 
				Please inform Francois Queinnec when modifying this part of code !
			*/

			GEO_vSetPointOfObject(hHandleOfGeometricShadowObject,&stPointOfShadowRectangle,0);
			stUV.xU=MTH_C_ZERO;
			stUV.xV=MTH_C_ZERO;
			GEO_vSetUVOfIndexedTriangles(hHandleOfGeometricShadowObject,0,0,&stUV);
			/*End of First Point*/
			
			MTH3D_M_vMulScalarVector(&stDblPicked,MTH_M_xFloatToReal(2.0f),&stPickedPoint);
			
			/*Third Point*/
			stPointOfShadowRectangle.xX = MTH_M_xSub(stDblPicked.xX,stPointOfShadowRectangle.xX);
			stPointOfShadowRectangle.xY = MTH_M_xSub(stDblPicked.xY,stPointOfShadowRectangle.xY);
			stPointOfShadowRectangle.xZ = MTH_M_xSub(stDblPicked.xZ,stPointOfShadowRectangle.xZ);
			
			GEO_vSetPointOfObject(hHandleOfGeometricShadowObject,&stPointOfShadowRectangle,2);
			stUV.xU=MTH_C_ONE;
			stUV.xV=MTH_C_ONE;
			GEO_vSetUVOfIndexedTriangles(hHandleOfGeometricShadowObject,0,2,&stUV);
			/*End of Third Point*/
			
			/*Second Point*/
			stPointOfShadowRectangle.xX = MTH_M_xAdd(stPickedPoint.xX,MTH_M_xAdd(xAX,xBY));
			stPointOfShadowRectangle.xY = MTH_M_xAdd(stPickedPoint.xY,MTH_M_xSub(xBX,xAY));
			stPointOfShadowRectangle.xZ = SHW_fn_vComputeZofShadowPoint(&stPickedPoint,&stGlobalNormalOfPickedFace,xInvGlobalNormalxZ,stPointOfShadowRectangle.xX,stPointOfShadowRectangle.xY);
			
			GEO_vSetPointOfObject(hHandleOfGeometricShadowObject,&stPointOfShadowRectangle,1);
			stUV.xU=MTH_C_ONE;
			stUV.xV=MTH_C_ZERO;
			GEO_vSetUVOfIndexedTriangles(hHandleOfGeometricShadowObject,0,1,&stUV);
			/*End of Second Point*/
			
			
			/*Fourth Point*/
			stPointOfShadowRectangle.xX = MTH_M_xSub(stDblPicked.xX,stPointOfShadowRectangle.xX);
			stPointOfShadowRectangle.xY = MTH_M_xSub(stDblPicked.xY,stPointOfShadowRectangle.xY);
			stPointOfShadowRectangle.xZ = MTH_M_xSub(stDblPicked.xZ,stPointOfShadowRectangle.xZ);
			
			GEO_vSetPointOfObject(hHandleOfGeometricShadowObject,&stPointOfShadowRectangle,3);
			stUV.xU=MTH_C_ZERO;
			stUV.xV=MTH_C_ONE;
			GEO_vSetUVOfIndexedTriangles(hHandleOfGeometricShadowObject,0,3,&stUV);
			/*End of Fourth Point*/
			
			/*I create my two faces of my shadow*/
			GEO_vSetFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,0,0,3,1);
			GEO_vSetIndexedUVOfFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,0,0,3,1);
			GEO_vSetFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,1,1,3,2);
			GEO_vSetIndexedUVOfFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,1,1,3,2);
			hHandleOfGeometricShadowObject->xNbPoints=4;
			p_stIndexedTriangle = (GEO_tdstElementIndexedTriangles *)hHandleOfGeometricShadowObject->d_stListOfElements[0];
			p_stIndexedTriangle->xNbFaces=2;

			SHW_fn_vSentToViewPort(_p_stVpt,_hHandleOfCharacter,_hSprObjSector,_lSectorDrawmask,hHandleOfGeometricShadowObject);
			
#else /* U64 Version : */

			{
				GEO_tdstElementU64IndexedTriangles *pElem;
				Vtx *pVtxList;
				Gfx *pGfx;

				/* First, we create, if necessary, the geometric object */

				if (g_hShadowObjectN64[g_xIndexOfShadow]==NULL) 
				{
					GEO_vCreateGeometricObject(&g_hShadowObjectN64[g_xIndexOfShadow],0,1);
					SHW_fn_vCreateElementU64IndexedTriangles(g_hShadowObjectN64[g_xIndexOfShadow],0);
					((GEO_tdstElementU64IndexedTriangles *)(g_hShadowObjectN64[g_xIndexOfShadow]->d_stListOfElements[0]))->hMaterial=(GMT_tdxHandleToGameMaterial)g_hShadowPolygonVisualMaterial;
					(g_hShadowObjectN64[g_xIndexOfShadow])->fScale=SHW_C_xU64ScaleForGeometricShadow;
					g_hShadowObjectN64[g_xIndexOfShadow]->uwSymType=0xFFFF;
					g_hShadowObjectN64[g_xIndexOfShadow]->uwRliFlag=0;
					g_hShadowObjectN64[g_xIndexOfShadow]->xNbPoints=4;
					pElem=((GEO_tdstElementU64IndexedTriangles **)(g_hShadowObjectN64[g_xIndexOfShadow]->d_stListOfElements))[0];
#if defined(_U64_GLI_BENCH_)
					pElem->uwNbFaces=2;
					pElem->uwSizeOfFacesInBytes=6;
#endif
					pElem->ulNbVertices=2;
					pElem->p_stVtxList=g_p_stVtxListForShadow[g_xIndexOfShadow];
					pElem->p_stGfxList=g_p_stGfxListForShadow[g_xIndexOfShadow];

				}
				
				pElem=((GEO_tdstElementU64IndexedTriangles **)(g_hShadowObjectN64[g_xIndexOfShadow]->d_stListOfElements))[0];
				pVtxList=g_p_stVtxListForShadow[g_xIndexOfShadow];
				pGfx=g_p_stGfxListForShadow[g_xIndexOfShadow];

				/* First Point */
				pVtxList->v.ob[0]=(short)((stPointOfShadowRectangle.xX-stPickedPoint.xX)*SHW_C_xU64ScaleForGeometricShadow);
				pVtxList->v.ob[1]=(short)((stPointOfShadowRectangle.xY-stPickedPoint.xY)*SHW_C_xU64ScaleForGeometricShadow);
				pVtxList->v.ob[2]=(short)((stPointOfShadowRectangle.xZ-stPickedPoint.xZ+SHW_C_ZBiasForZBuffer)*SHW_C_xU64ScaleForGeometricShadow);
				/*End of First Point*/
				
				/*Third Point*/

				MTH3D_M_vMulScalarVector(&stDblPicked,MTH_M_xFloatToReal(2.0f),&stPickedPoint);
				stPointOfShadowRectangle.xX = MTH_M_xSub(stDblPicked.xX,stPointOfShadowRectangle.xX);
				stPointOfShadowRectangle.xY = MTH_M_xSub(stDblPicked.xY,stPointOfShadowRectangle.xY);
				stPointOfShadowRectangle.xZ = MTH_M_xSub(stDblPicked.xZ,stPointOfShadowRectangle.xZ);
				
				pVtxList+=2;
				pVtxList->v.ob[0]=(short)((stPointOfShadowRectangle.xX-stPickedPoint.xX)*SHW_C_xU64ScaleForGeometricShadow);
				pVtxList->v.ob[1]=(short)((stPointOfShadowRectangle.xY-stPickedPoint.xY)*SHW_C_xU64ScaleForGeometricShadow);
				pVtxList->v.ob[2]=(short)((stPointOfShadowRectangle.xZ-stPickedPoint.xZ+SHW_C_ZBiasForZBuffer)*SHW_C_xU64ScaleForGeometricShadow);

				/*End of Third Point*/

				/*Second Point*/
				stPointOfShadowRectangle.xX = MTH_M_xAdd(stPickedPoint.xX,xBY);
				stPointOfShadowRectangle.xY = stPickedPoint.xY;
				stPointOfShadowRectangle.xZ = SHW_fn_vComputeZofShadowPoint(&stPickedPoint,&stGlobalNormalOfPickedFace,xInvGlobalNormalxZ,stPointOfShadowRectangle.xX,stPointOfShadowRectangle.xY);				

				pVtxList--;
				pVtxList->v.ob[0]=(short)((stPointOfShadowRectangle.xX-stPickedPoint.xX)*SHW_C_xU64ScaleForGeometricShadow);
				pVtxList->v.ob[1]=(short)((stPointOfShadowRectangle.xY-stPickedPoint.xY)*SHW_C_xU64ScaleForGeometricShadow);
				pVtxList->v.ob[2]=(short)((stPointOfShadowRectangle.xZ-stPickedPoint.xZ+SHW_C_ZBiasForZBuffer)*SHW_C_xU64ScaleForGeometricShadow);
				/*End of Second Point*/				
			
				/*Fourth Point*/
				stPointOfShadowRectangle.xX = MTH_M_xSub(stDblPicked.xX,stPointOfShadowRectangle.xX);
				stPointOfShadowRectangle.xY = MTH_M_xSub(stDblPicked.xY,stPointOfShadowRectangle.xY);
				stPointOfShadowRectangle.xZ = MTH_M_xSub(stDblPicked.xZ,stPointOfShadowRectangle.xZ);

				pVtxList+=2;
				pVtxList->v.ob[0]=(short)((stPointOfShadowRectangle.xX-stPickedPoint.xX)*SHW_C_xU64ScaleForGeometricShadow);
				pVtxList->v.ob[1]=(short)((stPointOfShadowRectangle.xY-stPickedPoint.xY)*SHW_C_xU64ScaleForGeometricShadow);
				pVtxList->v.ob[2]=(short)((stPointOfShadowRectangle.xZ-stPickedPoint.xZ+SHW_C_ZBiasForZBuffer)*SHW_C_xU64ScaleForGeometricShadow);

			g_pstPickedPointArray[g_xIndexOfShadow].xX=stPickedPoint.xX;
			g_pstPickedPointArray[g_xIndexOfShadow].xY=stPickedPoint.xY;
			g_pstPickedPointArray[g_xIndexOfShadow].xZ=stPickedPoint.xZ;

				g_uwGlobalAlpha=255;

				SHW_fn_vSentToViewPort(_p_stVpt,_hHandleOfCharacter,_hSprObjSector,_lSectorDrawmask,g_hShadowObjectN64[g_xIndexOfShadow]);
				
			}

#endif /* U64*/
			
			
		
			g_xIndexOfShadow++;
		}
	}
}
 
 
