/* ##TYPEDEF#----------------------------------------------------------------------------
Types definition
---------------------------------------------------------------------------------------*/
/*This is a structure used by my clipping function of triangles to create shadow faces*/
typedef struct SHW_tdstResultIntersectionCT_
{
	ACP_tdst2DUVValues uvPoint;
	short xStart1;
	short xStart2;
	
	ACP_tdxBool xCT1;
	ACP_tdxBool  xCT2;
} SHW_tdstResultIntersectionCT;
 
 
#define C_ShadowOnActors	256
#define	C_ShadowOnMe		512
/* ##-############################################ */
/* ##SECTION FROM SPO: Used for bounding volumes
/* ############################################### */
MTH_tdxReal             VoidReal;
ACP_tdxHandleOfObject   GeoHandle;
 
 
/* ##M===================================================================================
NAME :          SHW_M_hGetFirstLodOfVisualSetFromPo
DESCRIPTION :   return first level of detail of visual set of a physical object
INPUT :         Physical object
OUTPUT :        first level of detail of visual set of a physical object
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
#define SHW_M_hGetFirstLodOfVisualSetFromPo(Po)  \
(GLI_vGetVisualSetLOD(PO_fn_hGetVisualSet(Po), 0, &VoidReal, &GeoHandle), GeoHandle)
 
/* ##M===================================================================================
NAME :          SHW_M_hGetRepositionZoneFromPo
DESCRIPTION :   return reposition zone of a physical object
INPUT :         Physical object
OUTPUT :        reposition zone of a physical object
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
#define SHW_M_hGetRepositionZoneFromPo(Po)  \
(GLI_vGetVisualSetLOD(PO_fn_hGetVisualSet(Po), 0, &VoidReal, &GeoHandle), GeoHandle)
/* ##-############################################ */
/* ##END SECTION FROM SPO
/* ############################################### */
 
 
/* ##GLOBVAR#----------------------------------------------------------------------------
Globale variable declaration
---------------------------------------------------------------------------------------*/
 
GLI_tdstTexture             *g_p_stTextureOfTextureShadow;
 
/*Index of the shadow of character*/
/*Global variable for the quality of shadow*/
short                       g_xGeneralLevelOfQualityOfShadows=2;
short                       g_xLevelOfQualityOfShadows=2;
/*Global array of information about the intersected faces*/
SHW_tdstShadowInfo          g_a_stShadowInfo[SHW_C_xMaxGeomObjectPicked];
/*Array of Handles of characters that have shadow already calculated: Exemple into mirrors*/
HIE_tdxHandleToSuperObject	g_hHandleOfFather= NULL;
/*ACP_tdxBool					g_bOnPlatForm = FALSE;*/
ACP_tdxBool					g_bIsOnGround = FALSE;
 
ACP_tdxBool					g_bRayIsVertical;
 
MTH3D_tdstVector			g_stStartPicking;
MTH3D_tdstVector			g_stDirOfShadow;
 
/* YLG*/
/*MTH3D_tdstVector           g_stVertexA,*/
MTH3D_tdstVector			g_stVertexB;
MTH3D_tdstVector			g_stVertexAB;
MTH_tdxReal					g_xNearDistance;
MTH3D_tdstVector			g_stPickedPoint;
HIE_tdxHandleToSuperObject	g_hPickedSprObj;
ACP_tdxHandleOfObject		g_hPickedObject;
ACP_tdxIndex				g_xPickedElement;
ACP_tdxIndex				g_xPickedFace;
short						g_shNbObjPicked;
POS_tdstCompletePosition	g_stInvertCurrentMatrix;
/*MTH3D_tdstVector			g_stVertexALocal;*/
/*MTH3D_tdstVector			g_stVertexBLocal;*/
/*MTH3D_tdstVector			g_stVertexABLocal;*/
ACP_tdxBool					g_bFirstFace;
 
 
 
/* ##FUNCDEF#----------------------------------------------------------------------------
Functions definition
---------------------------------------------------------------------------------------*/
/* ##F===================================================================================
NAME :          SHW_fn_bIsCharacterBoundingVolumeIntersectwithSphere
DESCRIPTION :   return TRUE if bounding volumes intersect with sphere
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
ACP_tdxBool SHW_fn_bIsCharacterBoundingVolumeIntersectWithSphere
(
	 HIE_tdxHandleToSuperObject _hSprObj
)
{
    GEO_tdxHandleToParallelBox		hParallelBox = NULL;
	GEO_tdxHandleToBoundingSphere	hBoundingSphere = NULL;
	ACP_tdxBool						bBoundingBox;
	MTH3D_tdstVector				stGlobalSphereCenter, stLocalSphereCenter;
	/* FQ: I had to init those 2 variables, or else it hung on some special cases...*/
	/* Like Swamp2's moveable bridge int the N64 Version !*/
	MTH_tdxReal						xSphereRadius=0.0f,  xScaledRadius=0.0f;
	MTH3D_tdstVector				stMinPoint;
	MTH3D_tdstVector				stMaxPoint;
	
	if (HIE_fn_SO_bCheckChildren(_hSprObj))
		return TRUE;
 
	bBoundingBox = HIE_fn_SO_bHasABoxBoundingVolume(_hSprObj);
	 if(bBoundingBox)
		 hParallelBox = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
	 else
		hBoundingSphere = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
	 if ((hBoundingSphere) && (!bBoundingBox))
	 {
		/*PRF_fn_vIncreaseVariable(PRF_C_ulVarGLI1, NULL, 1);*/
		MTH3D_M_vCopyVector(&stLocalSphereCenter, GEO_fn_pGetCenterPointOfBoundingSphere(hBoundingSphere));
		xSphereRadius = GEO_fn_xGetRadiusOfBoundingSphere(hBoundingSphere);
		POS_fn_vMulMatrixVertex(&stGlobalSphereCenter, HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj), &stLocalSphereCenter);
		xScaledRadius = xSphereRadius * POS_fn_xGetMaxScale(HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj));
	 }
	 else if ((bBoundingBox) && (hParallelBox))
	 {
		 MTH3D_tdstVector	*p_stMinPoint;
		 MTH3D_tdstVector	*p_stMaxPoint;
		 MTH3D_tdstVector	stTranslation;
		 
		 /*PRF_fn_vIncreaseVariable(PRF_C_ulVarGLI1, NULL, 1);*/
		 p_stMinPoint = GEO_fn_pGetMinPointOfParallelBox(hParallelBox);
		 p_stMaxPoint = GEO_fn_pGetMaxPointOfParallelBox(hParallelBox);
		 stTranslation = (HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj))->stTranslationVector;
		 
		 MTH3D_M_vAddVector(&stMinPoint, p_stMinPoint , &stTranslation);
		 MTH3D_M_vAddVector(&stMaxPoint, p_stMaxPoint , &stTranslation);					 
	 }
 
	 /*Fast intersection test with the bounding volumes */
	 if(((!hBoundingSphere) && (!hParallelBox))|| 
	   (!bBoundingBox && INT_fn_bIntersectSphereWithSphere(&g_stPickedPoint,g_xNearDistance,&stGlobalSphereCenter,xScaledRadius)) ||
	   (bBoundingBox && INT_fn_bIntersectSphereWithBox(&g_stPickedPoint, g_xNearDistance, &stMinPoint,&stMaxPoint)))
	   return TRUE;
 
	 return FALSE;
}
 
/* ##F===================================================================================
NAME :          SHW_fn_bFirstIntersectShadowSuperObject
DESCRIPTION :   Find the face intersected by a semi-axe
Recursive function to find the highest face on several SpObj
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
ACP_tdxBool SHW_fn_bFirstIntersectShadowSuperObject
(
	HIE_tdxHandleToSuperObject _hSprObj,
	ACP_tdxIndex               *p_xIntersTest,
	HIE_tdxHandleToSuperObject hHandleOfCharacter
	)											
{
	GEO_tdxHandleToBoundingSphere	hBoundingSphere = NULL;
	GEO_tdxHandleToParallelBox		hParallelBox = NULL;
	ACP_tdxHandleOfObject			hSentObject=NULL;
	ACP_tdxIndex					i;
	long							lTempSuperObjectType;
	HIE_tdxHandleToSuperObject		_hChild;
	MTH3D_tdstVector				stHitPoint;
	ACP_tdxIndex					xElement;
	ACP_tdxIndex					xDataElement;
	ACP_tdxBool						bBoundingBox;
	MTH3D_tdstVector				stMinPoint;
	MTH3D_tdstVector				stMaxPoint;
	MTH3D_tdstVector				stVertexALocal;
	MTH3D_tdstVector				stVertexBLocal;
	MTH3D_tdstVector				stVertexABLocal;
	
	if ( HIE_fn_SO_bIsNotPickable( _hSprObj ))
		return ((*p_xIntersTest)!=0);
 
	lTempSuperObjectType=HIE_fn_ulGetSuperObjectType(_hSprObj);
	
	if (*p_xIntersTest<SHW_C_xDepthPickingObjectsForShadow)
	{
		HIE_fn_vPushMatrix (_hSprObj);
		bBoundingBox = HIE_fn_SO_bHasABoxBoundingVolume(_hSprObj);
		if(bBoundingBox)
			/* If the bounding volume of the super object is a Box ...*/
			hParallelBox = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
		else
			hBoundingSphere = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
		
		if ((bBoundingBox) && (hParallelBox))
		{
			MTH3D_tdstVector	*p_stMinPoint;
			MTH3D_tdstVector	*p_stMaxPoint;
			MTH3D_tdstVector	stTranslation;
 
			p_stMinPoint = GEO_fn_pGetMinPointOfParallelBox(hParallelBox);
			p_stMaxPoint = GEO_fn_pGetMaxPointOfParallelBox(hParallelBox);
			stTranslation = (HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj))->stTranslationVector;
 
			MTH3D_M_vAddVector(&stMinPoint, p_stMinPoint , &stTranslation);
			MTH3D_M_vAddVector(&stMaxPoint, p_stMaxPoint , &stTranslation);
		}
		
		/*Quick Test of intersection with the bounding volume*/
		if(((!hBoundingSphere) && (!hParallelBox))|| 
			(HIE_fn_SO_bCheckChildren(_hSprObj)) ||
			((!bBoundingBox) && fn_bDetectIntersectSegmentWithBoundingSphere(HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj), &g_stStartPicking,&g_stVertexAB, hBoundingSphere) ) ||
			((bBoundingBox) && INT_fn_bDetectIntersectSegmentWithBox(&g_stStartPicking,&g_stVertexAB, &stMinPoint ,&stMaxPoint,NULL)))
		{
			ACP_tdxBool					bContinue;
 
			bContinue= TRUE;
			
			/*Several functions to get the geometric linked object*/
			if(lTempSuperObjectType == HIE_C_ulPO)
				hSentObject=SHW_M_hGetRepositionZoneFromPo((PO_tdxHandleToPhysicalObject)HIE_fn_hGetSuperObjectObject(_hSprObj));
			else if (lTempSuperObjectType == HIE_C_ulEDT_Geometric) 
				hSentObject=(ACP_tdxHandleOfObject)HIE_fn_hGetSuperObjectObject(_hSprObj);
#ifndef D_THROW_IPO
			else if(lTempSuperObjectType & (HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
				hSentObject=SHW_M_hGetRepositionZoneFromPo(IPO_fn_hGetPhysicalObject((IPO_tdxHandleToInstanciatedPhysicalObject)HIE_fn_hGetSuperObjectObject(_hSprObj)));
#endif /* D_THROW_IPO */
			else bContinue = FALSE;
 
			if (bContinue)
			{
				POS_fn_vInvertMatrix(&g_stInvertCurrentMatrix, g_p_stCurrentMatrix);
				POS_fn_vMulMatrixVertex(&stVertexALocal, &g_stInvertCurrentMatrix, &g_stStartPicking);
				POS_fn_vMulMatrixVertex(&stVertexBLocal, &g_stInvertCurrentMatrix, &g_stVertexB);
				MTH3D_M_vSubVector(&stVertexABLocal, &stVertexBLocal, &stVertexALocal);
 
				/* Slow Intersection Test with the geometric object*/
				if (INT_fn_bIntersectSegmentWithShadowFaceOfGeometricObject
					(
						&stVertexALocal,
						&stVertexBLocal,
						&stVertexABLocal,
						hSentObject,
						&stHitPoint,
						&xElement,
						&xDataElement
						)
					)
				{
					MTH3D_tdstVector stMulMatrixTempVector;
 
					POS_fn_vMulMatrixVertex(&stMulMatrixTempVector,g_p_stCurrentMatrix,&stHitPoint);
					/*If I've found an upper face*/
					if (MTH_M_bGreater(stMulMatrixTempVector.xZ , g_stPickedPoint.xZ))
					{
						(*p_xIntersTest)++;
						MTH3D_M_vCopyVector(&g_stPickedPoint,&stMulMatrixTempVector);
						g_xPickedElement=xElement;
						g_xPickedFace=xDataElement;
						g_hPickedSprObj=_hSprObj;
						g_hPickedObject=hSentObject;
					}
				}
				if (*p_xIntersTest<SHW_C_xDepthPickingObjectsForShadow)
					HIE_M_ForEachChildOf(_hSprObj, _hChild, i)
					{
							SHW_fn_bFirstIntersectShadowSuperObject
							(
								_hChild,
								p_xIntersTest,
								hHandleOfCharacter
							);
					}
 
			}
			else
			{
				HIE_M_ForEachChildOf(_hSprObj, _hChild, i)
				{
					if(_hChild!=hHandleOfCharacter) 
					{
						/* recurence*/
						SHW_fn_bFirstIntersectShadowSuperObject
						(
							_hChild,
							p_xIntersTest,
							hHandleOfCharacter
						);
					}
				}
			}
 
		}
	HIE_fn_vPopMatrix ();
	}
	return ((*p_xIntersTest)!=0);
}/*SHW_fn_bFirstIntersectShadowSuperObject*/
 
 /* ##F===================================================================================
 NAME :          SHW_fn_bFirstIntersectShadowSuperObjectAndCharacters
 DESCRIPTION :   Find the face intersected by a semi-axe on the sectors and the characters
 Recursive function to find the highest face on several SpObj
 =========================================================================================
 CREATION : Philippe Thiébaut
 =======================================================================================*/
ACP_tdxBool SHW_fn_bFirstIntersectShadowSuperObjectAndCharacters(
	 HIE_tdxHandleToSuperObject _hSprObj,
	 ACP_tdxIndex               *p_xIntersTest,
	 HIE_tdxHandleToSuperObject hHandleOfCharacter)
 {
	 
	 ACP_tdxIndex							i;
	 short									shTempResult=0;
	 ACP_tdxIndex							xIntersTest=0;
	 SECT_tdxHandleOfElementLstCharacter	hCharacterElement;
	 HIE_tdxHandleToSuperObject				hChild;
	 
#ifndef SHW_FORCE_SHADOW
	if (fn_ulStandardGameGetCustomBitsSO(hHandleOfCharacter)&GAM_C_CustBitActorHasShadow)
#endif
	{
		if (g_hHandleOfFather)
		{
#ifndef SHW_FORCE_SHADOW
			if (fn_ulStandardGameGetCustomBitsSO(g_hHandleOfFather)&C_ShadowOnMe)
#endif
				shTempResult+=SHW_fn_bFirstIntersectShadowSuperObject(
				g_hHandleOfFather,
				&xIntersTest,
				hHandleOfCharacter);
		}
		else
		{
			if (!g_bIsOnGround)
			{
				/* Note: _hSprObj must be the current sector of the character*/
				/* First: Test the list of characters of _hSprObj*/
				SECT_M_ForEachCharListInSector(_hSprObj,hCharacterElement,i)
				{
					hChild = SECT_GetCharacterInList(hCharacterElement); 
					if ((hChild != hHandleOfCharacter)
#ifndef SHW_FORCE_SHADOW
						&&(fn_ulStandardGameGetCustomBitsSO(hChild)&C_ShadowOnMe)) 
#else
						)
#endif
						shTempResult+=SHW_fn_bFirstIntersectShadowSuperObject
						(
						hChild,
						&xIntersTest,
						hHandleOfCharacter
						);
				}
			}
			
		}
	 }
	 if(g_hHandleOfFather == NULL)
	 {
		 shTempResult+=SHW_fn_bFirstIntersectShadowSuperObject(
			 _hSprObj,
			 &xIntersTest,
			 hHandleOfCharacter);
 
	 }
	 
	 
	 return (shTempResult!=0); 
	 
 }/*SHW_fn_bFirstIntersectShadowSuperObjectAndCharacters*/
 
 
  /* ##F===================================================================================
  NAME :          SHW_fn_bSecondIntersectShadowSuperObject
  DESCRIPTION :   Find the face intersected by a sphere
  Recursive function to find the faces in all SpObj
  =========================================================================================
  CREATION : Philippe Thiébaut
 =======================================================================================*/
 ACP_tdxBool SHW_fn_bSecondIntersectShadowSuperObject(
	 HIE_tdxHandleToSuperObject _hSprObj,
	 HIE_tdxHandleToSuperObject hHandleOfCharacter
 )
 {
	 ACP_tdxIndex					i;
	 unsigned long					lTempSuperObjectType;
	 HIE_tdxHandleToSuperObject		_hChild;
	 ACP_tdxHandleOfObject			hSentObject=NULL;
	 GEO_tdxHandleToParallelBox		hParallelBox = NULL;
	 GEO_tdxHandleToBoundingSphere	hBoundingSphere = NULL;
	 ACP_tdxBool					bBoundingBox;
	 MTH3D_tdstVector				stGlobalSphereCenter, stLocalSphereCenter;
	 MTH_tdxReal					xSphereRadius,  xScaledRadius;
 	 SHW_tdstShadowInfo			 *	p_stShadowInfo;
	 COL_tdstShadowElement       *	p_stShadowObject;
	 MTH3D_tdstVector				stMinPoint;
	 MTH3D_tdstVector				stMaxPoint;
	 ACP_tdxBool					bBadMaterial;
 
	 if(((_hSprObj!=g_hPickedSprObj)||(g_bFirstFace))&&(_hSprObj!=hHandleOfCharacter))
	 {
		 
		 HIE_fn_vPushMatrix (_hSprObj);
		 lTempSuperObjectType = HIE_fn_ulGetSuperObjectType(_hSprObj);
		 if (g_shNbObjPicked<SHW_C_xMaxGeomObjectPicked)
		 {
			 if ( HIE_fn_SO_bIsNotPickable( _hSprObj ) )
				 lTempSuperObjectType = HIE_C_ulNoAction;
			 
			 /*All the types of objects that I project my shadow on	 */
			 if( lTempSuperObjectType & (HIE_C_ulPO | HIE_C_ulEDT_Geometric | HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
			 {
				 bBoundingBox = HIE_fn_SO_bHasABoxBoundingVolume(_hSprObj);
 
				 if(bBoundingBox)
					 hParallelBox = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
				 else
					hBoundingSphere = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
				 if ((hBoundingSphere) && (!bBoundingBox))
				 {
					 MTH3D_M_vCopyVector(&stLocalSphereCenter, GEO_fn_pGetCenterPointOfBoundingSphere(hBoundingSphere));
					 xSphereRadius = GEO_fn_xGetRadiusOfBoundingSphere(hBoundingSphere);
					 POS_fn_vMulMatrixVertex(&stGlobalSphereCenter, HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj), &stLocalSphereCenter);
					 xScaledRadius = xSphereRadius * POS_fn_xGetMaxScale(HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj));
				 }
 
				 if ((bBoundingBox) && (hParallelBox))
				 {
					 MTH3D_tdstVector	*p_stMinPoint;
					 MTH3D_tdstVector	*p_stMaxPoint;
					 MTH3D_tdstVector	stTranslation;
					 
					 p_stMinPoint = GEO_fn_pGetMinPointOfParallelBox(hParallelBox);
					 p_stMaxPoint = GEO_fn_pGetMaxPointOfParallelBox(hParallelBox);
					 stTranslation = (HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj))->stTranslationVector;
					 
					 MTH3D_M_vAddVector(&stMinPoint, p_stMinPoint , &stTranslation);
					 MTH3D_M_vAddVector(&stMaxPoint, p_stMaxPoint , &stTranslation);					 
				 }
 
				 /*Fast intersection test with the bounding volumes */
				 if(((!hBoundingSphere) && (!hParallelBox))|| 
					 (HIE_fn_SO_bCheckChildren(_hSprObj))||
				   (!bBoundingBox && INT_fn_bIntersectSphereWithSphere(&g_stPickedPoint,g_xNearDistance,&stGlobalSphereCenter,xScaledRadius)) ||
				   (bBoundingBox && INT_fn_bIntersectSphereWithBox(&g_stPickedPoint, g_xNearDistance, &stMinPoint,&stMaxPoint)))
				 {
					 MTH3D_tdstVector  p_stLocalCenter;
					 
					 if(lTempSuperObjectType == HIE_C_ulPO)
						 hSentObject=SHW_M_hGetRepositionZoneFromPo((PO_tdxHandleToPhysicalObject)HIE_fn_hGetSuperObjectObject(_hSprObj));
					 /*I get the linked geometric object */
					 else if(lTempSuperObjectType == HIE_C_ulEDT_Geometric)
						 hSentObject=(ACP_tdxHandleOfObject)HIE_fn_hGetSuperObjectObject(_hSprObj);
/*XB980821*/
#ifndef D_THROW_IPO
					 else if(lTempSuperObjectType & (HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
						 hSentObject = SHW_M_hGetRepositionZoneFromPo(IPO_fn_hGetPhysicalObject((IPO_tdxHandleToInstanciatedPhysicalObject)HIE_fn_hGetSuperObjectObject(_hSprObj)));
#endif /* D_THROW_IPO */
/*End XB				 */
					 /* conversion to local coordinate system */
					POS_fn_vInvertMatrix(&g_stInvertCurrentMatrix, g_p_stCurrentMatrix);
					 POS_fn_vMulMatrixVertex(&p_stLocalCenter, &g_stInvertCurrentMatrix, &g_stPickedPoint);
					 
					 /*Slow intersection test with the geometric object that gives to me an array of faces intersected*/
					 if (INT_fn_bIntersectSphereWithShadowFaceOfGeometricObject( 
							&p_stLocalCenter,
							g_xNearDistance,
							hSentObject,
							SHW_C_xMaxTriangles,
							&(g_a_stShadowInfo[g_shNbObjPicked].xNbElement),
							g_a_stShadowInfo[g_shNbObjPicked].a_stShadowObject,
							&bBadMaterial)
						)
					 {
						 /*If I am working on the first geometric object intersected by the semi-axe*/
						 if (g_bFirstFace)
						 {
							 long          xNbel;
							 short         xObjPicked;
							 ACP_tdxBool   xAddFace;
							 
							 xNbel=0;
							 xObjPicked=g_shNbObjPicked;
							 xAddFace=0;
							 /*I must add the first picked face to the array of face but without making it bouble*/
							 if (hSentObject==g_hPickedObject)
							 {
								 short			xNbElement;
								 ACP_tdxBool	bFlag = FALSE;
								 p_stShadowInfo = &g_a_stShadowInfo[xObjPicked];
								 p_stShadowObject = p_stShadowInfo->a_stShadowObject;
								 xNbElement = p_stShadowInfo->xNbElement;
 
								 if (xNbElement > SHW_C_xMaxTriangles)
								 {
									 xNbElement= SHW_C_xMaxTriangles;
									 bFlag = TRUE;
								 }
								 xNbel = 0;
 
								 while ((!xAddFace)&&(xNbel<xNbElement)/*&&(xNbel<SHW_C_xMaxTriangles)*/)
								 {
									 xAddFace+=(
												((p_stShadowObject->xElementIndex)==g_xPickedElement)&&
												((p_stShadowObject->xDataElementIndex)==g_xPickedFace)
											   );
									 p_stShadowObject ++;
									 xNbel++;
								 }
								 if (!xAddFace)
								 {
									 if (/*p_stShadowInfo->xNbElement<SHW_C_xMaxTriangles*/!bFlag)
									 {
										 p_stShadowObject = &(p_stShadowInfo->a_stShadowObject[xNbElement]);
										 p_stShadowObject->xElementIndex=g_xPickedElement;
										 p_stShadowObject->xDataElementIndex=g_xPickedFace;
										 p_stShadowInfo->xNbElement++;
									 }
									 else 
									 {
										 p_stShadowObject = &(p_stShadowInfo->a_stShadowObject[xNbElement-1]);
										 p_stShadowObject->xElementIndex=g_xPickedElement;
										 p_stShadowObject->xDataElementIndex=g_xPickedFace;
									 }
								 }
							 }					 
							 g_bFirstFace =FALSE;
						 }			 
						 p_stShadowInfo = &g_a_stShadowInfo[g_shNbObjPicked];
						 p_stShadowInfo->hPickedSpObj=_hSprObj;
						 p_stShadowInfo->hPickedObject=hSentObject;
						 g_shNbObjPicked++;					 
					 }
					 else
					 {
						 if ((g_bFirstFace)&&(hSentObject==g_hPickedObject))
						 {
							 if (!bBadMaterial)
							 {
								 p_stShadowInfo = &g_a_stShadowInfo[g_shNbObjPicked];
								 p_stShadowInfo->hPickedSpObj=_hSprObj;
								 p_stShadowInfo->hPickedObject=hSentObject;
 
								 p_stShadowObject = p_stShadowInfo->a_stShadowObject;
								 p_stShadowInfo->xNbElement=1;
								 p_stShadowObject->xElementIndex=g_xPickedElement;
								 p_stShadowObject->xDataElementIndex=g_xPickedFace;
								 g_shNbObjPicked++;
 
								 g_bFirstFace = FALSE;
							 }
						 }
					 }
					if (g_shNbObjPicked<SHW_C_xMaxGeomObjectPicked)
						  HIE_M_ForEachChildOf(_hSprObj, _hChild, i)
							{
	  						  SHW_fn_bSecondIntersectShadowSuperObject(
							  _hChild,
							  hHandleOfCharacter);
							}
				 }
			 }
			 else
			 {	
				  HIE_M_ForEachChildOf(_hSprObj, _hChild, i)
					{
	  						  SHW_fn_bSecondIntersectShadowSuperObject(
							  _hChild,
							  hHandleOfCharacter);
					}
			 }
  }
  HIE_fn_vPopMatrix();
 }
  
   return (g_shNbObjPicked !=0);
}/*SHW_fn_bSecondIntersectShadowSuperObject*/
 
 
 
/* ##F===================================================================================
NAME :          SHW_fn_bSecondIntersectShadowSuperObjectSpecificToCharacters
DESCRIPTION :   Find the face intersected by a sphere
Recursive function to find the faces in all SpObj
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
ACP_tdxBool SHW_fn_bSecondIntersectShadowSuperObjectSpecificToCharacters
(
	 HIE_tdxHandleToSuperObject _hSprObj,
	 HIE_tdxHandleToSuperObject hHandleOfCharacter
)
{
	ACP_tdxIndex					i;
	unsigned long					lTempSuperObjectType;
	HIE_tdxHandleToSuperObject		_hChild;
    ACP_tdxHandleOfObject			hSentObject=NULL;
	ACP_tdxBool						bBadMaterial;
	
	if ((_hSprObj!=hHandleOfCharacter)/*&&(_hSprObj!=g_hPickedSprObj)*/)
	{
		HIE_fn_vPushMatrix (_hSprObj);
		
		lTempSuperObjectType=HIE_fn_ulGetSuperObjectType(_hSprObj);	
		
		if (g_shNbObjPicked<SHW_C_xMaxGeomObjectPicked)
		{
			
			if ( HIE_fn_SO_bIsNotPickable( _hSprObj ) )
				lTempSuperObjectType = HIE_C_ulNoAction;
			
			/*All the types of objects that I project my shadow on		 */
			if(lTempSuperObjectType & (HIE_C_ulPO | HIE_C_ulEDT_Geometric | HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
			{
				/*PRF_fn_vIncreaseVariable(PRF_C_ulVarGLI2, NULL, 1);*/
				{
					MTH3D_tdstVector  p_stLocalCenter;
					/*I get the linked geometric object */
					if(lTempSuperObjectType==HIE_C_ulPO)
						hSentObject=SHW_M_hGetRepositionZoneFromPo((PO_tdxHandleToPhysicalObject)HIE_fn_hGetSuperObjectObject(_hSprObj));
					else if(lTempSuperObjectType==HIE_C_ulEDT_Geometric)
						hSentObject=(ACP_tdxHandleOfObject)HIE_fn_hGetSuperObjectObject(_hSprObj);
/*XB980821*/
#ifndef D_THROW_IPO
					else if(lTempSuperObjectType & (HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
						hSentObject=SHW_M_hGetRepositionZoneFromPo(IPO_fn_hGetPhysicalObject((IPO_tdxHandleToInstanciatedPhysicalObject)HIE_fn_hGetSuperObjectObject(_hSprObj)));
#endif /* D_THROW_IPO */
/*End XB*/
					/* conversion to local coordinate system*/
					POS_fn_vInvertMatrix(&g_stInvertCurrentMatrix, g_p_stCurrentMatrix);
					POS_fn_vMulMatrixVertex(&p_stLocalCenter, &g_stInvertCurrentMatrix, &g_stPickedPoint);
					/*Slow intersection test with the geometric object that gives to me an array of faces intersected*/
					/*PRF_fn_vStartChrono(PRF_C_ulGLI4, NULL);*/
					if (INT_fn_bIntersectSphereWithShadowFaceOfGeometricObject ( 
						&p_stLocalCenter,
						g_xNearDistance,
						hSentObject,
						SHW_C_xMaxTriangles,
						&(g_a_stShadowInfo[g_shNbObjPicked].xNbElement),
						g_a_stShadowInfo[g_shNbObjPicked].a_stShadowObject,
						&bBadMaterial))
					{
						if (!bBadMaterial)
						{
							g_a_stShadowInfo[g_shNbObjPicked].hPickedSpObj=_hSprObj;
							g_a_stShadowInfo[g_shNbObjPicked].hPickedObject=hSentObject;
							g_shNbObjPicked++;
						}
					}
					/*PRF_fn_vStopChrono(PRF_C_ulGLI4, NULL);*/
				  if (g_shNbObjPicked<SHW_C_xMaxGeomObjectPicked)
					HIE_M_ForEachChildOf(_hSprObj, _hChild, i)
					{
							SHW_fn_bSecondIntersectShadowSuperObjectSpecificToCharacters(
								_hChild,
								hHandleOfCharacter);
					}
				}
			}
			else
			{
				HIE_M_ForEachChildOf(_hSprObj, _hChild, i)
				{
						SHW_fn_bSecondIntersectShadowSuperObjectSpecificToCharacters(
							_hChild,
							hHandleOfCharacter);
				}
			}
		}
		HIE_fn_vPopMatrix();
	} 
	 return (g_shNbObjPicked!=0);
}/*SHW_fn_bSecondIntersectShadowSuperObject*/
	 
	 
	 
 
 
/* ##F===================================================================================
 NAME :          SHW_fn_bIntersectShadowSuperObjectLevel1
 DESCRIPTION :   Find the face upon which  the shadow is projected (For quality level 1 )
 =========================================================================================
 CREATION : Philippe Thiébaut
=======================================================================================*/
/* For effect*/
ACP_tdxBool SHW_fn_bIntersectShadowSuperObjectLevel1(
													 MTH3D_tdstVector           *p_stVertexA,
													 MTH3D_tdstVector           *p_stVertexB,
													 MTH3D_tdstVector           *p_stVectAB,
													 HIE_tdxHandleToSuperObject _hSprObj,
													 MTH3D_tdstVector           *p_stPickedPoint,
													 HIE_tdxHandleToSuperObject *p_hPickedSprObj,
													 ACP_tdxHandleOfObject      *p_hPickedObject,
													 ACP_tdxIndex               *p_xPickedElement,
													 ACP_tdxIndex               *p_xPickedFace,
													 MTH3D_tdstVector           *pstGlobalNormalOfPickedFace,
													 HIE_tdxHandleToSuperObject hHandleOfCharacter)
{
	ACP_tdxBool      bResult1=0;
	ACP_tdxIndex     xIntersTest=0;
	MTH3D_tdstVector p_stI;
	MTH3D_tdstVector p_stJ;
	MTH3D_tdstVector p_stK;
	MTH3D_tdstVector stTempVector;
	POS_tdstCompletePosition stTransMatrix;
	
	HIE_fn_bLoadIdentity();
 
	MTH3D_M_vCopyVector(&g_stStartPicking, p_stVertexA);
	MTH3D_M_vCopyVector(&g_stVertexB, p_stVertexB);
	MTH3D_M_vCopyVector(&g_stVertexAB, p_stVectAB);
 
	(*p_stPickedPoint).xZ=MTH_M_xFloatToReal(-100000.0f);
 
	MTH3D_M_vCopyVector(&g_stPickedPoint, p_stPickedPoint);
	g_hPickedSprObj = *p_hPickedSprObj;
	g_hPickedObject= *p_hPickedObject;
	g_xPickedElement =*p_xPickedElement;
	g_xPickedFace = *p_xPickedFace;
 
	/* First intersection detected*/
	bResult1=SHW_fn_bFirstIntersectShadowSuperObject(
		_hSprObj,
		&xIntersTest,
		hHandleOfCharacter);
	
	if (bResult1)
	{
		/*I put the normal of the face into the global reference*/
		GEO_vGetNormalOfGeometricObjectElement(
			g_hPickedObject,
			g_xPickedElement,
			g_xPickedFace,
			pstGlobalNormalOfPickedFace);
 
		POS_fn_vGetRotationMatrix(HIE_fn_hGetSuperObjectGlobalMatrix(g_hPickedSprObj),&p_stI,&p_stJ,&p_stK);
		POS_fn_vSetIdentityMatrix(&stTransMatrix);
		POS_fn_vSetRotationMatrix (&stTransMatrix ,&p_stI ,&p_stJ,&p_stK );
 
		POS_fn_vMulMatrixVector(&stTempVector,&stTransMatrix,pstGlobalNormalOfPickedFace);
		MTH3D_M_vNormalizeVector(pstGlobalNormalOfPickedFace,&stTempVector);
	}
	HIE_fn_bPopMatrix();
 
	MTH3D_M_vCopyVector(p_stVertexA, &g_stStartPicking);
	MTH3D_M_vCopyVector(p_stVertexB, &g_stVertexB);
	MTH3D_M_vCopyVector(p_stVectAB, &g_stVertexAB);
	MTH3D_M_vCopyVector(p_stPickedPoint, &g_stPickedPoint);
	*p_hPickedSprObj = g_hPickedSprObj;
	*p_hPickedObject= g_hPickedObject;
	*p_xPickedElement =g_xPickedElement ;
	*p_xPickedFace = g_xPickedFace;
 
	return (bResult1);
}/*SHW_fn_bIntersectShadowSuperObjectLevel1*/
/* for shadow*/
ACP_tdxBool SHW_fn_bIntersectShadowSuperObjectLevel
(
	HIE_tdxHandleToSuperObject _hSprObj,
	MTH3D_tdstVector           *pstGlobalNormalOfPickedFace,
	HIE_tdxHandleToSuperObject hHandleOfCharacter
)
{
	ACP_tdxBool      bResult1=0;
	ACP_tdxIndex     xIntersTest=0;
	MTH3D_tdstVector p_stI;
	MTH3D_tdstVector p_stJ;
	MTH3D_tdstVector p_stK;
	MTH3D_tdstVector stTempVector;
	POS_tdstCompletePosition stTransMatrix;
	
	HIE_fn_bLoadIdentity();
 
/*	g_stPickedPoint.xZ=MTH_M_xFloatToReal(-100000.0f);*/
 
	/* First intersection detected*/
/*	bResult1 = HIE_bIntersectSegmentWithFirstSuperObject(&g_stStartPicking,&g_stVertexAB,_hSprObj,&g_stPickedPoint,pstGlobalNormalOfPickedFace,&hTest);*/
	
	
/*	bResult1=SHW_fn_bFirstIntersectShadowSuperObject(
		_hSprObj,
		&xIntersTest,
		hHandleOfCharacter);
*/	
/*	if (bResult1)
	{
		//I put the normal of the face into the global reference
		GEO_vGetNormalOfGeometricObjectElement(
			g_hPickedObject,
			g_xPickedElement,
			g_xPickedFace,
			pstGlobalNormalOfPickedFace);
 
		POS_fn_vGetRotationMatrix(HIE_fn_hGetSuperObjectGlobalMatrix(g_hPickedSprObj),&p_stI,&p_stJ,&p_stK);
		POS_fn_vSetIdentityMatrix(&stTransMatrix);
		POS_fn_vSetRotationMatrix (&stTransMatrix ,&p_stI ,&p_stJ,&p_stK );
 
		POS_fn_vMulMatrixVector(&stTempVector,&stTransMatrix,pstGlobalNormalOfPickedFace);
		MTH3D_M_vNormalizeVector(pstGlobalNormalOfPickedFace,&stTempVector);
	}
*/	HIE_fn_bPopMatrix();
 
	return (bResult1);
}/*SHW_fn_bIntersectShadowSuperObjectLevel*/
 
 
/* ##F===================================================================================
 NAME :          SHW_fn_bSecondIntersectShadowWithStaticAndCharacters
 DESCRIPTION :   Find the face intersected by a sphere
 =========================================================================================
 CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fn_bSecondIntersectShadowSuperObjectWithStaticAndCharacters
(
	 HIE_tdxHandleToSuperObject _hCharacterSector,
	 HIE_tdxHandleToSuperObject hHandleOfCharacter
)
{
	ACP_tdxIndex    xI,xJ;
	SECT_tdxHandleOfElementLstCollisionInteraction hCollisionElement;
	SECT_tdxHandleOfElementLstCharacter hCharacterElement;
	
	/*PRF_fn_vStartChrono(PRF_C_ulGLI6, NULL);*/
	if (g_hHandleOfFather)
	{
#ifndef SHW_FORCE_SHADOW
			if (fn_ulStandardGameGetCustomBitsSO(g_hHandleOfFather)&C_ShadowOnMe)
#endif
			{
					SHW_fn_bSecondIntersectShadowSuperObjectSpecificToCharacters
					(
						g_hHandleOfFather,
						hHandleOfCharacter
					);
			}
	}
	else
	{
		if (!g_bIsOnGround)
		{
			/*For the current sector*/
#ifndef SHW_FORCE_SHADOW
			if (fn_ulStandardGameGetCustomBitsSO(hHandleOfCharacter)&C_ShadowOnActors)
#endif
			{
				HIE_tdxHandleToSuperObject hCharacter;
				/*For the limit characters*/
				SECT_M_ForEachCharListInSector(_hCharacterSector,hCharacterElement,xI)
				{
					hCharacter = SECT_GetCharacterInList(hCharacterElement);
#ifndef SHW_FORCE_SHADOW
					if (fn_ulStandardGameGetCustomBitsSO(hCharacter)&C_ShadowOnMe)
#endif
					{
						if (SHW_fn_bIsCharacterBoundingVolumeIntersectWithSphere(hCharacter))
							SHW_fn_bSecondIntersectShadowSuperObjectSpecificToCharacters(
							hCharacter,
							hHandleOfCharacter);
					}
				}
				
				/*For the characters in the limit sectors*/
				SECT_M_ForEachCollisionNodeInCollisionInteractionList(_hCharacterSector,hCollisionElement,xI)
				{	
					SECT_M_ForEachCharListInSector(SECT_GetSectorInCollisionList(hCollisionElement),hCharacterElement,xJ)
					{
						hCharacter = SECT_GetCharacterInList(hCharacterElement);
#ifndef SHW_FORCE_SHADOW
						if (fn_ulStandardGameGetCustomBitsSO(hCharacter)&C_ShadowOnMe)
#endif
						{
							if (SHW_fn_bIsCharacterBoundingVolumeIntersectWithSphere(hCharacter))
								SHW_fn_bSecondIntersectShadowSuperObjectSpecificToCharacters(
								hCharacter,
								hHandleOfCharacter);
						}
					}		
				}
				
			}
		}
 
		/* Test the static hierarchy*/
		SHW_fn_bSecondIntersectShadowSuperObject(
			_hCharacterSector,
			hHandleOfCharacter
			);
 
		SECT_M_ForEachCollisionNodeInCollisionInteractionList(_hCharacterSector,hCollisionElement,xI)
		{
				SHW_fn_bSecondIntersectShadowSuperObject(
					SECT_GetSectorInCollisionList(hCollisionElement),
					hHandleOfCharacter
					);
		}
 
	}
}
 
/* ##F===================================================================================
NAME :          SHW_fn_bIntersectShadowWithUnknownObjectBelow
DESCRIPTION :   Find the faces upon which the shadow is projected ( For quality level 2 ) 
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
ACP_tdxBool SHW_fn_bIntersectShadowWithUnknownObjectBelow(
	HIE_tdxHandleToSuperObject _hCharacterSector,
	HIE_tdxHandleToSuperObject hHandleOfCharacter,
	struct GLD_tdstViewportAttributes_ *p_stVpt)
{
	ACP_tdxBool					bResult1=0;
	ACP_tdxIndex				xIntersTest=0;
	HIE_tdxHandleToSuperObject	hTemporaryHandleOfFather; 
    MS_tdxHandleToDynam			h_Dynam;
	DNM_tdstDynamics			*p_stDynamics;
 
	HIE_fn_bLoadIdentity();
	g_stPickedPoint.xZ=MTH_M_xFloatToReal(-100000.0f);
 
	/*First intersection to find the first face*/
	hTemporaryHandleOfFather=HIE_fn_hGetSuperObjectFather(hHandleOfCharacter);
 
	if (g_bRayIsVertical)
	{
		 g_bIsOnGround = FALSE;
		 g_hHandleOfFather = CAM_fn_hGetFather(hHandleOfCharacter);
		 if (!g_hHandleOfFather)
		 {
			 h_Dynam = M_GetMSHandle(hHandleOfCharacter, Dynam);
			 if(h_Dynam )
			 {
				 p_stDynamics = fn_p_stDynamGetDynamics(h_Dynam);  	
				 if (DNM_M_bDynamicsIsOnGround(p_stDynamics))
					 g_bIsOnGround = TRUE;
			 }
		 }
	}
 
															 
/*	if (HIE_fn_ulGetSuperObjectType(hTemporaryHandleOfFather)==HIE_C_ulPO)
	{
		bResult1=SHW_fn_bFirstIntersectShadowSuperObject
					(
					hTemporaryHandleOfFather,
					&xIntersTest,
					hHandleOfCharacter
					);
	}
	else 
	{
*/		bResult1=SHW_fn_bFirstIntersectShadowSuperObjectAndCharacters
					(
					_hCharacterSector,
					&xIntersTest,
					hHandleOfCharacter
					);
/*	}*/
	/*If the character is on a limit sector of the sector being drawn*/
	if (!bResult1)
	{
		SECT_tdxHandleOfElementLstCollisionInteraction hCollisionElement;
		short xI;
																		 															 
		SECT_M_ForEachCollisionNodeInCollisionInteractionList(_hCharacterSector,hCollisionElement,xI)
		{
			if (!bResult1)
				bResult1=SHW_fn_bFirstIntersectShadowSuperObjectAndCharacters
							(
							SECT_GetSectorInCollisionList(hCollisionElement),
							&xIntersTest,
							hHandleOfCharacter
							);
		}
	}
																		 
	if (bResult1)
	{	
		if (GEO_lCullingSphere ( p_stVpt,&g_stPickedPoint,g_xNearDistance,g_p_stCurrentMatrix, GEO_C_lCullingOut))
		{
			SHW_fn_bSecondIntersectShadowSuperObjectWithStaticAndCharacters
				(
				_hCharacterSector,
				hHandleOfCharacter);
		}
		else 
			return 0;
	}
																	 
	HIE_fn_bPopMatrix();
 
	return (bResult1);
}/*SHW_fn_bIntersectShadowWithUnknownObjectBelow*/
 
 
 
 
/* ##F===================================================================================
NAME :          SHW_fn_vGetPointsOfFaceOfIndexedTriangle
DESCRIPTION :   Put the points of a face into a structure MTH3D_tdstVector vTriangle[3]
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fn_vGetPointsOfFaceOfIndexedTriangle
(
	ACP_tdxHandleOfObject	_hGeometricObjectCastingShadow,
	ACP_tdxHandleOfElement	_hHandleOfElement,
	ACP_tdxIndex			_xIndexOfFace,
	MTH3D_tdstVector		*_p_a3_stTriangle
)
{
	ACP_tdxIndex        xTempIndex0,xTempIndex1,xTempIndex2;
	MTH3D_tdstVector	*p_stTriangle = _p_a3_stTriangle;
 
	GEO_vGetFaceOfIndexedTriangles(_hGeometricObjectCastingShadow,_hHandleOfElement,_xIndexOfFace,
									&xTempIndex0,&xTempIndex1,&xTempIndex2);
	
	GEO_vGetPointOfObject(_hGeometricObjectCastingShadow,p_stTriangle,xTempIndex0);
	p_stTriangle++;
	GEO_vGetPointOfObject(_hGeometricObjectCastingShadow,p_stTriangle,xTempIndex1);
	p_stTriangle++;
	GEO_vGetPointOfObject(_hGeometricObjectCastingShadow,p_stTriangle,xTempIndex2);
}
 
 
 
 
 
/* ##F===================================================================================
NAME :          SHW_fn_vSetLevelOfQualityOfShadows
DESCRIPTION :   Initialization of the quality of the Shadows
Now it is  0 ( No Shadow) 1 ( Low Quality)  or 2 (High Quality)
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
 
void SHW_fn_vSetLevelOfQualityOfShadows(short xQualityOfShadow)
{
	/*By default quality is 2*/
	if (xQualityOfShadow>=2) g_xGeneralLevelOfQualityOfShadows=2;
	else if (xQualityOfShadow==1) g_xGeneralLevelOfQualityOfShadows=1;
	else (g_xGeneralLevelOfQualityOfShadows=0);
}
 
 
 
/* ##F===================================================================================
NAME :          SHW_fn_bInTriangleCalcul
DESCRIPTION :   Used by SHW_fn_bInTriangle
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
ACP_tdxBool SHW_fn_bInTriangleCalcul
(
	MTH_tdxReal *x2,
	MTH_tdxReal *y2,
	MTH_tdxReal *x1,
	MTH_tdxReal *y1,
	MTH_tdxReal *x,
	MTH_tdxReal *y
)
{
	return  MTH_M_bGreaterEqual
			(
				MTH_M_xMul(MTH_M_xSub(*x2,*x1),MTH_M_xSub(*y,*y1)),
				MTH_M_xMul(MTH_M_xSub(*y2,*y1),MTH_M_xSub(*x,*x1))
			);
}
 
/* ##F===================================================================================
NAME :          SHW_fn_bInTriangle
DESCRIPTION :   Test if a 2D point is into a 2D triangle
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
ACP_tdxBool SHW_fn_bInTriangle
(
	MTH_tdxReal *x1,
	MTH_tdxReal *y1,
	MTH_tdxReal *x2,
	MTH_tdxReal *y2,
	MTH_tdxReal *x3,
	MTH_tdxReal *y3,
	MTH_tdxReal *x,
	MTH_tdxReal *y)
{
	ACP_tdxBool bTemp;
/*	bTemp=SHW_fn_bInTriangleCalcul(x2,y2,x1,y1,x,y);*/
/*	return ((bTemp==SHW_fn_bInTriangleCalcul(x3,y3,x2,y2,x,y))&&(bTemp==SHW_fn_bInTriangleCalcul(x1,y1,x3,y3,x,y)));*/
	bTemp=((SHW_fn_bInTriangleCalcul(x2,y2,x1,y1,x,y)&&SHW_fn_bInTriangleCalcul(x3,y3,x2,y2,x,y))&& SHW_fn_bInTriangleCalcul(x1,y1,x3,y3,x,y));
	return bTemp;
}
 
 
/* ##F===================================================================================
NAME :          SHW_fn_bCreateIntersectionSegmentSegment
DESCRIPTION :   Return intersection of two 2D segments
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
ACP_tdxBool SHW_fn_bCreateIntersectionSegmentSegment
(
	MTH_tdxReal        *xA,
	MTH_tdxReal        *yA,
	MTH_tdxReal        *xB,
	MTH_tdxReal        *yB,
	MTH_tdxReal        *xD,
	MTH_tdxReal        *yD,
	MTH_tdxReal        *xE,
	MTH_tdxReal        *yE,
	MTH_tdxReal        *xIntersectionOnSegmentAB,
	MTH_tdxReal        *xIntersectionOnSegmentDE
)
{
	if (MTH_M_bEqual(*xE,*xD))
	{
		if MTH_M_bEqual(*xA,*xB) return 0;
		
		if MTH_M_bEqual(*yE,*yD) return 0;
		
		*xIntersectionOnSegmentAB=MTH_M_xDiv(MTH_M_xSub(*xD,*xA),MTH_M_xSub(*xB,*xA));
		if ((MTH_M_bLess(*xIntersectionOnSegmentAB,MTH_C_ZERO))||
			(MTH_M_bGreater(*xIntersectionOnSegmentAB,MTH_C_ONE))) 
			return 0;
		*xIntersectionOnSegmentDE=MTH_M_xDiv(MTH_M_xAdd(MTH_M_xMul(*xIntersectionOnSegmentAB,
			MTH_M_xSub(*yB,*yA)),MTH_M_xSub(*yA,*yD)),MTH_M_xSub(*yE,*yD));
		if ((MTH_M_bLess(*xIntersectionOnSegmentDE,MTH_C_ZERO))||
			(MTH_M_bGreater(*xIntersectionOnSegmentDE,MTH_C_ONE))) 
			return 0;
		return 1;
	}
	else
	{
		MTH_tdxReal    Div_yEmyD_xEmxD,xEmxD;
		
		xEmxD=MTH_M_xSub(*xE,*xD);
		Div_yEmyD_xEmxD=MTH_M_xDiv(MTH_M_xSub(*yE,*yD),xEmxD);
		if (MTH_M_bEqualZero(Div_yEmyD_xEmxD)) return 0;
		*xIntersectionOnSegmentAB=
			MTH_M_xDiv(MTH_M_xAdd(MTH_M_xSub(*yD,*yA),MTH_M_xMul(Div_yEmyD_xEmxD,MTH_M_xSub(*xA,*xD))),
			MTH_M_xAdd(MTH_M_xSub(*yB,*yA),MTH_M_xMul(Div_yEmyD_xEmxD,MTH_M_xSub(*xA,*xB))));
		if ((MTH_M_bLess(*xIntersectionOnSegmentAB,MTH_C_ZERO))||
			(MTH_M_bGreater(*xIntersectionOnSegmentAB,MTH_C_ONE))) 
			return 0;
		*xIntersectionOnSegmentDE=MTH_M_xDiv(MTH_M_xSub(MTH_M_xAdd(MTH_M_xMul(*xIntersectionOnSegmentAB,
			*xB),MTH_M_xMul(MTH_M_xSub(MTH_C_ONE,*xIntersectionOnSegmentAB),*xA)),*xD),xEmxD);
		if ((MTH_M_bLess(*xIntersectionOnSegmentDE,MTH_C_ZERO))||
			(MTH_M_bGreater(*xIntersectionOnSegmentDE,MTH_C_ONE))) 
			return 0;
		return 1;
	}
}/*SHW_fn_bCreateIntersectionSegmentSegment*/
 
 
/* ##F===================================================================================
NAME :          SHW_fn_vOrderTabResultInt
DESCRIPTION :   Return an order in an array of points: Specific to Fake Shadow
SEE THE DESCRIPTION OF THIS FUNCTION IN DOCUBI IF YOU MISS SOMETHING
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fn_vOrderTabResultInt
(
	SHW_tdstResultIntersectionCT  *_p_a10_stTabResultInt,
	short                         *_p_a10_xOrderInTabResult,
	short                         _xImax
)
{
	long							i;
	short							j,jprec,xCT1,xStart1,xCT2,xStart2;
	ACP_tdxBool						test,testOK;
	SHW_tdstResultIntersectionCT	*p_stTabResultInt;
	short							*p_xOrderInTabResult;
 
 
	*_p_a10_xOrderInTabResult=0;
	xCT1=_p_a10_stTabResultInt->xCT1;
	xStart1=_p_a10_stTabResultInt->xStart1;
	xCT2=_p_a10_stTabResultInt->xCT2;
	xStart2=_p_a10_stTabResultInt->xStart2;
	jprec=0;
 
	p_xOrderInTabResult = _p_a10_xOrderInTabResult;
	for (i=1;i<_xImax;i++)
	{
		j=0;
		testOK=1;
		p_stTabResultInt = _p_a10_stTabResultInt;
		while (testOK)
		{
			test=(((xCT1==p_stTabResultInt->xCT1)&&(xStart1==p_stTabResultInt->xStart1))||
			((xCT2==p_stTabResultInt->xCT2)&&(xStart2==p_stTabResultInt->xStart2))||
			((xCT1==p_stTabResultInt->xCT2)&&(xStart1==p_stTabResultInt->xStart2))||
			((xCT2==p_stTabResultInt->xCT1)&&(xStart2==p_stTabResultInt->xStart1)));
			testOK=(((j==jprec)||(j==*p_xOrderInTabResult)||(test==0))&&(j<_xImax));
			if (testOK) 
			{
				j++;
				p_stTabResultInt++;
			}
		}
		jprec=*p_xOrderInTabResult;
		p_xOrderInTabResult++;
		*p_xOrderInTabResult=j;
		xCT1=p_stTabResultInt->xCT1;
		xStart1=p_stTabResultInt->xStart1;
		xCT2=p_stTabResultInt->xCT2;
		xStart2=p_stTabResultInt->xStart2;
	}
}/*SHW_fn_vOrderTabResultInt*/
 
/* ##F===================================================================================
NAME :          SHW_fn_vCalculateCoordinatesForCorners
DESCRIPTION :   Calculate the coordinates of a corner of UV texture:Specific to Fake Shadow
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fn_vCalculateCoordinatesForCorners
(
	MTH3D_tdstVector               *_p_stTempTriangle,
	SHW_tdstResultIntersectionCT   *_p_stTabResultInt,
	MTH3D_tdstVector               *_p_stDirectionOfShadow,
	MTH3D_tdstVector               *_p_stTempGlobalNormal,
	MTH_tdxReal                    *_p_xZc1  ,
	MTH_tdxReal                    *_p_xZc2  ,
	MTH_tdxReal                    *_p_xInvGlobalNormalxZ,
	MTH3D_tdstVector               *_p_stGlobalPoints
)
{
	MTH_tdxReal UTemp1=MTH_M_xMul(*_p_xZc1  ,MTH_M_xSub(_p_stTabResultInt->uvPoint.xU,MTH_M_xFloatToReal(0.5f)));
	MTH_tdxReal UTemp2=MTH_M_xMul(*_p_xZc2  ,MTH_M_xSub(_p_stTabResultInt->uvPoint.xV,MTH_M_xFloatToReal(0.5f)));
 
	_p_stGlobalPoints->xX=MTH_M_xSub(g_stStartPicking.xX,MTH_M_xAdd(MTH_M_xMul(UTemp1,_p_stDirectionOfShadow->xY),MTH_M_xMul(UTemp2,_p_stDirectionOfShadow->xX)));
 
	_p_stGlobalPoints->xY=MTH_M_xAdd(g_stStartPicking.xY,MTH_M_xSub(MTH_M_xMul(UTemp1,_p_stDirectionOfShadow->xX),MTH_M_xMul(UTemp2,_p_stDirectionOfShadow->xY)));
	_p_stGlobalPoints->xZ=MTH_M_xSub
						   (
							_p_stTempTriangle->xZ,
							MTH_M_xMul
							(
								*_p_xInvGlobalNormalxZ,
								MTH_M_xAdd
								(
									MTH_M_xMul(_p_stTempGlobalNormal->xX,MTH_M_xSub(_p_stGlobalPoints->xX,_p_stTempTriangle->xX)),
									MTH_M_xMul(_p_stTempGlobalNormal->xY,MTH_M_xSub(_p_stGlobalPoints->xY,_p_stTempTriangle->xY))
								)
							)
						);
 
}/*SHW_fn_vCalculateCoordinatesForCorners*/
 
 
/* ##F===================================================================================
NAME :          SHW_fn_vClipShadow
DESCRIPTION :   Clip a face only with UV in [0;1] Specific to Fake Shadow
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fn_vClipShadow
(
	ACP_tdst2DUVValues	*_p_a3_stCalculatedUV,
	ACP_tdxIndex	    *_p_xTempPoints,
	ACP_tdxIndex		*_p_xTempFace,
	MTH3D_tdstVector	*_p_a3_stTempTriangle,
	MTH3D_tdstVector	*_p_stDirectionOfShadow,
	MTH3D_tdstVector	*_p_stTempGlobalNormal,
	MTH_tdxReal			*_p_xZc1,
	MTH_tdxReal			*_p_xZc2,
	MTH_tdxReal			*_p_xInvGlobalNormalxZ
)
{
	ACP_tdxIndex					xIndexOfFirstPoint;
	ACP_tdst2DUVValues				stUVC,stUVC2;
	SHW_tdstResultIntersectionCT	a10_stTabResultInt[10];
	short							a10_wOrderInTabResult[10];
	short							xNbIntTC=0,i,j;
	MTH3D_tdstVector				a10_stGlobalPoints[10];
	ACP_tdxBool						bInT1,bInT2,bInT3,bInT4,bInC1,bInC2,bInC3;
	ACP_tdxHandleOfObject			hHandleOfGeometricShadowObject;
	SHW_tdstResultIntersectionCT	*p_stTabResultInt;
	MTH3D_tdstVector				*p_stTmpGlobalPoints;
	short							*p_wOrderInTabResult;
	GLI_tdxUVValue					*p_xValueU0, *p_xValueU1, *p_xValueU2;	
	GLI_tdxUVValue					*p_xValueV0, *p_xValueV1, *p_xValueV2;	
	MTH3D_tdstVector				*p_stTempTriangle;
	ACP_tdst2DUVValues				*p_stCalculatedUV;
	MTH3D_tdstVector				*p_stNextTempTriangle;
	ACP_tdst2DUVValues				*p_stNextCalculatedUV;
 
	p_stCalculatedUV = _p_a3_stCalculatedUV;
	p_xValueU0 = &p_stCalculatedUV->xU;
	p_xValueV0 = &p_stCalculatedUV->xV;
	p_stCalculatedUV ++;
	p_xValueU1 = &p_stCalculatedUV->xU;
	p_xValueV1 = &p_stCalculatedUV->xV;
	p_stCalculatedUV ++;
	p_xValueU2 = &p_stCalculatedUV->xU;
	p_xValueV2 = &p_stCalculatedUV->xV;
 
	bInC1 = (MTH_M_bInUnitEqual(*p_xValueU0) && MTH_M_bInUnitEqual(*p_xValueV0));
	bInC2 = (MTH_M_bInUnitEqual(*p_xValueU1) && MTH_M_bInUnitEqual(*p_xValueV1));
	bInC3 = (MTH_M_bInUnitEqual(*p_xValueU2) && MTH_M_bInUnitEqual(*p_xValueV2));
 
	hHandleOfGeometricShadowObject = p_hHandleOfGeometricShadowObject[g_xIndexOfShadow];
	/*If the three points of the triangle are in the UV square*/
	if ((bInC1)&&(bInC2)&&(bInC3))
	{
		p_stTempTriangle = _p_a3_stTempTriangle;
		p_stCalculatedUV = _p_a3_stCalculatedUV;
 
		for (i=0;i<3;i++, p_stTempTriangle++, p_stCalculatedUV++)
		{
			GEO_vSetPointOfObject(hHandleOfGeometricShadowObject,p_stTempTriangle,(short)((*_p_xTempPoints)+i));
			GEO_vSetUVOfIndexedTriangles(hHandleOfGeometricShadowObject,0,(short)((*_p_xTempPoints)+i),p_stCalculatedUV);
		}
 
		GEO_vSetFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,*_p_xTempFace,*_p_xTempPoints,(short)((*_p_xTempPoints)+1),(short)((*_p_xTempPoints)+2));
		/*M_PrintfN64(("Adding Face %d,%d,%d\n",xIndexOfFirstPoint,*_p_xTempPoints,(short)((*_p_xTempPoints)+1),(short)((*_p_xTempPoints)+2)));*/
		GEO_vSetIndexedUVOfFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,*_p_xTempFace,*_p_xTempPoints,(short)((*_p_xTempPoints)+1),(short)((*_p_xTempPoints)+2));
		(*_p_xTempFace)++;
		(*_p_xTempPoints)+=3;
	}
	else
	{
		xNbIntTC=0;
		p_stTabResultInt = a10_stTabResultInt;
		stUVC.xU=MTH_C_ZERO;
		stUVC.xV=MTH_C_ZERO;
		bInT1=SHW_fn_bInTriangle(p_xValueU0,p_xValueV0,p_xValueU1,p_xValueV1,p_xValueU2,p_xValueV2,&stUVC.xU,&stUVC.xV);
		if (bInT1)
		{
			p_stTabResultInt->xCT1=0;
			p_stTabResultInt->xCT2=0;
			p_stTabResultInt->xStart1=3;
			p_stTabResultInt->xStart2=0;
			p_stTabResultInt->uvPoint.xU=MTH_C_ZERO;
			p_stTabResultInt->uvPoint.xV=MTH_C_ZERO;
			SHW_fn_vCalculateCoordinatesForCorners(_p_a3_stTempTriangle,p_stTabResultInt,_p_stDirectionOfShadow,_p_stTempGlobalNormal,_p_xZc1,_p_xZc2 ,_p_xInvGlobalNormalxZ,&a10_stGlobalPoints[xNbIntTC]);
			xNbIntTC++;
			p_stTabResultInt++;
		}
		stUVC.xU=MTH_C_ONE;
/*		stUVC.xV=MTH_C_ZERO;*/
		bInT2=SHW_fn_bInTriangle(p_xValueU0,p_xValueV0,p_xValueU1,p_xValueV1,p_xValueU2,p_xValueV2,&stUVC.xU,&stUVC.xV);
		if (bInT2)
		{
			p_stTabResultInt->xCT1=0;
			p_stTabResultInt->xCT2=0;
			p_stTabResultInt->xStart1=0;
			p_stTabResultInt->xStart2=1;
			p_stTabResultInt->uvPoint.xU=MTH_C_ONE;
			p_stTabResultInt->uvPoint.xV=MTH_C_ZERO;
			SHW_fn_vCalculateCoordinatesForCorners(_p_a3_stTempTriangle,p_stTabResultInt,_p_stDirectionOfShadow,_p_stTempGlobalNormal,_p_xZc1,_p_xZc2,_p_xInvGlobalNormalxZ,&a10_stGlobalPoints[xNbIntTC]);
			xNbIntTC++;
			p_stTabResultInt++;
		}
/*		stUVC.xU=MTH_C_ONE;*/
		stUVC.xV=MTH_C_ONE;
		bInT3=SHW_fn_bInTriangle(p_xValueU0,p_xValueV0,p_xValueU1,p_xValueV1,p_xValueU2,p_xValueV2,&stUVC.xU,&stUVC.xV);
		if (bInT3)
		{
			p_stTabResultInt->xCT1=0;
			p_stTabResultInt->xCT2=0;
			p_stTabResultInt->xStart1=1;
			p_stTabResultInt->xStart2=2;
			p_stTabResultInt->uvPoint.xU=MTH_C_ONE;
			p_stTabResultInt->uvPoint.xV=MTH_C_ONE;
			SHW_fn_vCalculateCoordinatesForCorners(_p_a3_stTempTriangle,p_stTabResultInt,_p_stDirectionOfShadow,_p_stTempGlobalNormal,_p_xZc1,_p_xZc2,_p_xInvGlobalNormalxZ,&a10_stGlobalPoints[xNbIntTC]);
			p_stTabResultInt++;
			xNbIntTC++;
		}
		stUVC.xU=MTH_C_ZERO;
/*		stUVC.xV=MTH_C_ONE;*/
		bInT4=SHW_fn_bInTriangle(p_xValueU0,p_xValueV0,p_xValueU1,p_xValueV1,p_xValueU2,p_xValueV2,&stUVC.xU,&stUVC.xV);
		if (bInT4)
		{
			p_stTabResultInt->xCT1=0;
			p_stTabResultInt->xCT2=0;
			p_stTabResultInt->xStart1=2;
			p_stTabResultInt->xStart2=3;
			p_stTabResultInt->uvPoint.xU=MTH_C_ZERO;
			p_stTabResultInt->uvPoint.xV=MTH_C_ONE;
			SHW_fn_vCalculateCoordinatesForCorners(_p_a3_stTempTriangle,p_stTabResultInt,_p_stDirectionOfShadow,_p_stTempGlobalNormal,_p_xZc1,_p_xZc2,_p_xInvGlobalNormalxZ,&a10_stGlobalPoints[xNbIntTC]);
			p_stTabResultInt++;
			xNbIntTC++;
		}
		/*If all the UV square is in the triangle*/
		if ((bInT1)&&(bInT2)&&(bInT3)&&(bInT4))
		{
			ACP_tdxIndex xIndexOfFirstPoint=(*_p_xTempPoints);
			p_stTabResultInt = a10_stTabResultInt;
			p_stTmpGlobalPoints = a10_stGlobalPoints;
			for (i=0;i<xNbIntTC;i++)
			{
				GEO_vSetPointOfObject(hHandleOfGeometricShadowObject,p_stTmpGlobalPoints,*_p_xTempPoints);
				GEO_vSetUVOfIndexedTriangles(hHandleOfGeometricShadowObject,0,*_p_xTempPoints,&(p_stTabResultInt->uvPoint));
				p_stTmpGlobalPoints++;
				p_stTabResultInt++;	
				(*_p_xTempPoints)++;
			}
 
			for (i=1;i<xNbIntTC-1;i++)
			{
				short p1,p2;
				p1=xIndexOfFirstPoint+i;
				p2=p1+1;
				GEO_vSetFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,*_p_xTempFace,xIndexOfFirstPoint,p1,p2);
				/*M_PrintfN64(("Adding Face %d,%d,%d\n",xIndexOfFirstPoint,p1,p2));*/
				GEO_vSetIndexedUVOfFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,*_p_xTempFace,xIndexOfFirstPoint,p1,p2);
				(*_p_xTempFace)++;
			}
		}
		else
		{
			p_stTempTriangle = _p_a3_stTempTriangle;
			p_stTmpGlobalPoints = &a10_stGlobalPoints[xNbIntTC];
			p_stTabResultInt = &a10_stTabResultInt[xNbIntTC];
			if (bInC1)
			{
				p_stTabResultInt->xCT1=1;
				p_stTabResultInt->xCT2=1;
				p_stTabResultInt->xStart1=2;
				p_stTabResultInt->xStart2=0;
				p_stTabResultInt->uvPoint.xU=*p_xValueU0;
				p_stTabResultInt->uvPoint.xV=*p_xValueV0;
				p_stTmpGlobalPoints->xX=p_stTempTriangle->xX;
				p_stTmpGlobalPoints->xY=p_stTempTriangle->xY;
				p_stTmpGlobalPoints->xZ=p_stTempTriangle->xZ;
				p_stTabResultInt++;
				p_stTmpGlobalPoints++;
				xNbIntTC++;
			}
			p_stTempTriangle++;
			if (bInC2)
			{
				p_stTabResultInt->xCT1=1;
				p_stTabResultInt->xCT2=1;
				p_stTabResultInt->xStart1=0;
				p_stTabResultInt->xStart2=1;
				p_stTabResultInt->uvPoint.xU=*p_xValueU1;
				p_stTabResultInt->uvPoint.xV=*p_xValueV1;
				p_stTmpGlobalPoints->xX=p_stTempTriangle->xX;
				p_stTmpGlobalPoints->xY=p_stTempTriangle->xY;
				p_stTmpGlobalPoints->xZ=p_stTempTriangle->xZ;
				
				p_stTabResultInt++;
				p_stTmpGlobalPoints++;
				xNbIntTC++;
			}
			p_stTempTriangle++;
			if (bInC3)
			{
				p_stTabResultInt->xCT1=1;
				p_stTabResultInt->xCT2=1;
				p_stTabResultInt->xStart1=1;
				p_stTabResultInt->xStart2=2;
				p_stTabResultInt->uvPoint.xU=*p_xValueU2;
				p_stTabResultInt->uvPoint.xV=*p_xValueV2;
				p_stTmpGlobalPoints->xX=p_stTempTriangle->xX;
				p_stTmpGlobalPoints->xY=p_stTempTriangle->xY;
				p_stTmpGlobalPoints->xZ=p_stTempTriangle->xZ;
				p_stTabResultInt++;
				p_stTmpGlobalPoints++;
				xNbIntTC++;
			}
	
			/*Here are the intersection computations*/
			for (i=0;i<4;i++)
			{
				switch(i)
				{
						case 0:
						{
							stUVC.xU=MTH_C_ZERO;
							stUVC.xV=MTH_C_ZERO;
							stUVC2.xU=MTH_C_ONE;
							stUVC2.xV=MTH_C_ZERO;
							break;
						}
						case 1:
						{
							stUVC.xU=MTH_C_ONE;
/*							stUVC.xV=MTH_C_ZERO;*/
/*							stUVC2.xU=MTH_C_ONE;*/
							stUVC2.xV=MTH_C_ONE;
							break;
						}
						case 2:
						{
/*							stUVC.xU=MTH_C_ONE;*/
							stUVC.xV=MTH_C_ONE;
							stUVC2.xU=MTH_C_ZERO;
/*							stUVC2.xV=MTH_C_ONE;*/
							break;
						}
						case 3: 
						{
							stUVC.xU=MTH_C_ZERO;
/*							stUVC.xV=MTH_C_ONE;*/
/*							stUVC2.xU=MTH_C_ZERO;*/
							stUVC2.xV=MTH_C_ZERO;
							break;
						}
				}
 
				p_stTabResultInt = &a10_stTabResultInt[xNbIntTC];
				p_stTmpGlobalPoints = &a10_stGlobalPoints[xNbIntTC];
				p_stTempTriangle = _p_a3_stTempTriangle;
				p_stCalculatedUV = _p_a3_stCalculatedUV;
 
				p_stNextTempTriangle = p_stTempTriangle;
				p_stNextCalculatedUV = p_stCalculatedUV;
				for (j=0;j<3;j++, p_stTempTriangle++, p_stCalculatedUV++)
				{
					MTH_tdxReal			xAlpha1,xAlpha2;
 
					if (j==2)
					{
						p_stNextTempTriangle = _p_a3_stTempTriangle;
						p_stNextCalculatedUV = _p_a3_stCalculatedUV;	
					}
					else
					{
						p_stNextTempTriangle++;
						p_stNextCalculatedUV++;	
					}
 
					
					if  (SHW_fn_bCreateIntersectionSegmentSegment(&stUVC.xU,&stUVC.xV,&stUVC2.xU,&stUVC2.xV,
																 &p_stCalculatedUV->xU,&p_stCalculatedUV->xV,
																 &p_stNextCalculatedUV->xU,&p_stNextCalculatedUV->xV,
																 &xAlpha1,&xAlpha2))
					{
						MTH_tdxReal xS1;
						p_stTabResultInt->xCT1=0;
						p_stTabResultInt->xCT2=1;
						p_stTabResultInt->xStart1=i;
						p_stTabResultInt->xStart2=j;
						xS1=MTH_M_xSub(MTH_C_ONE,xAlpha1);
 
						p_stTabResultInt->uvPoint.xU=MTH_M_xAdd(MTH_M_xMul(xS1,stUVC.xU),MTH_M_xMul(xAlpha1,stUVC2.xU));
						p_stTabResultInt->uvPoint.xV=MTH_M_xAdd(MTH_M_xMul(xS1,stUVC.xV),MTH_M_xMul(xAlpha1,stUVC2.xV));
						xS1=MTH_M_xSub(MTH_C_ONE,xAlpha2);
						p_stTmpGlobalPoints->xX=MTH_M_xAdd(MTH_M_xMul(xS1,p_stTempTriangle->xX),MTH_M_xMul(xAlpha2,p_stNextTempTriangle->xX));
						p_stTmpGlobalPoints->xY=MTH_M_xAdd(MTH_M_xMul(xS1,p_stTempTriangle->xY),MTH_M_xMul(xAlpha2,p_stNextTempTriangle->xY));
						p_stTmpGlobalPoints->xZ=MTH_M_xAdd(MTH_M_xMul(xS1,p_stTempTriangle->xZ),MTH_M_xMul(xAlpha2,p_stNextTempTriangle->xZ));
						p_stTabResultInt++;
						p_stTmpGlobalPoints++;
						xNbIntTC++;
					}
				}
			}  
			/*To put the array of points in order  */
			SHW_fn_vOrderTabResultInt(a10_stTabResultInt,a10_wOrderInTabResult,xNbIntTC);
 
			xIndexOfFirstPoint=*_p_xTempPoints;
			/*Add the points found*/
			p_wOrderInTabResult = a10_wOrderInTabResult;
			for (i=0;i<xNbIntTC;i++, p_wOrderInTabResult++)
			{
				GEO_vSetPointOfObject(hHandleOfGeometricShadowObject,&a10_stGlobalPoints[(*p_wOrderInTabResult)],*_p_xTempPoints);
				GEO_vSetUVOfIndexedTriangles(hHandleOfGeometricShadowObject,0,*_p_xTempPoints,&a10_stTabResultInt[(*p_wOrderInTabResult)].uvPoint);
				(*_p_xTempPoints)++;
			}
			/*Add the triangular faces*/
			for (i=1;i<xNbIntTC-1;i++)
			{
				short p1=xIndexOfFirstPoint+i;
				short p2=p1+1;
				GEO_vSetFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,*_p_xTempFace,xIndexOfFirstPoint,p1,p2);
				/* M_PrintfN64(("Adding Face %d,%d,%d\n",xIndexOfFirstPoint,p1,p2));*/
				GEO_vSetIndexedUVOfFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,*_p_xTempFace,xIndexOfFirstPoint,p1,p2);
				(*_p_xTempFace)++;
			}/*End of Add Faces */
		}/*End of bInclusTriangle all corners*/
	}/*End test of bInTriangle  */
}/*SHW_fn_vClipShadow*/
 
 
/* ##F===================================================================================
NAME :          SHW_fn_xFormulaU
DESCRIPTION :   Calculate U from x and y
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
MTH_tdxReal SHW_fn_xFormulaU
(
	 MTH_tdxReal        *_p_xScaleX,
	 MTH_tdxReal        *_p_xCoefAltitude,
	 MTH3D_tdstVector   *_p_stDirectionOfShadow,
	 MTH_tdxReal        *_p_xXPoint,
	 MTH_tdxReal        *_p_xYPoint
)
{
	 return MTH_M_xAdd(MTH_C_Inv2,MTH_M_xMul(*_p_xScaleX,MTH_M_xMul(*_p_xCoefAltitude,
						MTH_M_xSub(MTH_M_xMul(_p_stDirectionOfShadow->xX,*_p_xYPoint),
						MTH_M_xMul(_p_stDirectionOfShadow->xY,*_p_xXPoint)))));
}
 
 
/* ##F===================================================================================
NAME :          SHW_fn_xFormulaV
DESCRIPTION :   Calculate V from x and y
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
MTH_tdxReal SHW_fn_xFormulaV
(
	 MTH_tdxReal        *_p_xScaleY,
	 MTH_tdxReal        *_p_xCoefAltitude,
	 MTH3D_tdstVector   *_p_stDirectionOfShadow,
	 MTH_tdxReal        *_p_xXPoint,
	 MTH_tdxReal        *_p_xYPoint
)
{
	 return MTH_M_xSub(MTH_C_Inv2,MTH_M_xMul(*_p_xScaleY,MTH_M_xMul(*_p_xCoefAltitude,
						MTH_M_xAdd(MTH_M_xMul(_p_stDirectionOfShadow->xX,*_p_xXPoint),
						MTH_M_xMul(_p_stDirectionOfShadow->xY,*_p_xYPoint)))));
}
 
 
/* ##F===================================================================================
NAME :          SHW_fn_bFaceIsGoodInZForShadow
DESCRIPTION :   Test if a point of the face is over the Character
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
ACP_tdxBool SHW_fn_bFaceIsGoodInZForShadow
(
	 MTH3D_tdstVector	*_p_a3_stTempTriangle,
	 MTH3D_tdstVector	*_p_stPickedPoint,
	 short              _xObjPicked,
	 short              _xFacePicked
)
{
	long				i;
	ACP_tdxBool			bTest=1;
	ACP_tdxBool			bAnnulTestHigher=1;
	ACP_tdxBool			bAnnulTestLower=1;
	MTH3D_tdstVector	*p_stTempTriangle;
	SHW_tdstShadowInfo  *p_stShadowInfo;
 
 	p_stTempTriangle = _p_a3_stTempTriangle;
 
	 /* Second test for nearly vertical faces if they are connected to horizontal faces*/
	p_stShadowInfo = &g_a_stShadowInfo[_xObjPicked];
 
 if (p_stShadowInfo->bDrawFace[_xFacePicked]==1)
 {
	ACP_tdxBool				bPoint1IsOk=0;
	ACP_tdxBool				bPoint2IsOk=0;
	ACP_tdxBool				bPoint3IsOk=0;
	ACP_tdxIndex			xPointIndex0,xPointIndex1,xPointIndex2;
	short					j;
	COL_tdstShadowElement	*p_stShadowElement;
	short					*p_bDrawFace;
	ACP_tdxIndex			xNbElement;
		 
	 /* First test if all the points are above or below the picked point*/
	 for (i=0;i<3;i++,p_stTempTriangle++)
	 {
		 if (MTH_M_bLess(p_stTempTriangle->xZ,MTH_M_xAdd(_p_stPickedPoint->xZ,MTH_M_xFloatToReal(0.80f))))
		 {
			 bAnnulTestHigher=0;
		 }
		 if (MTH_M_bGreater(p_stTempTriangle->xZ,MTH_M_xSub(_p_stPickedPoint->xZ,MTH_M_xFloatToReal(0.80f))))
		 {
			 bAnnulTestLower=0;
		 }
	 }
	 if ((bAnnulTestHigher)&&(bAnnulTestLower)) 
		 return 0;
 
	p_stShadowElement = &p_stShadowInfo->a_stShadowObject[_xFacePicked];
	GEO_vGetFaceOfIndexedTriangles(p_stShadowInfo->hPickedObject,
									p_stShadowElement->xElementIndex,
									p_stShadowElement->xDataElementIndex,
									&xPointIndex0,&xPointIndex1,&xPointIndex2);
	
	p_stShadowElement = p_stShadowInfo->a_stShadowObject;
	p_bDrawFace = &p_stShadowInfo->bDrawFace[0];
	xNbElement = p_stShadowInfo->xNbElement; 
	for (j=0;j<xNbElement;j++, p_stShadowElement++, p_bDrawFace++)
	{
		if ((*p_bDrawFace==1) && (!((bPoint1IsOk)&&(bPoint2IsOk)&&(bPoint3IsOk))))
		{
			ACP_tdxIndex xPoint2Index0,xPoint2Index1,xPoint2Index2;
				 
			GEO_vGetFaceOfIndexedTriangles(p_stShadowInfo->hPickedObject,
											p_stShadowElement->xElementIndex,
											p_stShadowElement->xDataElementIndex,
											&xPoint2Index0,&xPoint2Index1,&xPoint2Index2);
 
			if (((xPointIndex0==xPoint2Index0)||(xPointIndex0==xPoint2Index1)||(xPointIndex0==xPoint2Index2)))
					bPoint1IsOk=1;
			if ((!bPoint2IsOk)&&((xPointIndex1==xPoint2Index0)||(xPointIndex1==xPoint2Index1)||(xPointIndex1==xPoint2Index2)))
					bPoint2IsOk=1;
			if ((!bPoint3IsOk)&&((xPointIndex2==xPoint2Index0)||(xPointIndex2==xPoint2Index1)||(xPointIndex2==xPoint2Index2)))
					bPoint3IsOk=1;
		}
	}
	bTest=((bPoint1IsOk)&&(bPoint2IsOk)&&(bPoint3IsOk));
 
	}
	return bTest;
}/*SHW_fn_bFaceIsGoodInZForShadow*/
 
 
/* ##F===================================================================================
NAME :          SHW_fn_vCreateIntersectionShadowFace
DESCRIPTION :   Create the shadow of one SpObj on one face
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fn_vCreateIntersectionShadowFace
(
	 MTH3D_tdstVector      *_p_stGlobalNormal,
	 MTH_tdxReal           *_p_xInvGlobalNormalxZ,
	 ACP_tdxHandleOfObject _hPickedObject,
	 short                 _xObjPicked,
	 short                 _xFacePicked,
	 ACP_tdxIndex          _xPickedElement,
	 ACP_tdxIndex          _xPickedFace,
	 MTH3D_tdstVector      *_p_stPickedPoint,
	 MTH3D_tdstVector      *_p_stDirectionOfShadow,
	 ACP_tdxIndex          *_p_xTempPoints,
	 ACP_tdxIndex          *_p_xTempFace,
	 MTH_tdxReal           *_p_xScaleX,
	 MTH_tdxReal           *_p_xScaleY,
	 MTH_tdxReal           *_p_xCoefAltitude,
	 MTH_tdxReal           *_p_xZc1,
	 MTH_tdxReal           *_p_xZc2
)
{
	MTH3D_tdstVector		a3_stTempTriangle[3];
	MTH3D_tdstVector		*p_stTempTriangle;
	MTH_tdxReal				xXPoint,xYPoint;
	ACP_tdst2DUVValues		a3_stCalculatedUV[3];
	ACP_tdst2DUVValues		*p_stCalculatedUV;
	short					i;
	GEO_tdxHandleToMatrix   hGlobalMatrixOfCharacter;
	 
	
	SHW_fn_vGetPointsOfFaceOfIndexedTriangle(_hPickedObject,_xPickedElement,_xPickedFace,a3_stTempTriangle);
	
	p_stTempTriangle = a3_stTempTriangle;
	hGlobalMatrixOfCharacter = HIE_fn_hGetSuperObjectGlobalMatrix(g_a_stShadowInfo[_xObjPicked].hPickedSpObj);
 
	for (i=0;i<3;i++, p_stTempTriangle++)
	{
		p_stTempTriangle->xZ += 0.05f;
		 /* I get the triangle in the global reference*/
		 POS_fn_vMulMatrixVertex (p_stTempTriangle,hGlobalMatrixOfCharacter,p_stTempTriangle);
	}
	 
	/*I create the shadow faces if the trangle is correct and if there is still enough space in my array*/
	if (
/*		(SHW_fn_bFaceIsGoodInZForShadow(a3_stTempTriangle,_p_stPickedPoint,_xObjPicked,_xFacePicked))&&*/
		(*_p_xTempPoints<=SHW_C_xNbMaxOfPointsPerShadow-6)&&
		(*_p_xTempFace<=SHW_C_xNbMaxOfFacesPerShadow-4))	 
	 {
		p_stTempTriangle = a3_stTempTriangle;
		p_stCalculatedUV = a3_stCalculatedUV;
		for (i=0;i<3;i++, p_stTempTriangle++, p_stCalculatedUV++)
		{
			xXPoint=(MTH_M_xSub(p_stTempTriangle->xX,g_stStartPicking.xX));
			xYPoint=(MTH_M_xSub(p_stTempTriangle->xY,g_stStartPicking.xY));
 
			/*I compute the corresponding UV*/
			p_stCalculatedUV->xU=SHW_fn_xFormulaU(_p_xScaleX,_p_xCoefAltitude,_p_stDirectionOfShadow,&xXPoint,&xYPoint);
			p_stCalculatedUV->xV=SHW_fn_xFormulaV(_p_xScaleY,_p_xCoefAltitude,_p_stDirectionOfShadow,&xXPoint,&xYPoint);
		}
	 	/*PRF_fn_vStartChrono(PRF_C_ulGLI5, NULL);*/
		SHW_fn_vClipShadow(a3_stCalculatedUV,_p_xTempPoints,_p_xTempFace,a3_stTempTriangle,_p_stDirectionOfShadow,
							_p_stGlobalNormal,_p_xZc1,_p_xZc2,_p_xInvGlobalNormalxZ);
		/*PRF_fn_vStopChrono(PRF_C_ulGLI5, NULL);*/
 
	 }
}/*SHW_fn_vCreateIntersectionShadowFace*/
 
 
/* ##F===================================================================================
NAME :          SHW_fn_vCreateShadowOfCharacterOnFace
DESCRIPTION :   Create the shadow of a character on one face
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fn_vCreateShadowOfCharacterOnFace
(
	MTH3D_tdstVector           *_p_stGlobalNormal,
	MTH_tdxReal                _xInvNormalZ,
	HIE_tdxHandleToSuperObject _hFather,
	ACP_tdxHandleOfObject      _hPickedObject,
	short                      _xObjPicked,
	short                      _xFacePicked,
	ACP_tdxIndex               _xPickedElement,
	ACP_tdxIndex               _xPickedFace,
	MTH3D_tdstVector           *_p_stPickedPoint,
	ACP_tdxIndex               *_p_xTempPoints,
	ACP_tdxIndex               *_p_xTempFace,
	MTH_tdxReal                *_p_xCoefAltitude,
	MTH_tdxReal                *_p_xScaleX,
	MTH_tdxReal                *_p_xScaleY
	)
{
	GEO_tdxHandleToMatrix   hGlobalMatrixOfCharacter;
	MTH3D_tdstVector        stCharacterRotationX;
	MTH3D_tdstVector        stCharacterRotationY;
	MTH3D_tdstVector        stCharacterRotationZ;
	MTH_tdxReal             xZc1;
	MTH_tdxReal             xZc2;
	
	hGlobalMatrixOfCharacter=HIE_fn_hGetSuperObjectGlobalMatrix(_hFather);
	
	if (MTH3D_M_bIsNullVector(&g_stDirOfShadow))
	{
		/* I get the rotation matrix of the character*/
		POS_fn_vGetRotationMatrix(hGlobalMatrixOfCharacter ,&stCharacterRotationX,&stCharacterRotationY,&stCharacterRotationZ) ;  
	}
	else
	{
		MTH3D_M_vCopyVector(&stCharacterRotationX, &g_stDirOfShadow);
	}
	
	/*Important: Rotation doesn't have to take in account the Z coef*/
	stCharacterRotationX.xZ=MTH_C_ZERO;
	
	/*If the orientation vector is in Z only*/
	if ((MTH_M_bLess(MTH_M_xAbs(stCharacterRotationX.xX),MTH_M_xFloatToReal(0.1f)))&&
		(MTH_M_bLess(MTH_M_xAbs(stCharacterRotationX.xY),MTH_M_xFloatToReal(0.1f))))
	{
		/*I don't have any orientation so the shadow will be round*/
		/*The round scale must be defined here*/
		stCharacterRotationX.xX=MTH_M_xDiv(0.48f,fn_x3dDataGetShadowScaleXFromSO(_hFather));
		stCharacterRotationX.xY=stCharacterRotationX.xX;
	}
	MTH3D_M_vNormalizeVector(&stCharacterRotationX,&stCharacterRotationX);
	
	xZc1=MTH_M_xDiv(MTH_C_ONE,MTH_M_xMul(*_p_xScaleX,*_p_xCoefAltitude));
	xZc2=MTH_M_xDiv(MTH_C_ONE,MTH_M_xMul(*_p_xScaleY,*_p_xCoefAltitude));
	
	/*PRF_fn_vStartChrono(PRF_C_ulGLI6, NULL);*/
	SHW_fn_vCreateIntersectionShadowFace
		(_p_stGlobalNormal,&_xInvNormalZ,_hPickedObject,_xObjPicked,_xFacePicked,_xPickedElement,_xPickedFace,_p_stPickedPoint,
		&stCharacterRotationX,_p_xTempPoints,_p_xTempFace,_p_xScaleX,_p_xScaleY,_p_xCoefAltitude,&xZc1,&xZc2);
	/*PRF_fn_vStopChrono(PRF_C_ulGLI6, NULL);*/
 
}/*SHW_fn_vCreateShadowOfCharacterOnFace*/
 
 
/* ##F===================================================================================
//NAME :          SHW_fn_vNormalZSort
NAME :          SHW_fn_wNormalZSort
DESCRIPTION :   Test the normal coefficient in Z to determine if the face is drawn or not
=========================================================================================
CREATION : Philippe Thiébaut
MODIFICAION : YLG
=======================================================================================*/
short SHW_fn_wNormalZSort
(
	HIE_tdxHandleToSuperObject	_hPickedSprObject,
	ACP_tdxHandleOfObject		_hPickedObject,
	COL_tdstShadowElement		*_p_stShadowObject,
	MTH3D_tdstVector			*_p_stGlobalNormal
)
{
	MTH3D_tdstVector  vTempLocalNormal;
	
	/*I get the global normal of the face by multiplying the local normal by the rotation matrix*/
	GEO_vGetNormalOfGeometricObjectElement(	_hPickedObject,
											_p_stShadowObject->xElementIndex,
											_p_stShadowObject->xDataElementIndex,
											&vTempLocalNormal);
	
	POS_fn_vRotateVector(_p_stGlobalNormal,HIE_fn_hGetSuperObjectGlobalMatrix(_hPickedSprObject),&vTempLocalNormal);
	
	MTH3D_M_vNormalizeVector(_p_stGlobalNormal,_p_stGlobalNormal);
	
	/*Here the faces are considered as horizontal*/
	if (MTH_M_bGreater(_p_stGlobalNormal->xZ,MTH_M_xFloatToReal(0.3f)))
		return 2;
	/*Here the faces are considered as nearly vertical*/
	else if (MTH_M_bGreater(_p_stGlobalNormal->xZ,MTH_M_xFloatToReal(0.1f)))
		return 1;
	/*Here the faces don't cast any shadow*/
	else return 0;
 
}/*SHW_fn_vNormalZSort*/
 
 
/* ##F===================================================================================
NAME :          SHW_fnvIsThereTooManyFaces
DESCRIPTION :   Return if there is too many faces
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fnvIsThereTooManyFaces(short  *xNbObjPicked)
{
	short       xObjPicked=0;
	ACP_tdxBool bDrawShadowOnlyOnOneObject=FALSE;
	 
	/*PRF_fn_vStartChrono(PRF_C_ulGLI7, NULL);*/
	if (g_a_stShadowInfo[0].xNbElement==SHW_C_xMaxTriangles)
	{
		g_a_stShadowInfo[0].xNbElement=1;
		(*xNbObjPicked)=1;
	}
	else 
	{
		for (xObjPicked=1;xObjPicked<(*xNbObjPicked);xObjPicked++)
		{
			if (g_a_stShadowInfo[xObjPicked].xNbElement==SHW_C_xMaxTriangles) 
				bDrawShadowOnlyOnOneObject=TRUE;
		}
		if (bDrawShadowOnlyOnOneObject) 
				(*xNbObjPicked)=1;
	}
	/*PRF_fn_vStopChrono(PRF_C_ulGLI7, NULL);*/
}
 
/* ##F===================================================================================
NAME :          SHW_fn_vTakeCareOfProjectionVector
DESCRIPTION :
=========================================================================================
CREATION : Yann Le Guyader
=======================================================================================*/
void	SHW_fn_vTakeCareOfProjectionVector
(
	HIE_tdxHandleToSuperObject	_hHandleOfCharacter,
	MTH3D_tdstVector			*_p_stProjectionVector,
	MTH_tdxReal                 *_p_xScaleX,
	MTH_tdxReal                 *_p_xScaleY
)
{
	MTH3D_tdstVector	stLightDir;
	MTH3D_tdstVector	stVectB;
	MTH_tdxReal			xCosX, xCosY;
	MTH_tdxReal			xNormUV;
 
	
	MTH3D_M_vCopyVector(&stLightDir, fn_p_st3dDataGetSHWDeformationVectorFromSO(_hHandleOfCharacter));
	if (MTH3D_M_bIsNullVector(&stLightDir))
	{
		MTH3D_M_vNullVector(&g_stDirOfShadow);
		MTH3D_M_vSetVectorElements(_p_stProjectionVector,MTH_C_ZERO,MTH_C_ZERO,/*MTH_C_MinusONE*/ MTH_M_xFloatToReal(-15.0f));
		*_p_xScaleX = MTH_M_xInv(*_p_xScaleX);
		*_p_xScaleY = MTH_M_xInv(*_p_xScaleY);
		g_bRayIsVertical = TRUE;
	}
	else
	{
 
		MTH3D_M_vSetVectorElements(_p_stProjectionVector,MTH_C_ZERO,MTH_C_ZERO,MTH_C_MinusONE);
 
		if (MTH3D_M_bEqualVector(&stLightDir, _p_stProjectionVector))
			g_bRayIsVertical = TRUE;
		else
			g_bRayIsVertical = FALSE;
 
		MTH3D_M_vCopyVector(&g_stDirOfShadow, &stLightDir);
 
		MTH3D_M_vCopyVector(&stVectB, &g_stDirOfShadow);
		stVectB.xX = MTH_C_ZERO;
		xNormUV = MTH_M_xMul(MTH3D_M_xDotProductVector(_p_stProjectionVector,_p_stProjectionVector),
							MTH3D_M_xDotProductVector(&stVectB, &stVectB));
		/* if U OR V null, set product to 1*/
		if (MTH_M_bIsNull(xNormUV))
			xNormUV= MTH_C_ONE;
		else /* |U|*|V|*/
			xNormUV = MTH_M_xSqrt(xNormUV);
 
		xCosX = MTH_M_xDiv(MTH3D_M_xDotProductVector(_p_stProjectionVector,&stVectB),xNormUV);
		if (!MTH_M_bIsNull(xCosX))
		{
			*_p_xScaleX = MTH_M_xMul(*_p_xScaleX, xCosX);
		}
		*_p_xScaleX = MTH_M_xInv(*_p_xScaleX);
 
		MTH3D_M_vCopyVector(&stVectB, &g_stDirOfShadow);
		stVectB.xY = MTH_C_ZERO;
		xNormUV = MTH_M_xMul(MTH3D_M_xDotProductVector(_p_stProjectionVector,_p_stProjectionVector),
								MTH3D_M_xDotProductVector(&stVectB, &stVectB));
		/* if U OR V null, set product to 1*/
		if (MTH_M_bIsNull(xNormUV))
			xNormUV= MTH_C_ONE;
		else /* |U|*|V|*/
			xNormUV = MTH_M_xSqrt(xNormUV);
		xCosY = MTH_M_xDiv(MTH3D_M_xDotProductVector(_p_stProjectionVector,&stVectB),xNormUV);
		if (!MTH_M_bIsNull(xCosY))
		{
			*_p_xScaleY = MTH_M_xMul(*_p_xScaleY, xCosY);
		}
		*_p_xScaleY = MTH_M_xInv(*_p_xScaleY);
 
		g_stDirOfShadow.xZ = MTH_C_ZERO;
		MTH3D_M_vCopyVector(_p_stProjectionVector, &stLightDir);
	}
}
 
 
/* ##F===================================================================================
NAME :          SHW_fn_vDrawShadow
DESCRIPTION :   Draw a Fake Shadow for a Character
=========================================================================================
CREATION : Philippe Thiébaut
=======================================================================================*/
void SHW_fn_vDrawComplexShadow
(
	struct GLD_tdstViewportAttributes_		*_p_stVpt,
	HIE_tdxHandleToSuperObject				_hHandleOfCharacter,
	HIE_tdxHandleToSuperObject				_hSprObjSector,
	long									_lSectorDrawmask
)
{
	ACP_tdxIndex					xResultIntersection = 0;
	ACP_tdxIndex					xTempPoints=0,xTempFace=0;
	short							xFacePicked=0,xObjPicked=0;
	MTH3D_tdstVector                stGlobalNormalOfPickedFace;
	GEO_tdxHandleToMatrix           hGlobalMatrixOfCharacter=NULL;
	MTH_tdxReal                     xCoefAltitude;
	short                           xIndexOfCalculatedShadow;
	GEO_tdstElementIndexedTriangles	*p_stIndexedTriangle;
	MTH_tdxReal                     xScaleX;
	MTH_tdxReal                     xScaleY;
	SHW_tdstShadowInfo				*p_stShadowInfo=NULL;
	MTH3D_tdstVector				*p_stGlobalNormal=NULL;
	COL_tdstShadowElement			*p_stShadowElement=NULL;
	ACP_tdxHandleOfObject			hHandleOfGeometricShadowObject = NULL;
	ACP_tdxIndex					xNbElement;
	short							*p_bDrawFace;
	MTH_tdxReal						xHeight;
	HIE_tdxHandleToSuperObject		hTest,hSprObjSector;
	
	
	g_hHandleOfFather = NULL;
	g_bIsOnGround = FALSE;
	g_bFirstFace = TRUE;
	
 
	hGlobalMatrixOfCharacter=HIE_fn_hGetSuperObjectGlobalMatrix(_hHandleOfCharacter);
	POS_fn_vGetTranslationVector(hGlobalMatrixOfCharacter, &g_stStartPicking ) ;
	
	hHandleOfGeometricShadowObject = p_hHandleOfGeometricShadowObject[g_xIndexOfShadow];
	
	xScaleX = MTH_M_xAbs(fn_x3dDataGetShadowScaleXFromSO(_hHandleOfCharacter));
	xScaleY = MTH_M_xAbs(fn_x3dDataGetShadowScaleYFromSO(_hHandleOfCharacter));
	
 
	POS_fn_vSetIdentityMatrix(&g_stInvertCurrentMatrix);
	
	g_shNbObjPicked=0;
	g_hPickedSprObj = NULL;
	g_xPickedElement=0;
	g_xPickedFace=0;
	/*
	*	complete calculation
	*/
	g_xNearDistance= MTH_M_xMax(xScaleX,xScaleY);
	
	SHW_fn_vTakeCareOfProjectionVector(_hHandleOfCharacter,&g_stVertexAB,&xScaleX,&xScaleY);
	xHeight = *fn_p_x3dDataGetSHWHeightFromSO(_hHandleOfCharacter);
	
	g_stStartPicking.xZ=MTH_M_xAdd(g_stStartPicking.xZ, xHeight);
	MTH3D_M_vAddVector(&g_stVertexB,&g_stStartPicking,&g_stVertexAB);
	if (
		SHW_fn_bIntersectShadowWithUnknownObjectBelow
		(
		_hSprObjSector,
		_hHandleOfCharacter,
		_p_stVpt
		)
		)
	{
		/*Formula for scale*/
		xCoefAltitude=MTH_M_xAdd(MTH_C_Inv2,MTH_M_xMul(MTH_M_xFloatToReal(0.03f),MTH_M_xSub(g_stStartPicking.xZ,g_stPickedPoint.xZ)));
		MTH3D_M_vCopyVector(&g_stStartPicking, &g_stPickedPoint);
		
		/*Test if there are too many faces around the picked point*/
		SHW_fnvIsThereTooManyFaces(&g_shNbObjPicked);
		
		p_stShadowInfo = g_a_stShadowInfo;
		for ( xObjPicked=0;xObjPicked<g_shNbObjPicked;xObjPicked++, p_stShadowInfo++)
		{
			xNbElement = p_stShadowInfo->xNbElement;
			p_bDrawFace = &p_stShadowInfo->bDrawFace[0];
			p_stShadowElement = p_stShadowInfo->a_stShadowObject;
			p_stGlobalNormal = p_stShadowInfo->pstGlobalNormal;
			
			if (xNbElement >= SHW_C_xNbMaxOfFacesPerShadow)
				xNbElement = SHW_C_xNbMaxOfFacesPerShadow;
			
			for ( xFacePicked=0;xFacePicked<xNbElement;xFacePicked++, p_bDrawFace++, p_stShadowElement++, p_stGlobalNormal++)
			{
				
				if ((*p_bDrawFace=SHW_fn_wNormalZSort( p_stShadowInfo->hPickedSpObj, p_stShadowInfo->hPickedObject, p_stShadowElement, p_stGlobalNormal))!=0)
				{
					MTH_tdxReal xInvNormalZ;
					
					xInvNormalZ=MTH_M_xDiv(MTH_C_ONE,p_stGlobalNormal->xZ);
					SHW_fn_vCreateShadowOfCharacterOnFace
						(
						p_stGlobalNormal,
						xInvNormalZ,
						_hHandleOfCharacter,
						p_stShadowInfo->hPickedObject,
						xObjPicked,
						xFacePicked,
						p_stShadowElement->xElementIndex,
						p_stShadowElement->xDataElementIndex,
						&g_stPickedPoint,&xTempPoints,&xTempFace,&xCoefAltitude,
						&xScaleX,&xScaleY
						);
					
					
				}/*if (g_a_stShadowInfo[xObjPicked].bDrawFace[xFacePicked]!=0)*/
			}/*for*/
		}/*for*/
		
		hHandleOfGeometricShadowObject->xNbPoints=xTempPoints;
		p_stIndexedTriangle = (GEO_tdstElementIndexedTriangles *)hHandleOfGeometricShadowObject->d_stListOfElements[0];
		p_stIndexedTriangle->xNbFaces=xTempFace;
		if (xTempPoints!=0)
		{
			SHW_fn_vSentToViewPort(_p_stVpt,_hHandleOfCharacter,_hSprObjSector,_lSectorDrawmask,hHandleOfGeometricShadowObject);
		}/*(xTempPoints!=0)*/
		
		g_xIndexOfShadow++;
	}
}
 
 
