845 lines
26 KiB
C
845 lines
26 KiB
C
/*
|
|
*=======================================================================================
|
|
* Name : MecCol.c
|
|
* Author : J Thénoz Date : 01/05/98
|
|
* Description : Mechanic collision functions
|
|
*=======================================================================================
|
|
*/
|
|
#include "cpa_expt.h"
|
|
#include "ACP_Base.h"
|
|
|
|
|
|
#include "MEC/MECInc.h"
|
|
#include "MEC/DnmDynam.h"
|
|
#include "MEC/ParsData.h"
|
|
#include "MEC/DNMSurSt.h"
|
|
#include "MEC/mbase.h"
|
|
#include "Extheade.h"
|
|
#include "COL.h"
|
|
#include "MEC/MecDef.h"
|
|
#include "MEC/MECCol.h"
|
|
#include "MEC/MECTools.h"
|
|
|
|
#include "PCS.h" /* Physical Collide Set */
|
|
#include "SCT.h" /* SeCTor*/
|
|
#include "FIL.h" /* SeCTor*/
|
|
#include "PRT.h" /* PaRTicules*/
|
|
#include "GAM.h" /* GAMe*/
|
|
|
|
|
|
//DNM_tdstMecObstacle g_a_stObstacle [COL_C_xMaxNumberOfCollisions];
|
|
DNM_tdstMecObstacle *g_a_stObstacle = (DNM_tdstMecObstacle *) COL_g_stCollisionCase;
|
|
ACP_tdxBool g_bWaterNoCollide;
|
|
|
|
ACP_tdxBool MEC_fn_bCollision ( long* p_lObstacle, DNM_tdstMecObstacle *p_stObstacle, struct DNM_stDynamics* p_stDynamic, HIE_tdxHandleToSuperObject p_stSupObj, POS_tdstCompletePosition *p_stStartPosition, POS_tdstCompletePosition *p_stEndPosition, ACP_tdxBool bBackFace )
|
|
{
|
|
long lCounter;
|
|
DNM_tdstMecObstacle *p_stTmpObstacle;
|
|
DNM_tdstMecObstacle stHandObstacle;
|
|
POS_tdxHandleToPosition hSupObjMatrix;
|
|
MTH3D_tdstVector stMove, stVector;
|
|
MTH3D_tdstVector *p_stStartTranslation, *p_stEndTranslation;
|
|
MTH3D_tdstVector *p_stX, *p_stY, *p_stZ;
|
|
/* XB 05/05/99 */
|
|
/* ACP_tdxBool bIndexedTriangles = FALSE; */
|
|
/* End XB 05/05/99 */
|
|
ACP_tdxBool bObstacleOk = FALSE;
|
|
MTH_tdxReal xDotProd;
|
|
ACP_tdxBool bWaterFace = FALSE;
|
|
MTH_tdxReal xDotProdMax;
|
|
|
|
*p_lObstacle = 0;
|
|
xDotProdMax = MTH_C_MinusONE;
|
|
|
|
*p_lObstacle = COL_lHaveITakeSThgIntoTheMug (p_stObstacle, p_stSupObj, p_stStartPosition, p_stEndPosition);
|
|
|
|
/* delete back faces */
|
|
if (!bBackFace) MEC_fn_vDeleteBaseBackFace ( *p_lObstacle,p_stObstacle, p_stDynamic );
|
|
|
|
MEC_fn_vDeleteNoCollidedGroundFace (*p_lObstacle,p_stObstacle,p_stDynamic);
|
|
|
|
if (*p_lObstacle<=0) return FALSE;
|
|
|
|
if (DNM_M_bDynamicsIsHanging(p_stDynamic))
|
|
MEC_fn_vDeleteHangingObstacle (*p_lObstacle,p_stObstacle,p_stDynamic);
|
|
|
|
p_stStartTranslation = POS_fn_p_stGetTranslationVector (p_stStartPosition);
|
|
p_stEndTranslation = POS_fn_p_stGetTranslationVector (p_stEndPosition);
|
|
MTH3D_M_vSubVector ( &stMove, p_stStartTranslation, p_stEndTranslation );
|
|
|
|
MEC_fn_vComputeCollisionTranslation (*p_lObstacle,p_stObstacle,&stMove);
|
|
|
|
hSupObjMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(p_stSupObj);
|
|
POS_fn_vGetRotationVector ( hSupObjMatrix, &p_stX, &p_stY, &p_stZ );
|
|
|
|
for (lCounter=0; lCounter<*p_lObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = p_stObstacle+lCounter;
|
|
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
|
|
ACP_tdxBool bCollisionOk = TRUE;
|
|
|
|
/* hands */
|
|
if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetMyMaterial(p_stTmpObstacle),C_xDNM_HAND_TYPE_GAME_MATERIAL))
|
|
{
|
|
bCollisionOk = FALSE;
|
|
if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_HANG_TYPE_GAME_MATERIAL) )
|
|
{
|
|
/* collide only hand with ground */
|
|
if (MEC_fn_bGroundObstacle(p_stDynamic,p_stTmpObstacle))
|
|
{
|
|
/* choose best hand obstacle */
|
|
MTH3D_M_vSubVector (&stVector,DNM_M_p_stObstacleGetContact(p_stTmpObstacle),POS_fn_p_stGetTranslationVector(hSupObjMatrix));
|
|
if (!MEC_fn_bIsNullVector(&stVector))
|
|
MTH3D_M_vNormalizeVector (&stVector,&stVector);
|
|
|
|
xDotProd = MTH_M_xAbs(MTH3D_M_xDotProductVector (p_stY,&stVector));
|
|
if (xDotProd>xDotProdMax)
|
|
{
|
|
xDotProdMax = xDotProd;
|
|
DNM_M_MecObstacleCopyClone ( &stHandObstacle, p_stTmpObstacle );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* water */
|
|
else if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_WATER_TYPE_GAME_MATERIAL))
|
|
{
|
|
if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetMyMaterial(p_stTmpObstacle),C_xDNM_WATER_TYPE_GAME_MATERIAL))
|
|
{
|
|
|
|
if (!bWaterFace)
|
|
{
|
|
|
|
/* delete water back face */
|
|
xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stTmpObstacle),DNM_M_pObstacleGetZoneMove(p_stTmpObstacle) );
|
|
|
|
if ( MTH_M_bGreater ( MTH_M_xAbs ( MTH3D_M_xGetZofVector (DNM_M_pObstacleGetZoneMove(p_stTmpObstacle))), 0.03 ) )
|
|
{
|
|
if ( MTH_M_bLess(xDotProd, MTH_C_ZERO) )
|
|
{
|
|
MEC_fn_vReportCollision (p_stDynamic, p_stSupObj, 1, p_stTmpObstacle, 0);
|
|
/* the obstacle is used for repositionning only if required*/
|
|
bCollisionOk = fn_bBrainWaterCollideSO(p_stSupObj);
|
|
if (!bCollisionOk)
|
|
g_bWaterNoCollide = TRUE;
|
|
bWaterFace = TRUE;
|
|
}
|
|
else
|
|
bCollisionOk = FALSE;
|
|
}
|
|
else
|
|
{
|
|
|
|
|
|
MTH3D_M_vSubVector ( &stVector, DNM_M_p_stObstacleGetContact(p_stTmpObstacle), DNM_M_pObstacleGetZonePosition(p_stTmpObstacle) );
|
|
MTH3D_M_vAddVector ( &stVector, &stVector, DNM_M_pObstacleGetZoneMove(p_stTmpObstacle) );
|
|
|
|
xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stTmpObstacle),&stVector );
|
|
|
|
if (MTH_M_bLessEqual(xDotProd,MTH_C_ZERO))
|
|
{
|
|
MEC_fn_vReportCollision (p_stDynamic, p_stSupObj, 1, p_stTmpObstacle, 0);
|
|
bCollisionOk = fn_bBrainWaterCollideSO(p_stSupObj);
|
|
if (!bCollisionOk)
|
|
g_bWaterNoCollide = TRUE;
|
|
bWaterFace = TRUE;
|
|
}
|
|
else
|
|
bCollisionOk = FALSE;
|
|
}
|
|
|
|
if (MTH_M_bGreater(MTH3D_M_xGetZofVector(DNM_M_p_stObstacleGetNorm(p_stTmpObstacle)),MTH_C_ZERO))
|
|
bCollisionOk = FALSE;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
bCollisionOk = FALSE;
|
|
}
|
|
|
|
}
|
|
else /*we do not report the collision because it does not exist: do not use the obstable for repositionning*/
|
|
bCollisionOk = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
/* No collision faces */
|
|
if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_NO_COLLISION_TYPE_GAME_MATERIAL))
|
|
{
|
|
/* Climb faces */
|
|
if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_CLIMB_TYPE_GAME_MATERIAL))
|
|
bCollisionOk = DNM_M_bDynamicsIsClimb(p_stDynamic);
|
|
|
|
/* Gi faces */
|
|
else if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_GI_TYPE_GAME_MATERIAL))
|
|
bCollisionOk = DNM_M_bDynamicsIsGi(p_stDynamic);
|
|
|
|
/* Other faces */
|
|
else if (MEC_fn_bTestMaskGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_COLLISION_REPORT_MASK))
|
|
{
|
|
bCollisionOk=FALSE;
|
|
MEC_fn_vReportCollision (p_stDynamic, p_stSupObj, 1, p_stTmpObstacle, 0);
|
|
}
|
|
|
|
/* no report */
|
|
else bCollisionOk=FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
if (!bCollisionOk) MEC_fn_vInvalidateObstacle(p_stTmpObstacle);
|
|
else bObstacleOk=TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
/* report hand obstacle */
|
|
if (xDotProdMax != MTH_C_MinusONE)
|
|
MEC_fn_vReportCollision (p_stDynamic, p_stSupObj, 1, &stHandObstacle, 0);
|
|
|
|
return bObstacleOk;
|
|
}
|
|
|
|
|
|
|
|
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
|
|
ACP_tdxBool MEC_fn_bInCollision ( struct DNM_stDynamics *p_stDynamic, HIE_tdxHandleToSuperObject hSupObj )
|
|
{
|
|
/* DNM_tdstMecObstacle a_stObstacle[COL_C_xMaxNumberOfCollisions];*/
|
|
POS_tdxHandleToPosition hCurrentMatrix;
|
|
POS_tdxHandleToPosition hPreviousMatrix;
|
|
|
|
hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
|
|
hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
|
|
|
|
return COL_lHaveITakeSThgIntoTheMug (g_a_stObstacle, hSupObj, hPreviousMatrix, hCurrentMatrix) > 0;
|
|
}
|
|
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
|
|
|
|
|
|
|
|
|
|
|
|
/* report collide actor */
|
|
void MEC_fn_vReportCollideActor (HIE_tdxHandleToSuperObject hCollideSupObj,DNM_tdstMecObstacle* p_stCollideObstacle)
|
|
{
|
|
struct DNM_stDynamics* p_stDynamic;
|
|
DNM_tdstObstacle* p_stObstacle;
|
|
MTH3D_tdstVector stVector;
|
|
HIE_tdxHandleToSuperObject hSupObj;
|
|
|
|
hSupObj = DNM_M_p_stObstacleGetObject (p_stCollideObstacle);
|
|
|
|
if (!HIE_fn_bIsSuperObjectValid(hSupObj)) return;
|
|
hSupObj = MEC_fn_hGetFatherActor (hSupObj);
|
|
|
|
p_stDynamic= fn_p_stDynamGetDynamicsSO (hSupObj);
|
|
if (!p_stDynamic) return;
|
|
|
|
/* no report so nothing to do here */
|
|
if (!DNM_M_bDynamicsIsCollisionReport(p_stDynamic)) return;
|
|
|
|
/* flag */
|
|
DNM_M_ulReportAddSurfaceState (DNM_M_p_stDynamicsGetReport(p_stDynamic),C_WOT_ulForceMobile);
|
|
|
|
/* obstacle */
|
|
p_stObstacle = DNM_M_p_stReportGetCharacter ( DNM_M_p_stDynamicsGetReport(p_stDynamic) );
|
|
DNM_M_xObstacleSetRate (p_stObstacle,0);
|
|
MTH3D_M_vNegVector (&stVector,DNM_M_p_stObstacleGetNorm(p_stCollideObstacle));
|
|
DNM_M_ObstacleSetNorm (p_stObstacle,&stVector);
|
|
DNM_M_ObstacleSetContact (p_stObstacle,DNM_M_p_stObstacleGetContact(p_stCollideObstacle));
|
|
DNM_M_p_stObstacleSetObject (p_stObstacle,hCollideSupObj);
|
|
DNM_M_vObstacleSetCollidedMaterial (p_stObstacle,DNM_M_hObstacleGetMyMaterial(p_stCollideObstacle));
|
|
DNM_M_vObstacleSetMyMaterial (p_stObstacle,DNM_M_hObstacleGetCollidedMaterial(p_stCollideObstacle));
|
|
}
|
|
|
|
|
|
|
|
/* report collision */
|
|
void MEC_fn_vReportCollision
|
|
(
|
|
struct DNM_stDynamics* p_stDynamic,
|
|
HIE_tdxHandleToSuperObject hSupObj,
|
|
long lNbObstacle,
|
|
DNM_tdstMecObstacle a_stObstacle[COL_C_xMaxNumberOfCollisions],
|
|
long lObstacle
|
|
)
|
|
{
|
|
MTH_tdxReal xDotProduct;
|
|
MTH_tdxReal xPreviousRate, xCurrentRate;
|
|
MTH3D_tdstVector stVerticalVector;
|
|
MTH3D_tdstVector* p_stNormalVector;
|
|
DNM_tdstMecObstacle* p_stTmpObstacle = NULL;
|
|
long lCounter;
|
|
ACP_tdxBool bStop = FALSE;
|
|
ACP_tdxBool bHurt = FALSE;
|
|
|
|
ACP_tdxBool bObstacle = FALSE;
|
|
ACP_tdxBool bCeil = FALSE;
|
|
ACP_tdxBool bWall = FALSE;
|
|
ACP_tdxBool bGround = FALSE;
|
|
ACP_tdxBool bActor = FALSE;
|
|
ACP_tdxBool bWater = FALSE;
|
|
|
|
ACP_tdxBool bObstacleEdge;
|
|
ACP_tdxBool bCeilEdge;
|
|
ACP_tdxBool bWallEdge;
|
|
ACP_tdxBool bGroundEdge;
|
|
ACP_tdxBool bActorEdge;
|
|
ACP_tdxBool bWaterEdge;
|
|
|
|
|
|
ACP_tdxBool bEdge;
|
|
|
|
MTH3D_M_vSetVectorElements (&stVerticalVector, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE);
|
|
xPreviousRate = MTH_C_2;
|
|
|
|
for (lCounter=0; lCounter<lNbObstacle && !bStop; lCounter++)
|
|
{
|
|
p_stTmpObstacle = a_stObstacle + lCounter;
|
|
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
xCurrentRate = DNM_M_xObstacleGetRate (p_stTmpObstacle);
|
|
|
|
if ( lCounter<=lObstacle || MTH_M_bEqual(xPreviousRate,xCurrentRate) )
|
|
{
|
|
p_stNormalVector = DNM_M_p_stObstacleGetNorm (p_stTmpObstacle);
|
|
bEdge = MEC_fn_bIsEdge (p_stTmpObstacle);
|
|
xPreviousRate = xCurrentRate;
|
|
|
|
|
|
/* obstacle */
|
|
if (!bObstacle)
|
|
{
|
|
DNM_M_MecReportSetObstacle (&g_stReport, p_stTmpObstacle);
|
|
bObstacleEdge = bEdge;
|
|
bObstacle = TRUE;
|
|
}
|
|
else if (bObstacleEdge && !bEdge)
|
|
{
|
|
DNM_M_MecReportSetObstacle (&g_stReport, p_stTmpObstacle);
|
|
bObstacleEdge = FALSE;
|
|
}
|
|
|
|
|
|
/* actor */
|
|
if
|
|
(
|
|
((DNM_M_eObstacleGetType(p_stTmpObstacle) & DNM_ObsType_Mobile) == DNM_ObsType_Mobile )
|
|
|| ((DNM_M_eObstacleGetType(p_stTmpObstacle) & DNM_ObsType_MobileWall) == DNM_ObsType_MobileWall )
|
|
)
|
|
{
|
|
if (!bActor)
|
|
{
|
|
DNM_M_MecReportSetCharacter (&g_stReport,p_stTmpObstacle);
|
|
bActorEdge = bEdge;
|
|
bActor = TRUE;
|
|
}
|
|
else if (bActorEdge && !bEdge)
|
|
{
|
|
DNM_M_MecReportSetCharacter (&g_stReport,p_stTmpObstacle);
|
|
bActorEdge = FALSE;
|
|
}
|
|
}
|
|
|
|
/* water */
|
|
if
|
|
(
|
|
(
|
|
MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_WATER_TYPE_GAME_MATERIAL)
|
|
&& MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetMyMaterial(p_stTmpObstacle),C_xDNM_WATER_TYPE_GAME_MATERIAL)
|
|
)
|
|
||
|
|
(
|
|
MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_NO_COLLISION_TYPE_GAME_MATERIAL)
|
|
&& MEC_fn_bTestMaskGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_COLLISION_REPORT_MASK)
|
|
)
|
|
)
|
|
{
|
|
/* water and no_collionable material are reported as water obstacles */
|
|
if (!bWater)
|
|
{
|
|
DNM_M_MecReportSetWater (&g_stReport,p_stTmpObstacle);
|
|
bWaterEdge = bEdge;
|
|
bWater = TRUE;
|
|
}
|
|
else if (bWaterEdge && !bEdge)
|
|
{
|
|
DNM_M_MecReportSetWater (&g_stReport,p_stTmpObstacle);
|
|
bWaterEdge = FALSE;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
/* search collision type : wall or ground ? */
|
|
xDotProduct = MTH3D_M_xDotProductVector ( p_stNormalVector, &stVerticalVector );
|
|
|
|
if (xDotProduct>MEC_fn_xGroundLimit(p_stDynamic) )
|
|
{
|
|
/* ground */
|
|
if (!bGround)
|
|
{
|
|
DNM_M_MecReportSetGround (&g_stReport,p_stTmpObstacle);
|
|
bGroundEdge = bEdge;
|
|
bGround = TRUE;
|
|
}
|
|
else if (bGroundEdge && !bEdge)
|
|
{
|
|
DNM_M_MecReportSetGround (&g_stReport,p_stTmpObstacle);
|
|
bGroundEdge = FALSE;
|
|
}
|
|
}
|
|
|
|
else if (xDotProduct>MEC_fn_xWallLimit(p_stDynamic))
|
|
{
|
|
/* wall */
|
|
if (!bWall)
|
|
{
|
|
DNM_M_MecReportSetWall (&g_stReport,p_stTmpObstacle);
|
|
bWallEdge = bEdge;
|
|
bWall = TRUE;
|
|
}
|
|
else if (bWallEdge && !bEdge)
|
|
{
|
|
DNM_M_MecReportSetWall (&g_stReport,p_stTmpObstacle);
|
|
bWallEdge = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* ceil */
|
|
if (!bCeil)
|
|
{
|
|
DNM_M_MecReportSetCeil (&g_stReport,p_stTmpObstacle);
|
|
bCeilEdge = bEdge;
|
|
bCeil = TRUE;
|
|
}
|
|
else if (bCeilEdge && !bEdge)
|
|
{
|
|
DNM_M_MecReportSetCeil (&g_stReport,p_stTmpObstacle);
|
|
bCeilEdge = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else bStop=TRUE;
|
|
}
|
|
}
|
|
|
|
if (bActor)
|
|
{
|
|
DNM_M_ulReportAddSurfaceState (&g_stReport,C_WOT_ulMobile);
|
|
MEC_fn_vReportCollideActor (hSupObj,DNM_M_p_stReportGetCharacter(&g_stReport));
|
|
}
|
|
|
|
if (bWater)
|
|
DNM_M_ulReportAddSurfaceState (&g_stReport,C_WOT_ulWater);
|
|
|
|
if (bGround)
|
|
{
|
|
DNM_M_ulReportAddSurfaceState (&g_stReport,C_WOT_ulGround);
|
|
if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic)) DNM_M_vDynamicsSetGroundNormal (p_stDynamic,DNM_M_p_stObstacleGetNorm(DNM_M_p_stReportGetGround(&g_stReport)));
|
|
}
|
|
|
|
if (bWall)
|
|
{
|
|
DNM_M_ulReportAddSurfaceState (&g_stReport,C_WOT_ulWall);
|
|
if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic)) DNM_M_vDynamicsSetWallNormal (p_stDynamic,DNM_M_p_stObstacleGetNorm(DNM_M_p_stReportGetWall(&g_stReport)));
|
|
}
|
|
|
|
if (bCeil)
|
|
DNM_M_ulReportAddSurfaceState (&g_stReport,C_WOT_ulCeiling);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MEC_fn_vFillCollisionReport
|
|
(
|
|
struct DNM_stDynamics* p_stDynamic
|
|
)
|
|
{
|
|
DNM_tdstReport* p_stReport;
|
|
|
|
if (!DNM_M_bDynamicsIsCollisionReport(p_stDynamic)) return;
|
|
if (DNM_M_ulReportGetSurfaceState(&g_stReport)==0) return;
|
|
|
|
p_stReport = DNM_M_p_stDynamicsGetReport (p_stDynamic);
|
|
|
|
DNM_M_ReportSetObstacle ( p_stReport, DNM_M_p_stReportGetObstacle(&g_stReport) );
|
|
|
|
if ( DNM_M_ulReportGetSurfaceState(&g_stReport) & C_WOT_ulMobile )
|
|
{
|
|
DNM_M_ulReportAddSurfaceState (p_stReport,C_WOT_ulMobile);
|
|
DNM_M_ReportSetCharacter ( p_stReport, DNM_M_p_stReportGetCharacter(&g_stReport) );
|
|
}
|
|
|
|
if ( DNM_M_ulReportGetSurfaceState(&g_stReport) & C_WOT_ulWater )
|
|
{
|
|
DNM_M_ulReportAddSurfaceState (p_stReport,C_WOT_ulWater);
|
|
DNM_M_ReportSetWater ( p_stReport, DNM_M_p_stReportGetWater(&g_stReport) );
|
|
}
|
|
|
|
if ( DNM_M_ulReportGetSurfaceState(&g_stReport) & C_WOT_ulGround )
|
|
{
|
|
DNM_M_ulReportAddSurfaceState (p_stReport,C_WOT_ulGround);
|
|
DNM_M_ReportSetGround ( p_stReport, DNM_M_p_stReportGetGround(&g_stReport) );
|
|
}
|
|
|
|
if ( DNM_M_ulReportGetSurfaceState(&g_stReport) & C_WOT_ulWall )
|
|
{
|
|
DNM_M_ulReportAddSurfaceState (p_stReport,C_WOT_ulWall);
|
|
DNM_M_ReportSetWall ( p_stReport, DNM_M_p_stReportGetWall(&g_stReport) );
|
|
}
|
|
|
|
if ( DNM_M_ulReportGetSurfaceState(&g_stReport) & C_WOT_ulCeiling )
|
|
{
|
|
DNM_M_ulReportAddSurfaceState (p_stReport,C_WOT_ulCeiling);
|
|
DNM_M_ReportSetCeil ( p_stReport, DNM_M_p_stReportGetCeil(&g_stReport) );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
ACP_tdxBool MEC_fn_vComputeAdjustVector (MTH3D_tdstVector *p_stAdjustVector, struct DNM_stDynamics* p_stDynamic, long lObstacle, DNM_tdstMecObstacle *p_stObstacle, long lObstacleMin)
|
|
{
|
|
long lCounter;
|
|
DNM_tdeObstacleType xObstacleType;
|
|
ACP_tdxBool bAdjustVector = FALSE;
|
|
/* XB 05/05/99 */
|
|
/* ACP_tdxBool bJustOneDynamic = TRUE; */
|
|
/* End XB 05/05/99 */
|
|
ACP_tdxBool bContinue;
|
|
ACP_tdxBool bConflict = FALSE;
|
|
/* XB 05/05/99 */
|
|
/* ACP_tdxBool bMobileWall = FALSE; */
|
|
/* End XB 05/05/99 */
|
|
|
|
DNM_tdstMecObstacle* p_stTmpObstacle, *p_stWaterObstacle;
|
|
MTH_tdxReal xDotProd;
|
|
MTH3D_tdstVector stNormalAdjustVector, stTangentAdjustVector, stVector;
|
|
MTH3D_tdstVector stAdjustAxis;
|
|
|
|
p_stWaterObstacle = NULL;
|
|
MTH3D_M_vNullVector (p_stAdjustVector);
|
|
|
|
for (lCounter=0; lCounter<lObstacle && !p_stWaterObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = p_stObstacle+lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle) && MEC_fn_bIsWater(p_stTmpObstacle))
|
|
p_stWaterObstacle = p_stTmpObstacle;
|
|
}
|
|
|
|
for (xObstacleType=DNM_ObsType_Scenery; xObstacleType<=DNM_ObsType_Mobile; xObstacleType++)
|
|
{
|
|
bContinue=TRUE;
|
|
|
|
for (lCounter=0; lCounter<lObstacle && bContinue; lCounter++)
|
|
{
|
|
p_stTmpObstacle = p_stObstacle+lCounter;
|
|
|
|
if ( (DNM_M_eObstacleGetType(p_stTmpObstacle) & xObstacleType) == xObstacleType )
|
|
{
|
|
if ( lCounter<=lObstacleMin || MEC_fn_bIsCollide(p_stTmpObstacle) )
|
|
{
|
|
if ( MEC_fn_bIsObstacleValid(p_stTmpObstacle) && !MEC_fn_bIsWater(p_stTmpObstacle) /*&& MTH_M_bDifferentZero(DNM_M_xObstacleGetRate(p_stTmpObstacle))*/ )
|
|
{
|
|
if (bAdjustVector)
|
|
{
|
|
MTH3D_M_vCopyVector (&stVector,DNM_M_xObstacleGetTranslation(p_stTmpObstacle));
|
|
if (!MEC_fn_bIsNullVector(p_stAdjustVector)) MTH3D_M_vNormalizeVector (&stAdjustAxis,p_stAdjustVector)
|
|
else MTH3D_M_vCopyVector (&stAdjustAxis,p_stAdjustVector);
|
|
|
|
xDotProd = MTH3D_M_xDotProductVector (&stAdjustAxis,&stVector);
|
|
|
|
// if (MTH_M_bLess(xDotProd,MTH_C_ZERO))
|
|
// if (MTH_M_bLess(xDotProd,MTH_C_MinusInv2))
|
|
// bConflict = TRUE;
|
|
|
|
// if (MTH_M_bGreater(xDotProd,MTH_C_MinusInv2))
|
|
if (MTH_M_bGreater(xDotProd,MTH_C_ZERO))
|
|
{
|
|
if (MTH_M_bLess(xDotProd,MTH3D_M_xNormVector(p_stAdjustVector)))
|
|
{
|
|
MTH3D_M_vMulScalarVector (&stNormalAdjustVector,xDotProd,&stAdjustAxis);
|
|
MTH3D_M_vSubVector (&stTangentAdjustVector,&stVector,&stNormalAdjustVector);
|
|
MTH3D_M_vAddVector (p_stAdjustVector, p_stAdjustVector, &stTangentAdjustVector );
|
|
}
|
|
else
|
|
{
|
|
MTH3D_M_vCopyVector (p_stAdjustVector,&stVector);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bConflict = TRUE;
|
|
if (xObstacleType==DNM_ObsType_Scenery)
|
|
{
|
|
MTH3D_M_vMulScalarVector (&stNormalAdjustVector,xDotProd,&stAdjustAxis);
|
|
MTH3D_M_vSubVector (&stTangentAdjustVector,&stVector,&stNormalAdjustVector);
|
|
MTH3D_M_vAddVector (p_stAdjustVector, p_stAdjustVector, &stTangentAdjustVector );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MTH3D_M_vCopyVector (p_stAdjustVector,DNM_M_xObstacleGetTranslation(p_stTmpObstacle));
|
|
bAdjustVector = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else bContinue=FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* adjust actor position under water*/
|
|
if (p_stWaterObstacle)
|
|
{
|
|
MTH3D_M_vNormalizeVector (&stAdjustAxis,DNM_M_p_stObstacleGetNorm(p_stWaterObstacle));
|
|
xDotProd = MTH3D_M_xDotProductVector ( &stAdjustAxis, p_stAdjustVector );
|
|
MTH3D_M_vMulScalarVector (&stNormalAdjustVector,MTH_M_xSub(xDotProd,MTH_M_xDoubleToReal(0.01)),&stAdjustAxis);
|
|
MTH3D_M_vSubVector (p_stAdjustVector,p_stAdjustVector,&stNormalAdjustVector);
|
|
MTH3D_M_vAddVector (p_stAdjustVector,p_stAdjustVector,DNM_M_xObstacleGetTranslation(p_stWaterObstacle));
|
|
}
|
|
|
|
return !bConflict;
|
|
}
|
|
|
|
|
|
void MEC_fn_vEdgeAnalysis ( struct DNM_stDynamics *p_stDynamic, long lObstacle, DNM_tdstMecObstacle *p_stObstacle, DNM_tdstMecObstacle *p_stGround )
|
|
{
|
|
long lCounter;
|
|
MTH3D_tdstVector stContact, stVector, stEdgeVector, stVector1;
|
|
DNM_tdstMecObstacle *p_stTmpObstacle;
|
|
DNM_tdstMecObstacle *p_stNotGround = NULL;
|
|
/* XB 05/05/99 */
|
|
/* ACP_tdxBool bGround = FALSE; */
|
|
/* End XB 05/05/99 */
|
|
ACP_tdxBool bNotGround = FALSE;
|
|
|
|
long lGround = 0;
|
|
|
|
MTH_tdxReal xDotProd;
|
|
/* XB 05/05/99 */
|
|
/* ACP_tdxBool bCanFall = FALSE; */
|
|
/* End XB 05/05/99 */
|
|
|
|
DNM_M_bDynamicsSetCanFall (p_stDynamic,FALSE);
|
|
|
|
|
|
/* no ground*/
|
|
if ( !p_stGround )
|
|
{
|
|
/* there is no ground pass to the function, so we continue as we have always done */
|
|
|
|
|
|
/* if there is no ground edge in the obstacles, we cannot fall (but what about no ground obstacle at all ?)*/
|
|
for
|
|
(
|
|
lCounter = 0, p_stTmpObstacle = p_stObstacle;
|
|
lCounter < lObstacle && !p_stGround;
|
|
lCounter ++, p_stTmpObstacle ++
|
|
)
|
|
{
|
|
if ( MEC_fn_bIsObstacleValid(p_stTmpObstacle) && MEC_fn_bGroundObstacle(p_stDynamic,p_stTmpObstacle) )
|
|
{
|
|
if ( MEC_fn_bIsEdge(p_stTmpObstacle) )
|
|
{
|
|
p_stGround = p_stTmpObstacle; /*record the obstacle we found too...*/
|
|
}
|
|
else return;
|
|
}
|
|
}
|
|
|
|
if (!p_stGround)
|
|
return;
|
|
|
|
}
|
|
else
|
|
{
|
|
/* we can only fall if current ground obsacle is an edge */
|
|
if ( !MEC_fn_bIsEdge(p_stGround) )
|
|
return;
|
|
}
|
|
|
|
/* ground is a double-edge*/
|
|
if (MEC_fn_bIsDoubleEdge(p_stGround)) return;
|
|
|
|
|
|
/*keep the contact position on an edge we found */
|
|
MTH3D_M_vCopyVector (&stContact,DNM_M_p_stObstacleGetContact(p_stGround));
|
|
|
|
|
|
/*compute the normed vector from the contact point to the center of the terminal zone position*/
|
|
MTH3D_M_vAddVector (&stVector1, DNM_M_pObstacleGetZonePosition(p_stGround), DNM_M_xObstacleGetTranslation(p_stGround));
|
|
MTH3D_M_vSubVector (&stVector1, &stVector1, &stContact);
|
|
MTH3D_M_vNormalizeVector (&stVector1,&stVector1);
|
|
|
|
for
|
|
(
|
|
lCounter = 0, p_stTmpObstacle = p_stObstacle;
|
|
lCounter < lObstacle;
|
|
lCounter ++, p_stTmpObstacle ++
|
|
)
|
|
{
|
|
if ( MEC_fn_bIsObstacleValid(p_stTmpObstacle) )
|
|
{
|
|
|
|
if ( MEC_fn_bGroundObstacle(p_stDynamic,p_stTmpObstacle) ) /*this one is a ground*/
|
|
{
|
|
|
|
if ( MEC_fn_bIsEdge(p_stTmpObstacle) )
|
|
{
|
|
/* same contact point ?*/
|
|
MTH3D_M_vSubVector (&stVector,&stContact,DNM_M_p_stObstacleGetContact(p_stTmpObstacle));
|
|
if ( MEC_fn_bIsNullVector(&stVector) ) lGround++;
|
|
}
|
|
else return; /*if any other obstacle is a non-edge, we cannot fall*/
|
|
|
|
}
|
|
else /*we find a non-ground edge*/
|
|
{
|
|
if (MEC_fn_bIsLowEdge(p_stTmpObstacle))
|
|
{
|
|
/*it is an edge, account for it in the number of different edge contact points*/
|
|
MTH3D_M_vSubVector (&stVector,&stContact,DNM_M_p_stObstacleGetContact(p_stTmpObstacle));
|
|
if ( MEC_fn_bIsNullVector(&stVector) ) /*at the same contact point than the ground edge*/
|
|
{
|
|
if ( MTH_M_bGreater(DNM_M_xDynamicsGetPreviousSlide (p_stDynamic),MTH_M_xDoubleToReal(0.5)) )
|
|
{
|
|
xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stGround), DNM_M_p_stObstacleGetNorm(p_stTmpObstacle) );
|
|
if (MTH_M_bGreater(xDotProd,MTH_M_xDoubleToReal(0.707)))
|
|
return;
|
|
}
|
|
|
|
xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stTmpObstacle), &stVector1 );
|
|
|
|
if ( !p_stNotGround && MTH_M_bGreaterZero(xDotProd) )
|
|
{
|
|
bNotGround = TRUE;
|
|
p_stNotGround = p_stTmpObstacle;
|
|
}
|
|
}
|
|
}
|
|
else if (MEC_fn_bWallObstacle(p_stDynamic,p_stTmpObstacle) && !MEC_fn_bIsHighEdge(p_stTmpObstacle))
|
|
{
|
|
MTH3D_M_vSubVector (&stVector,&stContact,DNM_M_p_stObstacleGetContact(p_stTmpObstacle));
|
|
xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stGround), &stVector );
|
|
if (MTH_M_bLessZero(xDotProd))
|
|
{
|
|
/* check we are on the ground side */
|
|
xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stTmpObstacle), &stVector );
|
|
if (MTH_M_bLess(xDotProd,MTH_M_xDoubleToReal(-1e-3)))
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lGround>=2) return;
|
|
|
|
/*here either we have a ground/non-ground obstable pair, or we have only a ground obstacle (bGround is true in either case)*/
|
|
|
|
/*compute the normed vector from the contact point to the center of the terminal zone position*/
|
|
// MTH3D_M_vAddVector (&stVector, DNM_M_pObstacleGetZonePosition(p_stGround), DNM_M_xObstacleGetTranslation(p_stGround));
|
|
// MTH3D_M_vSubVector (&stVector, &stVector, &stContact);
|
|
// MTH3D_M_vNormalizeVector (&stVector,&stVector);
|
|
|
|
if ( bNotGround )
|
|
{
|
|
MTH3D_M_vAddVector (&stEdgeVector,DNM_M_p_stObstacleGetNorm(p_stGround),DNM_M_p_stObstacleGetNorm(p_stNotGround));
|
|
bNotGround = !MEC_fn_bIsNullVector(&stEdgeVector); /*if the vector is null, we have only one edge normal (backface)*/
|
|
}
|
|
|
|
if ( bNotGround ) /*we have 2 edge normals*/
|
|
{
|
|
MTH_tdxReal xDotProd;
|
|
MTH3D_M_vNormalizeVector (&stEdgeVector,&stEdgeVector);
|
|
xDotProd = MTH3D_M_xDotProductVector (&stVector1,&stEdgeVector);
|
|
|
|
if ( MTH_M_bLessZero(xDotProd) )
|
|
return;
|
|
}
|
|
|
|
if ( MTH_M_bLess(MTH3D_M_xGetZofVector(&stVector1), C_xDNM_EDGE_GROUND_LIMIT) )
|
|
{
|
|
DNM_M_bDynamicsSetCanFall(p_stDynamic,TRUE);
|
|
|
|
/* compute fall translation */
|
|
if (DNM_M_bDynamicsIsComplexSize(p_stDynamic) )
|
|
{
|
|
MTH3D_M_vSetZofVector ( &stVector1, MTH_C_ZERO );
|
|
if (!MEC_fn_bIsNullVector(&stVector1)) MTH3D_M_vNormalizeVector (&stVector1,&stVector1)
|
|
else MTH3D_M_vNullVector (&stVector1);
|
|
DNM_M_vDynamicsSetFallTranslation (p_stDynamic,&stVector1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* is the actor */
|
|
void MEC_fn_vCrashAnalysis
|
|
(
|
|
struct DNM_stDynamics *p_stDynamic,
|
|
long lObstacle,
|
|
DNM_tdstMecObstacle *p_stObstacle
|
|
)
|
|
{
|
|
long lCounter;
|
|
DNM_tdstMecObstacle *p_stTmpObstacle;
|
|
DNM_tdstMecObstacle *p_stGroundObstacle, *p_stCeilObstacle;
|
|
|
|
p_stGroundObstacle = NULL;
|
|
p_stCeilObstacle = NULL;
|
|
DNM_M_vDynamicsSetCrash(p_stDynamic,FALSE);
|
|
|
|
p_stTmpObstacle = p_stObstacle;
|
|
for (lCounter=0; lCounter<lObstacle; lCounter++)
|
|
{
|
|
if ( MEC_fn_bIsObstacleValid(p_stTmpObstacle) )
|
|
{
|
|
if (!p_stGroundObstacle && MEC_fn_bGroundObstacle(p_stDynamic,p_stTmpObstacle))
|
|
p_stGroundObstacle = p_stTmpObstacle;
|
|
|
|
if (!p_stCeilObstacle && MEC_fn_bCeilObstacle(p_stDynamic,p_stTmpObstacle))
|
|
p_stCeilObstacle = p_stTmpObstacle;
|
|
}
|
|
p_stTmpObstacle++;
|
|
}
|
|
|
|
if (!p_stCeilObstacle || !p_stGroundObstacle)
|
|
return;
|
|
|
|
if
|
|
(
|
|
(
|
|
(DNM_M_eObstacleGetType(p_stGroundObstacle) & DNM_ObsType_Mobile)
|
|
&& MEC_fn_bCanCrashActor(p_stGroundObstacle)
|
|
)
|
|
||
|
|
(
|
|
(DNM_M_eObstacleGetType(p_stCeilObstacle) & DNM_ObsType_Mobile)
|
|
&& MEC_fn_bCanCrashActor(p_stCeilObstacle)
|
|
)
|
|
)
|
|
DNM_M_vDynamicsSetCrash(p_stDynamic,TRUE);
|
|
}
|
|
|
|
|
|
|