reman3/Rayman_X/cpa/tempgrp/MEC/MECCol.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);
}