reman3/Rayman_X/cpa/tempgrp/SHW/shaddraw.cxx

2137 lines
76 KiB
C++

/* ##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++;
}
}