2137 lines
76 KiB
C++
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++;
|
|
}
|
|
}
|
|
|
|
|