2005 lines
74 KiB
C
2005 lines
74 KiB
C
/*
|
|
*=======================================================================================
|
|
* Name : MecBhv.c
|
|
* Author : J Thénoz Date : 01/05/98
|
|
* Description : Mechanic Behaviours
|
|
*=======================================================================================
|
|
*/
|
|
|
|
|
|
#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/MECOpt.h"
|
|
#include "MEC/MECBhv.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*/
|
|
|
|
/* Global data*/
|
|
long g_lCallCounter = 0; /* recursive call counter*/
|
|
extern long COL_g_lMaxNumberOfCollisions; /* size of collide array */
|
|
extern COL_tdstGVForCollision COL_g_stGVForCol;
|
|
extern ACP_tdxBool g_bWaterNoCollide;
|
|
|
|
|
|
|
|
ACP_tdxBool g_bHighSpeed = FALSE;
|
|
MTH3D_tdstVector g_stFirstMove;
|
|
|
|
|
|
/* private functions*/
|
|
|
|
void MEC_fn_vCollideBaseMechanic
|
|
(
|
|
struct DNM_stDynamics *p_stDynamic,
|
|
HIE_tdxHandleToSuperObject hSupObj,
|
|
long lObstacle,
|
|
DNM_tdstMecObstacle a_stObstacle[COL_C_xMaxNumberOfCollisions],
|
|
MTH_tdxReal xDT
|
|
)
|
|
{
|
|
POS_tdxHandleToPosition hCurrentMatrix, hPreviousMatrix, hAbsolutePreviousMatrix;
|
|
MTH3D_tdstVector stIncidentVector, stResultantVector;
|
|
MTH3D_tdstVector stNormalizeResultantVector;
|
|
MTH3D_tdstVector stPosition;
|
|
MTH3D_tdstVector *p_stPreviousPosition, *p_stCurrentPosition;
|
|
|
|
MTH3D_tdstVector stBaseRebound, stBaseSlide;
|
|
MTH3D_tdstVector stVector;
|
|
MTH3D_tdstVector stExtremPosition;
|
|
MTH3D_tdstVector stMoveVector;
|
|
MTH3D_tdstVector stAdjustVector;
|
|
MTH3D_tdstVector stNormalVector;
|
|
MTH3D_tdstVector* p_stNormal;
|
|
MTH_tdxReal xDotProd;
|
|
MTH_tdxReal xNorm;
|
|
MTH_tdxReal xRate;
|
|
MTH_tdxReal xOneMinusRate;
|
|
ACP_tdxBool bWallObstacle, bGroundObstacle;
|
|
ACP_tdxBool bOnlyEdge = TRUE;
|
|
ACP_tdxBool bWater = FALSE;
|
|
ACP_tdxBool bCollisionOk = TRUE;
|
|
MTH_tdxReal xSlide, xRebound;
|
|
MTH_tdxReal xResultantNorm;
|
|
MTH_tdxReal xDotProdMax = MTH_C_MinusONE;
|
|
MTH_tdxReal xDotProdMin = MTH_C_2;
|
|
ACP_tdxBool bCantKeepWallSpeedZ = FALSE;
|
|
|
|
MTH3D_tdstVector stVerticalVector;
|
|
DNM_tdstMecObstacle *p_stObstacle, *p_stBestObstacle, *p_stTmpObstacle, *p_stGroundObstacle, *p_stWaterObstacle;
|
|
long lCounter;
|
|
|
|
long lBestObstacleCounter;
|
|
long lObstacleCounter;
|
|
long lGroundObstacle;
|
|
long lWaterObstacle;
|
|
|
|
hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
|
|
hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
|
|
if (DNM_M_bDynamicsIsComplexSize(p_stDynamic)) hAbsolutePreviousMatrix = DNM_M_p_stDynamicsGetAbsolutePreviousMatrix (p_stDynamic);
|
|
p_stCurrentPosition = POS_fn_p_stGetTranslationVector ( hCurrentMatrix );
|
|
p_stPreviousPosition = POS_fn_p_stGetTranslationVector ( hPreviousMatrix );
|
|
|
|
/* search obstacle */
|
|
p_stObstacle = NULL;
|
|
p_stBestObstacle = NULL;
|
|
p_stGroundObstacle = NULL;
|
|
p_stWaterObstacle = NULL;
|
|
MTH3D_M_vNullVector (&stNormalVector);
|
|
lWaterObstacle = 0;
|
|
|
|
if (DNM_M_bDynamicsIsCanFall(p_stDynamic))
|
|
{
|
|
for (lCounter=0; lCounter<lObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = a_stObstacle+lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if (MEC_fn_bGroundObstacle(p_stDynamic,p_stTmpObstacle) )
|
|
MEC_fn_vInvalidateObstacle (p_stTmpObstacle);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (lCounter=0; lCounter<lObstacle && !p_stGroundObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = a_stObstacle+lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if (MEC_fn_bIsWater(p_stTmpObstacle))
|
|
{
|
|
p_stWaterObstacle = p_stTmpObstacle;
|
|
}
|
|
else if (MEC_fn_bGroundObstacle(p_stDynamic,p_stTmpObstacle) )
|
|
{
|
|
p_stGroundObstacle = p_stTmpObstacle;
|
|
lGroundObstacle = lCounter;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p_stGroundObstacle && DNM_M_bDynamicsIsSwim(p_stDynamic))
|
|
{
|
|
bWater = ( ( DNM_M_ulReportGetSurfaceState(&g_stReport) & C_WOT_ulWater ) == C_WOT_ulWater );
|
|
|
|
/* if actor collides ground when he swims, it's like if he walks on the ground under water*/
|
|
if (!bWater)
|
|
{
|
|
MEC_fn_vGroundObstacleManagement ( p_stDynamic, hSupObj, xDT );
|
|
DNM_M_ulReportSetSurfaceState (&g_stReport,DNM_M_ulReportGetSurfaceState(&g_stReport)&(~C_WOT_ulWater));
|
|
return;
|
|
}
|
|
}
|
|
|
|
bOnlyEdge = TRUE;
|
|
for (lCounter=0; lCounter<lObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = a_stObstacle+lCounter;
|
|
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if ((DNM_M_eObstacleGetType(p_stTmpObstacle) & DNM_ObsType_Mobile) == DNM_ObsType_Mobile)
|
|
{
|
|
if (!p_stBestObstacle)
|
|
{
|
|
p_stBestObstacle = p_stTmpObstacle;
|
|
lBestObstacleCounter = lCounter;
|
|
}
|
|
}
|
|
else if ( MEC_fn_bIsWater(p_stTmpObstacle) )
|
|
{
|
|
if (!p_stBestObstacle)
|
|
{
|
|
p_stBestObstacle = p_stTmpObstacle;
|
|
lBestObstacleCounter = lCounter;
|
|
}
|
|
if (!lWaterObstacle)
|
|
lWaterObstacle = lCounter;
|
|
}
|
|
|
|
xDotProd = MTH3D_M_xDotProductVector (DNM_M_pObstacleGetZoneMove(p_stTmpObstacle),DNM_M_p_stObstacleGetNorm(p_stTmpObstacle));
|
|
if (MTH_M_bLess(xDotProd,xDotProdMin))
|
|
{
|
|
xDotProdMin = xDotProd;
|
|
p_stObstacle = p_stTmpObstacle;
|
|
lObstacleCounter = lCounter;
|
|
}
|
|
|
|
if (!MEC_fn_bIsEdge(p_stTmpObstacle))
|
|
bOnlyEdge = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( !p_stObstacle )
|
|
{
|
|
p_stObstacle = p_stBestObstacle;
|
|
lObstacleCounter = lBestObstacleCounter;
|
|
}
|
|
|
|
if (!p_stObstacle)
|
|
return;
|
|
|
|
if (p_stGroundObstacle && lGroundObstacle>lObstacleCounter)
|
|
lObstacleCounter=lGroundObstacle;
|
|
|
|
if (lWaterObstacle>lObstacleCounter)
|
|
lObstacleCounter = lWaterObstacle;
|
|
|
|
MEC_fn_vReportCollision (p_stDynamic,hSupObj,lObstacle,a_stObstacle,lObstacleCounter);
|
|
|
|
if (!bOnlyEdge||DNM_M_bDynamicsIsCanFall(p_stDynamic))
|
|
p_stNormal = DNM_M_p_stObstacleGetNorm (p_stObstacle);
|
|
else
|
|
{
|
|
p_stNormal = &stNormalVector;
|
|
for (lCounter=0; lCounter<lObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = a_stObstacle+lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
MTH3D_M_vAddVector ( p_stNormal, p_stNormal, DNM_M_p_stObstacleGetNorm(p_stTmpObstacle) );
|
|
}
|
|
|
|
if (!MTH3D_M_bIsNullVector(p_stNormal))
|
|
MTH3D_M_vNormalizeVector ( p_stNormal, p_stNormal )
|
|
else
|
|
p_stNormal = DNM_M_p_stObstacleGetNorm(p_stObstacle);
|
|
|
|
if (MEC_fn_bGroundNormal(p_stDynamic,p_stNormal) && (!p_stGroundObstacle || (p_stGroundObstacle&&MEC_fn_bIsEdge(p_stGroundObstacle)) ) )
|
|
{
|
|
/* choose best face*/
|
|
for (lCounter=0; lCounter<lObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = a_stObstacle+lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
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) );
|
|
if (!MEC_fn_bIsNullVector(&stVector)) MTH3D_M_vNormalizeVector (&stVector,&stVector)
|
|
xDotProd = MTH3D_M_xDotProductVector (&stVector,DNM_M_p_stObstacleGetNorm(p_stTmpObstacle));
|
|
if (MTH_M_bGreater(xDotProd,xDotProdMax))
|
|
{
|
|
xDotProdMax = xDotProd;
|
|
p_stNormal = DNM_M_p_stObstacleGetNorm(p_stTmpObstacle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
xSlide = MEC_fn_xGetSlide (p_stDynamic,p_stObstacle);
|
|
xRebound = MEC_fn_xGetRebound (p_stDynamic,p_stObstacle);
|
|
|
|
MTH3D_M_vNullVector (&stNormalizeResultantVector);
|
|
MTH3D_M_vNullVector (&stAdjustVector);
|
|
|
|
/* type of obstacle */
|
|
MTH3D_M_vSetVectorElements (&stVerticalVector, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE);
|
|
xDotProd = MTH3D_M_xDotProductVector ( p_stNormal, &stVerticalVector );
|
|
bWallObstacle = MTH_M_bGreaterEqual (xDotProd,MEC_fn_xWallLimit(p_stDynamic)) && MTH_M_bLessEqual (xDotProd,MEC_fn_xGroundLimit(p_stDynamic));
|
|
bGroundObstacle = MTH_M_bGreaterEqual (xDotProd,MEC_fn_xGroundLimit(p_stDynamic));
|
|
|
|
/* compute incident vector */
|
|
MTH3D_M_vSubVector ( &stIncidentVector, p_stCurrentPosition, p_stPreviousPosition );
|
|
xNorm = MTH3D_M_xNormVector ( &stIncidentVector );
|
|
|
|
/* compute new base axis */
|
|
xDotProd = MTH3D_M_xDotProductVector ( &stIncidentVector, p_stNormal );
|
|
MTH3D_M_vMulScalarVector ( &stVector, MTH_M_xNeg(xDotProd), p_stNormal );
|
|
MTH3D_M_vAddVector ( &stBaseSlide, &stIncidentVector, &stVector);
|
|
MTH3D_M_vAddVector ( &stBaseRebound, &stBaseSlide, &stVector);
|
|
|
|
/* compute resultant vector */
|
|
MTH3D_M_vMulScalarVector ( &stResultantVector, xSlide, &stBaseSlide );
|
|
MTH3D_M_vMulScalarVector ( &stVector, xRebound, &stBaseRebound );
|
|
MTH3D_M_vAddVector ( &stResultantVector, &stResultantVector, &stVector );
|
|
xResultantNorm = MTH3D_M_xNormVector ( &stResultantVector );
|
|
if (!MEC_fn_bIsNullVector(&stResultantVector)) MTH3D_M_vMulScalarVector(&stNormalizeResultantVector,MTH_M_xInv(xResultantNorm),&stResultantVector);
|
|
|
|
/* adjust resultant vector if control speedz */
|
|
/* only for wall obstacle */
|
|
if (DNM_M_bDynamicsIsKeepWallSpeedZ(p_stDynamic) && bWallObstacle && !MTH_M_bEqual(MTH3D_M_xGetZofVector (&stResultantVector),MTH_C_ZERO))
|
|
{
|
|
MTH_tdxReal xZRate, xZResultantVector;
|
|
|
|
xZRate = MTH3D_M_xGetZofVector (&stIncidentVector);
|
|
xZResultantVector = MTH3D_M_xGetZofVector (&stResultantVector);
|
|
if (!MTH_M_bEqual(xZResultantVector,MTH_C_ZERO))
|
|
{
|
|
xZRate = MTH_M_xDiv ( xZRate, xZResultantVector );
|
|
if (MTH_M_bGreater(xZRate,MTH_C_MinusONE))
|
|
{
|
|
if ( MTH_M_bLessEqual(xZRate,MTH_C_ONE) )
|
|
{
|
|
/* change norm*/
|
|
MTH3D_M_vMulScalarVector ( &stResultantVector, xZRate, &stResultantVector );
|
|
}
|
|
else
|
|
{
|
|
/* change direction*/
|
|
MTH3D_tdstVector stU, stV, stN, stVector;
|
|
MTH_tdxReal xU, xV, xN, xNorm2, xVExtrem, xVExtrem2;
|
|
|
|
/* system axis */
|
|
MTH3D_M_vCopyVector ( &stN, p_stNormal );
|
|
MTH3D_M_vCrossProductVector ( &stU, &stVerticalVector, &stN );
|
|
MTH3D_M_vCrossProductVector ( &stV, &stN, &stU );
|
|
|
|
xU = MTH3D_M_xDotProductVector ( &stResultantVector, &stU );
|
|
xV = MTH3D_M_xDotProductVector ( &stResultantVector, &stV );
|
|
xN = MTH3D_M_xDotProductVector ( &stResultantVector, &stN );
|
|
|
|
xVExtrem = MTH_M_xDiv ( MTH3D_M_xGetZofVector (&stIncidentVector), MTH3D_M_xGetZofVector (&stV) );
|
|
|
|
xNorm2 = MTH_M_xAdd ( MTH_M_xMul(xU,xU), MTH_M_xMul(xV,xV) );
|
|
xVExtrem2 = MTH_M_xMul( xVExtrem, xVExtrem );
|
|
|
|
if ( MTH_M_bGreaterEqual (xNorm2, xVExtrem2) && MTH_M_bGreater ( MTH_M_xAbs(xU),C_xDNM_VERTICAL_FALL_LIMIT) )
|
|
{
|
|
// xU = MTH_M_xMul ( MTH_M_xSqrt ( MTH_M_xSub (xNorm2,xVExtrem2) ), MTH_M_xSign (xU) );
|
|
xV = xVExtrem;
|
|
}
|
|
else
|
|
{
|
|
// xU = MTH_C_ZERO;
|
|
xV = xVExtrem;
|
|
}
|
|
|
|
MTH3D_M_vMulScalarVector ( &stResultantVector, xU, &stU );
|
|
MTH3D_M_vMulScalarVector ( &stVector, xV, &stV );
|
|
MTH3D_M_vAddVector ( &stResultantVector, &stResultantVector, &stVector );
|
|
MTH3D_M_vMulScalarVector ( &stVector, xN, &stN );
|
|
MTH3D_M_vAddVector ( &stResultantVector, &stResultantVector, &stVector );
|
|
}
|
|
}
|
|
else
|
|
bCantKeepWallSpeedZ = TRUE;
|
|
}
|
|
}
|
|
|
|
/* adjust positions */
|
|
xRate = DNM_M_xObstacleGetRate (p_stObstacle);
|
|
|
|
bCollisionOk = MEC_fn_vComputeAdjustVector (&stAdjustVector, p_stDynamic, lObstacle, a_stObstacle, lObstacleCounter);
|
|
|
|
if (DNM_M_bDynamicsIsHanging(p_stDynamic))
|
|
MTH3D_M_vSetZofVector (&stAdjustVector,MTH_C_ZERO);
|
|
|
|
MTH3D_M_vAddVector (&stPosition, p_stCurrentPosition, &stAdjustVector);
|
|
|
|
if (MTH_M_bGreaterEqual (xRate, MTH_C_ZERO))
|
|
xOneMinusRate = MTH_M_xSub (MTH_C_ONE,xRate);
|
|
else
|
|
// {
|
|
// if (!MTH_M_bIsNullWithEpsilon(MTH3D_M_xGetZofVector(&stResultantVector),MTH_M_xDoubleToReal(1e-5)) && DNM_M_bDynamicsIsKeepWallSpeedZ(p_stDynamic) && !bCantKeepWallSpeedZ )
|
|
// {
|
|
// MTH3D_M_vSubVector (&stAdjustVector, &stPosition, p_stPreviousPosition);
|
|
// xOneMinusRate = MTH_M_xDiv ( MTH_M_xSub(MTH3D_M_xGetZofVector(&stIncidentVector),MTH3D_M_xGetZofVector(&stAdjustVector)),MTH3D_M_xGetZofVector(&stResultantVector));
|
|
// }
|
|
// else
|
|
xOneMinusRate = MTH_C_ZERO;
|
|
// }
|
|
|
|
MTH3D_M_vMulScalarVector (&stVector, xOneMinusRate,&stResultantVector);
|
|
|
|
if ( MTH_M_bGreater ( MTH3D_M_xNormVector(&stVector), DNM_M_xObstacleGetZoneRadius(p_stObstacle) ) )
|
|
{
|
|
MTH3D_M_vNormalizeVector ( &stVector, &stVector );
|
|
MTH3D_M_vMulScalarVector ( &stVector, DNM_M_xObstacleGetZoneRadius(p_stObstacle), &stVector );
|
|
}
|
|
|
|
MTH3D_M_vAddVector (&stExtremPosition, &stPosition, &stVector);
|
|
|
|
MTH3D_M_vSubVector (&stMoveVector, &stExtremPosition, p_stPreviousPosition);
|
|
xDotProd = MTH3D_M_xDotProductVector (p_stNormal,&stMoveVector);
|
|
|
|
if ( ( ( ((MTH_M_bGreater(xDotProd,C_xDNM_MTH_EPSILON) && bGroundObstacle && MTH_M_bGreaterZero(xRebound)) || ( p_stGroundObstacle && !MEC_fn_bGroundObstacle(p_stDynamic,p_stObstacle) ) || ( p_stWaterObstacle && (p_stObstacle!=p_stWaterObstacle) ) || g_bWaterNoCollide ) && !DNM_M_bDynamicsIsCanFall(p_stDynamic) ) ) )
|
|
{
|
|
MTH3D_M_vCopyVector (p_stCurrentPosition,&stPosition);
|
|
MTH3D_M_vSubVector (p_stPreviousPosition, p_stCurrentPosition, &stResultantVector);
|
|
}
|
|
else
|
|
{
|
|
MTH3D_M_vCopyVector (p_stCurrentPosition,&stExtremPosition);
|
|
MTH3D_M_vSubVector (p_stPreviousPosition, p_stCurrentPosition, &stResultantVector);
|
|
}
|
|
|
|
if (DNM_M_bDynamicsIsComplexSize(p_stDynamic)) POS_fn_vSetTranslationVector ( hAbsolutePreviousMatrix, p_stPreviousPosition );
|
|
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
}
|
|
|
|
|
|
void MEC_fn_vWallObstacleManagement
|
|
(
|
|
MTH3D_tdstVector* pstResultMove,
|
|
struct DNM_stDynamics *p_stDynamic,
|
|
MTH3D_tdstVector* pstMove,
|
|
MTH3D_tdstVector* pstGroundNormal,
|
|
MTH3D_tdstVector* pstWallNormal,
|
|
MTH_tdxReal xDT,
|
|
ACP_tdxBool bAngleLimit
|
|
)
|
|
{
|
|
MTH3D_tdstVector stDirection;
|
|
MTH3D_tdstVector stWallNormalAdjust;
|
|
MTH3D_tdstVector stVector;
|
|
POS_tdxHandleToPosition hCurrentMatrix;
|
|
MTH3D_tdstVector *p_stCurrentTranslation;
|
|
MTH_tdxReal xDotProd1, xDotProd2, xFactor;
|
|
|
|
if ( MEC_fn_bIsNullVector(pstMove) )
|
|
{
|
|
MTH3D_M_vNullVector (pstResultMove);
|
|
return;
|
|
}
|
|
|
|
hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
|
|
p_stCurrentTranslation = POS_fn_p_stGetTranslationVector ( hCurrentMatrix );
|
|
MTH3D_M_vCrossProductVectorWithoutBuffer ( &stDirection, pstGroundNormal, pstWallNormal );
|
|
|
|
if (MEC_fn_bIsNullVector(&stDirection))
|
|
{
|
|
MTH3D_M_vNullVector (pstResultMove);
|
|
return;
|
|
}
|
|
|
|
|
|
MTH3D_M_vNormalizeVector (&stDirection,&stDirection);
|
|
xDotProd1 = MTH3D_M_xDotProductVector (&stDirection, pstMove);
|
|
|
|
if (bAngleLimit && (g_lCallCounter==1))
|
|
{
|
|
if (!MEC_fn_bIsNullVector(pstMove))
|
|
MTH3D_M_vNormalizeVector (&stVector,pstMove)
|
|
else
|
|
MTH3D_M_vNullVector(&stVector);
|
|
|
|
xDotProd2 = MTH_M_xNeg(MTH3D_M_xDotProductVector (&stVector,pstWallNormal));
|
|
|
|
xFactor = MTH_M_xMul(MTH3D_M_xNormVector(pstMove),MTH_M_xSign(xDotProd1));
|
|
if (MTH_M_bGreater(xDotProd2,C_xDNM_CLIMB_COS_ANGLE_LIMIT))
|
|
xFactor = MTH_M_xMul ( xFactor, MTH_M_xDiv(MTH_M_xSub(MTH_C_ONE,xDotProd2),MTH_M_xSub(MTH_C_ONE,C_xDNM_CLIMB_COS_ANGLE_LIMIT)) );
|
|
}
|
|
else
|
|
xFactor = xDotProd1;
|
|
|
|
MTH3D_M_vMulScalarVector ( pstResultMove, xFactor, &stDirection);
|
|
|
|
// MTH3D_M_vMulScalarVector ( &stWallNormalAdjust, MTH_M_xMul(MTH3D_M_xNormVector(pstResultMove),MTH_M_xDoubleToReal(0.005)), pstWallNormal );
|
|
MTH3D_M_vMulScalarVector ( &stWallNormalAdjust, MTH_M_xMul(MTH3D_M_xNormVector(pstResultMove),MTH_M_xDoubleToReal(0.01)), pstWallNormal );
|
|
MTH3D_M_vAddVector ( pstResultMove, pstResultMove, &stWallNormalAdjust );
|
|
|
|
MTH3D_M_vAddVector ( p_stCurrentTranslation, p_stCurrentTranslation, pstResultMove);
|
|
}
|
|
|
|
/* orient current matrix ( -y = normal )*/
|
|
void MEC_fn_vOrient ( struct DNM_stDynamics *p_stDynamic, MTH3D_tdstVector* p_stNormal)
|
|
{
|
|
POS_tdxHandleToPosition hCurrentMatrix;
|
|
MTH3D_tdstVector stVerticalVector;
|
|
MTH3D_tdstVector *p_stX, *p_stY, *p_stZ;
|
|
|
|
hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
|
|
MTH3D_M_vSetBaseKVector (&stVerticalVector);
|
|
|
|
POS_fn_vGetRotationVector ( hCurrentMatrix, &p_stX, &p_stY, &p_stZ );
|
|
MTH3D_M_vCopyVector ( p_stY, p_stNormal );
|
|
MTH3D_M_vCrossProductVectorWithoutBuffer (p_stX, p_stY, &stVerticalVector);
|
|
MTH3D_M_vCrossProductVectorWithoutBuffer (p_stZ, p_stX, p_stY );
|
|
MEC_fn_vUpdateMatrix ( p_stDynamic, hCurrentMatrix );
|
|
}
|
|
|
|
|
|
/* Obstacle collide*/
|
|
void MEC_fn_vBaseObstacleManagement ( struct DNM_stDynamics *p_stDynamic, HIE_tdxHandleToSuperObject hSupObj, MTH_tdxReal xDT )
|
|
{
|
|
long lObstacle;
|
|
|
|
POS_tdxHandleToPosition hCurrentMatrix;
|
|
POS_tdxHandleToPosition hInitialMatrix;
|
|
POS_tdstCompletePosition stInitialMatrix;
|
|
|
|
#ifdef DNM_DEBUG
|
|
if(p_stDynamic == NULL)
|
|
return;
|
|
#endif
|
|
|
|
hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
|
|
|
|
if (fn_ucCollSetGetCollComputeFrequencySO(hSupObj)>1)
|
|
{
|
|
hInitialMatrix = &stInitialMatrix;
|
|
POS_fn_vCopyMatrix (hInitialMatrix,DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic));
|
|
MEC_fn_vGetCollisionTranslation (p_stDynamic,hInitialMatrix);
|
|
}
|
|
else hInitialMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
|
|
|
|
/* Detection of collisions */
|
|
g_bWaterNoCollide = FALSE;
|
|
|
|
if(MEC_fn_bCollision(&lObstacle,g_a_stObstacle,p_stDynamic,hSupObj,hInitialMatrix,hCurrentMatrix,(ACP_tdxBool)DNM_M_bDynamicsIsHanging(p_stDynamic)))
|
|
{
|
|
MEC_fn_vEdgeAnalysis (p_stDynamic, lObstacle, g_a_stObstacle, NULL );
|
|
MEC_fn_vCollideBaseMechanic ( p_stDynamic, hSupObj, lObstacle, g_a_stObstacle, xDT);
|
|
}
|
|
else
|
|
DNM_M_vDynamicsSetStop (p_stDynamic,FALSE);
|
|
|
|
}
|
|
|
|
|
|
/* new Gi*/
|
|
void MEC_fn_vGiObstacleManagement ( struct DNM_stDynamics *p_stDynamic, HIE_tdxHandleToSuperObject hSupObj, MTH_tdxReal xDT )
|
|
{
|
|
long lObstacle;
|
|
long lCounter=0;
|
|
long lCounter1=0;
|
|
long lFace=0;
|
|
ACP_tdxBool bGiFace = FALSE;
|
|
|
|
MTH_tdxReal xNormalMove;
|
|
MTH_tdxReal xSlope;
|
|
MTH_tdxReal xDotProd;
|
|
|
|
MTH3D_tdstVector *p_stCurrentTranslation;
|
|
MTH3D_tdstVector *p_stPreviousTranslation;
|
|
MTH3D_tdstVector *p_stDownTranslation;
|
|
MTH3D_tdstVector *p_stUpTranslation;
|
|
MTH3D_tdstVector *p_stGiNormal, *p_stGiContact;
|
|
MTH3D_tdstVector stVector;
|
|
MTH3D_tdstVector stNormalMove, stTangentMove, stMove, stSlideMove;
|
|
MTH3D_tdstVector stVerticalVector;
|
|
MTH3D_tdstVector stAdjustVector;
|
|
|
|
DNM_tdstMecObstacle *p_stTmpObstacle;
|
|
DNM_tdstMecObstacle *p_stGiObstacle, *p_stSlideObstacle;
|
|
DNM_tdstObstacle *p_stPreviousCeilObstacle;
|
|
|
|
POS_tdstCompletePosition a2_stPosition[2];
|
|
POS_tdstCompletePosition *p_stPOS_DownPosition = a2_stPosition;
|
|
POS_tdstCompletePosition *p_stPOS_UpPosition = a2_stPosition+1;
|
|
POS_tdxHandleToPosition hCurrentMatrix, hPreviousMatrix;
|
|
|
|
xSlope = MEC_fn_xMaxSlope (p_stDynamic);
|
|
|
|
#ifdef DNM_DEBUG
|
|
if(p_stDynamic == NULL)
|
|
return;
|
|
if(!HIE_fn_bIsSuperObjectValid(hSupObj))
|
|
return;
|
|
#endif
|
|
|
|
/* Matrix init */
|
|
hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
|
|
hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
|
|
MTH3D_M_vSetVectorElements( &stVerticalVector, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE );
|
|
|
|
|
|
POS_fn_vCopyMatrix(p_stPOS_UpPosition, hCurrentMatrix);
|
|
POS_fn_vCopyMatrix(p_stPOS_DownPosition, hCurrentMatrix);
|
|
|
|
p_stCurrentTranslation = POS_fn_p_stGetTranslationVector ( hCurrentMatrix );
|
|
p_stPreviousTranslation = POS_fn_p_stGetTranslationVector ( hPreviousMatrix );
|
|
MTH3D_M_vSubVector (&stMove,p_stCurrentTranslation,p_stPreviousTranslation);
|
|
|
|
/* stack protection -> no more than 5 recursives calls. ( experience teaches it's enough )*/
|
|
g_lCallCounter++;
|
|
if (g_lCallCounter>5)
|
|
{
|
|
/* stay here */
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,p_stPreviousTranslation);
|
|
MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
|
|
return;
|
|
}
|
|
|
|
xNormalMove = MTH_M_xMul ( xSlope, MTH3D_M_xNormVector(&stMove) );
|
|
|
|
if (MTH_M_bLess (xNormalMove,C_xDNM_CLIMB_DEFAULT_NORMAL_MOVE)) xNormalMove = C_xDNM_GI_DEFAULT_NORMAL_MOVE;
|
|
|
|
p_stGiNormal = NULL;
|
|
p_stGiContact = NULL;
|
|
p_stPreviousCeilObstacle = DNM_M_p_stReportGetCeil (DNM_M_p_stDynamicsGetReport(p_stDynamic));
|
|
if (p_stPreviousCeilObstacle)
|
|
{
|
|
p_stGiNormal = DNM_M_p_stObstacleGetNorm(p_stPreviousCeilObstacle);
|
|
p_stGiContact = DNM_M_p_stObstacleGetContact(p_stPreviousCeilObstacle);
|
|
}
|
|
else
|
|
{
|
|
p_stGiNormal = &stVerticalVector;
|
|
}
|
|
|
|
/* normal and tangent move */
|
|
MTH3D_M_vMulScalarVector ( &stNormalMove, MTH3D_M_xDotProductVector( &stMove, p_stGiNormal ), p_stGiNormal);
|
|
MTH3D_M_vSubVector ( &stTangentMove, &stMove, &stNormalMove );
|
|
MTH3D_M_vMulScalarVector ( &stVector, xNormalMove, p_stGiNormal);
|
|
|
|
p_stDownTranslation = POS_fn_p_stGetTranslationVector ( p_stPOS_DownPosition );
|
|
MTH3D_M_vCopyVector ( p_stDownTranslation, p_stPreviousTranslation );
|
|
MTH3D_M_vAddVector ( p_stDownTranslation, p_stDownTranslation, &stTangentMove );
|
|
MTH3D_M_vAddVector ( p_stDownTranslation, p_stDownTranslation, &stVector );
|
|
|
|
p_stUpTranslation = POS_fn_p_stGetTranslationVector ( p_stPOS_UpPosition );
|
|
MTH3D_M_vCopyVector ( p_stUpTranslation, p_stPreviousTranslation );
|
|
MTH3D_M_vAddVector ( p_stUpTranslation, p_stUpTranslation, &stTangentMove );
|
|
MTH3D_M_vSubVector ( p_stUpTranslation, p_stUpTranslation, &stVector );
|
|
|
|
|
|
p_stGiObstacle = NULL;
|
|
p_stSlideObstacle = NULL;
|
|
p_stPreviousCeilObstacle = NULL;
|
|
|
|
/* call collisions*/
|
|
if(MEC_fn_bCollision(&lObstacle,g_a_stObstacle,p_stDynamic,hSupObj,p_stPOS_DownPosition,p_stPOS_UpPosition,TRUE))
|
|
{
|
|
MEC_fn_vDeleteGiBackFace (lObstacle,g_a_stObstacle,p_stDynamic,&stMove);
|
|
|
|
/* search first collided Gi faces */
|
|
for (lCounter=0; lCounter<lObstacle && (!p_stGiObstacle || !bGiFace); lCounter++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle + lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if ( (MEC_fn_bTypeOfGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle), C_xDNM_GI_TYPE_GAME_MATERIAL)) && !(MEC_fn_bTypeOfGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle), C_xDNM_NO_COLLISION_TYPE_GAME_MATERIAL)) && (MEC_fn_bCeilObstacle (p_stDynamic,p_stTmpObstacle)) )
|
|
{
|
|
if (!p_stGiObstacle)
|
|
p_stGiObstacle = p_stTmpObstacle;
|
|
if (!MEC_fn_bIsEdge(p_stTmpObstacle))
|
|
bGiFace = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p_stGiObstacle)
|
|
{
|
|
p_stGiNormal = DNM_M_p_stObstacleGetNorm(p_stGiObstacle);
|
|
p_stGiContact = DNM_M_p_stObstacleGetContact(p_stGiObstacle);
|
|
}
|
|
|
|
for (lCounter1=0; lCounter1<lObstacle && !p_stSlideObstacle; lCounter1++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle + lCounter1;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if
|
|
(
|
|
!MEC_fn_bTypeOfGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle), C_xDNM_GI_TYPE_GAME_MATERIAL)
|
|
|| MEC_fn_bTypeOfGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle), C_xDNM_NO_COLLISION_TYPE_GAME_MATERIAL)
|
|
)
|
|
{
|
|
xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stTmpObstacle), p_stGiNormal );
|
|
if (MTH_M_bLess(xDotProd,MTH_M_xDoubleToReal(0.707)))
|
|
{
|
|
MTH3D_M_vSubVector ( &stVector, DNM_M_p_stObstacleGetContact(p_stTmpObstacle), p_stGiContact );
|
|
xDotProd = MTH3D_M_xDotProductVector ( &stVector, p_stGiNormal );
|
|
if (MTH_M_bGreater ( xDotProd, MTH_M_xDoubleToReal(-0.01) ))
|
|
p_stSlideObstacle = p_stTmpObstacle;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p_stSlideObstacle && lCounter1>lCounter) lCounter=lCounter1;
|
|
|
|
/* report obstacles in the report.*/
|
|
MEC_fn_vReportCollision (p_stDynamic,hSupObj,lObstacle,g_a_stObstacle,lCounter-1);
|
|
|
|
/* detect stop to stay compatible with previous Gi mechanics*/
|
|
if (p_stGiObstacle && MEC_fn_bIsEdge(p_stGiObstacle) && !p_stSlideObstacle && !bGiFace)
|
|
{
|
|
for ( lCounter1=0; lCounter1<lObstacle; lCounter1++ )
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle+lCounter1;
|
|
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
MTH3D_M_vSubVector ( &stVector, p_stGiContact, DNM_M_p_stObstacleGetContact(p_stTmpObstacle) );
|
|
if (MEC_fn_bIsNullVector(&stVector))
|
|
{
|
|
lFace++;
|
|
|
|
// if
|
|
// (
|
|
// !MEC_fn_bCeilObstacle (p_stDynamic,p_stTmpObstacle)
|
|
// || !MEC_fn_bTypeOfGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle), C_xDNM_GI_TYPE_GAME_MATERIAL)
|
|
// || MEC_fn_bTypeOfGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle), C_xDNM_NO_COLLISION_TYPE_GAME_MATERIAL)
|
|
// )
|
|
// {
|
|
// /* stop */
|
|
// if (!DNM_M_bDynamicsIsMechanicChange(p_stDynamic)) DNM_M_vDynamicsSetStop (p_stDynamic,TRUE);
|
|
// MTH3D_M_vCopyVector (p_stCurrentTranslation,p_stPreviousTranslation);
|
|
// MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
|
|
//
|
|
// /*/ report previous collision */
|
|
// if (DNM_M_bDynamicsIsCollisionReport(p_stDynamic))
|
|
// DNM_M_ulReportSetSurfaceState(DNM_M_p_stDynamicsGetReport(p_stDynamic),DNM_M_ulReportGetPrevSurfaceState (DNM_M_p_stDynamicsGetReport(p_stDynamic)) );
|
|
// return;
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lFace==1 && !MEC_fn_bIsDoubleEdge(p_stGiObstacle))
|
|
{
|
|
/* stop */
|
|
if (!DNM_M_bDynamicsIsMechanicChange(p_stDynamic)) DNM_M_vDynamicsSetStop (p_stDynamic,TRUE);
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,p_stPreviousTranslation);
|
|
MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
|
|
|
|
/*/ report previous collision */
|
|
if (DNM_M_bDynamicsIsCollisionReport(p_stDynamic))
|
|
DNM_M_ulReportSetSurfaceState(DNM_M_p_stDynamicsGetReport(p_stDynamic),DNM_M_ulReportGetPrevSurfaceState (DNM_M_p_stDynamicsGetReport(p_stDynamic)) );
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* we meet a gi face ...*/
|
|
if (p_stGiObstacle)
|
|
{
|
|
if(!p_stSlideObstacle)
|
|
{
|
|
MTH3D_M_vAddVector (&stVector, p_stUpTranslation, DNM_M_xObstacleGetTranslation (p_stGiObstacle));
|
|
POS_fn_vSetTranslationVector ( hCurrentMatrix, &stVector );
|
|
}
|
|
else
|
|
{
|
|
/* we use its previous position that is safe.*/
|
|
if ( p_stSlideObstacle && MEC_fn_bIsCollide(p_stSlideObstacle) && (g_lCallCounter>2) )
|
|
{
|
|
MEC_fn_vComputeAdjustVector (&stAdjustVector, p_stDynamic, lObstacle, g_a_stObstacle, lCounter);
|
|
MTH3D_M_vAddVector (p_stCurrentTranslation, p_stUpTranslation, &stAdjustVector);
|
|
MTH3D_M_vSubVector (&stVector, p_stCurrentTranslation, p_stPreviousTranslation);
|
|
MTH3D_M_vSubVector (&stMove,&stMove,&stVector);
|
|
MTH3D_M_vCopyVector (p_stPreviousTranslation,p_stCurrentTranslation);
|
|
}
|
|
else
|
|
/* we use its previous position that is safe.*/
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,p_stPreviousTranslation);
|
|
|
|
/* compute slide -> Current position is the new place were we try to go*/
|
|
MEC_fn_vWallObstacleManagement ( &stSlideMove, p_stDynamic, &stMove, DNM_M_p_stObstacleGetNorm(p_stGiObstacle), DNM_M_p_stObstacleGetNorm(p_stSlideObstacle), xDT, FALSE );
|
|
|
|
/* stWallMove contains the move due to wall slide. If it's not significant, it's no use to continue.*/
|
|
if (!MEC_fn_bIsNullVector(&stSlideMove))
|
|
{
|
|
MEC_fn_vGiObstacleManagement (p_stDynamic, hSupObj, xDT);
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
return;
|
|
}
|
|
else MTH3D_M_vCopyVector (p_stCurrentTranslation,p_stPreviousTranslation);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (p_stSlideObstacle)
|
|
{
|
|
/* we use its previous position that is safe.*/
|
|
if ( p_stSlideObstacle && MEC_fn_bIsCollide(p_stSlideObstacle) /*&& !MEC_fn_bIsEdge(p_stSlideObstacle)*/ )
|
|
{
|
|
MEC_fn_vComputeAdjustVector (&stAdjustVector, p_stDynamic, lObstacle, g_a_stObstacle, lCounter);
|
|
MTH3D_M_vAddVector (p_stCurrentTranslation, p_stUpTranslation, &stAdjustVector);
|
|
MTH3D_M_vSubVector (&stVector, p_stCurrentTranslation, p_stPreviousTranslation);
|
|
MTH3D_M_vSubVector (&stMove,&stMove,&stVector);
|
|
MTH3D_M_vCopyVector (p_stPreviousTranslation,p_stCurrentTranslation);
|
|
}
|
|
else
|
|
/* we use its previous position that is safe.*/
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,p_stPreviousTranslation);
|
|
|
|
MEC_fn_vWallObstacleManagement ( &stSlideMove, p_stDynamic, &stMove, p_stGiNormal, DNM_M_p_stObstacleGetNorm(p_stSlideObstacle), xDT, FALSE );
|
|
|
|
if (!MEC_fn_bIsNullVector(&stSlideMove))
|
|
{
|
|
MEC_fn_vGiObstacleManagement ( p_stDynamic, hSupObj, xDT );
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
return;
|
|
}
|
|
else MTH3D_M_vCopyVector (p_stCurrentTranslation,p_stPreviousTranslation);
|
|
}
|
|
else
|
|
{
|
|
POS_fn_vCopyMatrix ( hCurrentMatrix, hPreviousMatrix );
|
|
MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
|
|
if (!DNM_M_bDynamicsIsMechanicChange(p_stDynamic)) DNM_M_vDynamicsSetStop ( p_stDynamic, TRUE );
|
|
|
|
/* resport previous state */
|
|
if (DNM_M_bDynamicsIsCollisionReport(p_stDynamic))
|
|
DNM_M_ulReportSetSurfaceState(DNM_M_p_stDynamicsGetReport(p_stDynamic),DNM_M_ulReportGetPrevSurfaceState (DNM_M_p_stDynamicsGetReport(p_stDynamic)) );
|
|
return;
|
|
}
|
|
}
|
|
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
return;
|
|
}
|
|
|
|
|
|
/* There is no obstacle at all.*/
|
|
POS_fn_vCopyMatrix ( hCurrentMatrix, hPreviousMatrix );
|
|
MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
|
|
if (!DNM_M_bDynamicsIsMechanicChange(p_stDynamic)) DNM_M_vDynamicsSetStop (p_stDynamic,TRUE);
|
|
|
|
/* resport previous state */
|
|
if (DNM_M_bDynamicsIsCollisionReport(p_stDynamic))
|
|
DNM_M_ulReportSetSurfaceState(DNM_M_p_stDynamicsGetReport(p_stDynamic),DNM_M_ulReportGetPrevSurfaceState (DNM_M_p_stDynamicsGetReport(p_stDynamic)) );
|
|
|
|
return;
|
|
}
|
|
|
|
/* new climb*/
|
|
void MEC_fn_vClimbObstacleManagement
|
|
(
|
|
struct DNM_stDynamics *p_stDynamic,
|
|
HIE_tdxHandleToSuperObject hSupObj,
|
|
MTH_tdxReal xDT
|
|
)
|
|
{
|
|
long lObstacle;
|
|
long lCounter=0;
|
|
long lCounter1=0;
|
|
long lCounter2=0;
|
|
|
|
ACP_tdxBool bStop = FALSE;
|
|
|
|
MTH_tdxReal xNormalMove;
|
|
MTH_tdxReal xSlope;
|
|
MTH_tdxReal xDotProd;
|
|
MTH_tdxReal xDotProdMin = MTH_C_ZERO;
|
|
|
|
MTH3D_tdstVector *p_stX, *p_stY, *p_stZ;
|
|
MTH3D_tdstVector *p_stCurrentTranslation;
|
|
MTH3D_tdstVector *p_stPreviousTranslation;
|
|
MTH3D_tdstVector *p_stBackTranslation;
|
|
MTH3D_tdstVector *p_stFrontTranslation;
|
|
MTH3D_tdstVector *p_stNormal;
|
|
MTH3D_tdstVector *p_stCollideSlideObstacle = NULL;
|
|
|
|
MTH3D_tdstVector stVector;
|
|
MTH3D_tdstVector stAdjustVector;
|
|
MTH3D_tdstVector stMove, stNormalMove, stTangentMove, stSlideMove;
|
|
MTH3D_tdstVector stVerticalVector;
|
|
MTH3D_tdstVector stSafeTranslation;
|
|
MTH3D_tdstVector stNormMove;
|
|
MTH3D_tdstVector stNormTangentMove;
|
|
|
|
DNM_tdstMecObstacle *p_stTmpObstacle;
|
|
DNM_tdstMecObstacle *p_stClimbObstacle, *p_stSlideObstacle;
|
|
DNM_tdstMecObstacle *p_stEdgeObstacle;
|
|
DNM_tdstMecObstacle *p_stGroundObstacle;
|
|
|
|
POS_tdstCompletePosition a2_stPosition[2];
|
|
POS_tdstCompletePosition *p_stPOS_BackPosition = a2_stPosition;
|
|
POS_tdstCompletePosition *p_stPOS_FrontPosition = a2_stPosition+1;
|
|
POS_tdxHandleToPosition hCurrentMatrix, hPreviousMatrix;
|
|
|
|
xSlope = C_xDNM_CLIMB_SLOPE_LIMIT;
|
|
|
|
#ifdef DNM_DEBUG
|
|
if(p_stDynamic == NULL)
|
|
return;
|
|
if(!HIE_fn_bIsSuperObjectValid(hSupObj))
|
|
return;
|
|
#endif
|
|
|
|
/* Matrix init */
|
|
hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
|
|
hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
|
|
MTH3D_M_vSetVectorElements( &stVerticalVector, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE );
|
|
|
|
/* orient toward the rock the first time */
|
|
if (DNM_M_bDynamicsIsMechanicChange (p_stDynamic))
|
|
{
|
|
p_stNormal = DNM_M_pDynamicsGetWallNormal (p_stDynamic);
|
|
if (!MTH3D_M_bIsNullVector(p_stNormal))
|
|
MEC_fn_vOrient ( p_stDynamic, p_stNormal );
|
|
}
|
|
|
|
|
|
POS_fn_vCopyMatrix(p_stPOS_FrontPosition, hCurrentMatrix);
|
|
POS_fn_vCopyMatrix(p_stPOS_BackPosition, hCurrentMatrix);
|
|
|
|
p_stCurrentTranslation = POS_fn_p_stGetTranslationVector ( hCurrentMatrix );
|
|
p_stPreviousTranslation = POS_fn_p_stGetTranslationVector ( hPreviousMatrix );
|
|
MTH3D_M_vSubVector (&stMove,p_stCurrentTranslation,p_stPreviousTranslation);
|
|
|
|
if (!MEC_fn_bIsNullVector(&stMove))
|
|
MTH3D_M_vNormalizeVector(&stNormMove,&stMove)
|
|
else
|
|
MTH3D_M_vNullVector(&stNormMove);
|
|
|
|
|
|
/* stack protection -> no more than 5 recursives calls. ( experience teaches it's enough )*/
|
|
g_lCallCounter++;
|
|
if (g_lCallCounter>5)
|
|
{
|
|
/* stay here */
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,p_stPreviousTranslation);
|
|
MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
|
|
return;
|
|
}
|
|
|
|
/* normal and tangent move */
|
|
POS_fn_vGetRotationVector ( hCurrentMatrix, &p_stX, &p_stY, &p_stZ );
|
|
MTH3D_M_vMulScalarVector ( &stNormalMove, MTH3D_M_xDotProductVector( &stMove, DNM_M_pDynamicsGetWallNormal (p_stDynamic)), DNM_M_pDynamicsGetWallNormal (p_stDynamic));
|
|
MTH3D_M_vSubVector ( &stTangentMove, &stMove, &stNormalMove );
|
|
|
|
if (g_lCallCounter==1)
|
|
MTH3D_M_vCopyVector ( &g_stFirstMove, &stTangentMove );
|
|
|
|
if (!MEC_fn_bIsNullVector(&stTangentMove))
|
|
MTH3D_M_vNormalizeVector(&stNormTangentMove,&stTangentMove)
|
|
else
|
|
MTH3D_M_vNullVector(&stNormTangentMove);
|
|
|
|
if (DNM_M_bDynamicsIsMechanicChange (p_stDynamic)) xNormalMove = C_xDNM_CLIMB_FIRST_NORMAL_MOVE;
|
|
else xNormalMove = MTH_M_xMul ( xSlope, MTH3D_M_xNormVector(&stTangentMove) );
|
|
|
|
if (MTH_M_bLess (xNormalMove,C_xDNM_CLIMB_DEFAULT_NORMAL_MOVE)) xNormalMove = C_xDNM_CLIMB_DEFAULT_NORMAL_MOVE;
|
|
|
|
p_stBackTranslation = POS_fn_p_stGetTranslationVector ( p_stPOS_BackPosition );
|
|
MTH3D_M_vAddVector ( p_stBackTranslation, p_stPreviousTranslation, &stTangentMove );
|
|
MTH3D_M_vMulScalarVector (&stVector, xNormalMove, DNM_M_pDynamicsGetWallNormal (p_stDynamic));
|
|
MTH3D_M_vAddVector ( p_stBackTranslation, p_stBackTranslation, &stVector );
|
|
|
|
p_stFrontTranslation = POS_fn_p_stGetTranslationVector ( p_stPOS_FrontPosition );
|
|
MTH3D_M_vAddVector ( p_stFrontTranslation, p_stPreviousTranslation, &stTangentMove );
|
|
MTH3D_M_vSubVector ( p_stFrontTranslation, p_stFrontTranslation, &stVector );
|
|
|
|
p_stClimbObstacle = NULL;
|
|
p_stSlideObstacle = NULL;
|
|
p_stEdgeObstacle = NULL;
|
|
p_stGroundObstacle = NULL;
|
|
|
|
/* call collisions*/
|
|
if(MEC_fn_bCollision(&lObstacle,g_a_stObstacle,p_stDynamic,hSupObj,p_stPOS_BackPosition,p_stPOS_FrontPosition,TRUE))
|
|
{
|
|
/* delete back faces */
|
|
MEC_fn_vDeleteClimbBackFace (lObstacle,g_a_stObstacle,p_stDynamic,&stNormTangentMove);
|
|
|
|
/* search first collided Climb faces and slide faces*/
|
|
for (lCounter=0; lCounter<lObstacle && !p_stClimbObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle + lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if ( (MEC_fn_bTypeOfGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle), C_xDNM_CLIMB_TYPE_GAME_MATERIAL)) && !(MEC_fn_bTypeOfGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle), C_xDNM_NO_COLLISION_TYPE_GAME_MATERIAL)) && (MEC_fn_bWallObstacle (p_stDynamic,p_stTmpObstacle)) )
|
|
p_stClimbObstacle = p_stTmpObstacle;
|
|
}
|
|
}
|
|
|
|
|
|
for (lCounter=0; lCounter<lObstacle && !p_stGroundObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle + lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if (MEC_fn_bGroundObstacle(p_stDynamic,p_stTmpObstacle))
|
|
{
|
|
p_stGroundObstacle = p_stTmpObstacle;
|
|
MEC_fn_vReportCollision (p_stDynamic,hSupObj,1,p_stGroundObstacle,0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p_stClimbObstacle)
|
|
{
|
|
bStop = FALSE;
|
|
for ( lCounter1=0; lCounter1<lObstacle && !bStop; lCounter1++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle + lCounter1;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stTmpObstacle), DNM_M_p_stObstacleGetNorm(p_stClimbObstacle) );
|
|
if (MTH_M_bLess(xDotProd,MTH_M_xDoubleToReal(0.707)))
|
|
{
|
|
MTH3D_M_vSubVector ( &stVector, DNM_M_p_stObstacleGetContact(p_stTmpObstacle), DNM_M_p_stObstacleGetContact(p_stClimbObstacle) );
|
|
xDotProd = MTH3D_M_xDotProductVector ( &stVector, DNM_M_p_stObstacleGetNorm(p_stClimbObstacle) );
|
|
if (MTH_M_bGreater ( xDotProd, MTH_M_xDoubleToReal(0.1) ))
|
|
// if (MTH_M_bGreaterZero ( xDotProd))
|
|
{
|
|
xDotProd = MTH3D_M_xDotProductVector ( &stNormTangentMove, DNM_M_p_stObstacleGetNorm(p_stTmpObstacle));
|
|
|
|
if
|
|
(
|
|
MEC_fn_bTypeOfGameMaterial ( DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle), C_xDNM_CLIMB_TYPE_GAME_MATERIAL )
|
|
&& !MEC_fn_bTypeOfGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle), C_xDNM_NO_COLLISION_TYPE_GAME_MATERIAL)
|
|
)
|
|
{
|
|
p_stSlideObstacle=NULL;
|
|
bStop = TRUE;
|
|
|
|
}
|
|
else if (MTH_M_bLess(xDotProd,xDotProdMin))
|
|
{
|
|
xDotProdMin = xDotProd;
|
|
p_stSlideObstacle = p_stTmpObstacle;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* else if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic))
|
|
{
|
|
for ( lCounter1=0; lCounter1<lObstacle && !p_stSlideObstacle; lCounter1++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle + lCounter1;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stTmpObstacle), DNM_M_pDynamicsGetWallNormal(p_stDynamic) );
|
|
if (MTH_M_bLess (xDotProd,MTH_M_xDoubleToReal(0.707)))
|
|
p_stSlideObstacle = p_stTmpObstacle;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
/* remove slide obstacle if it's a climb material */
|
|
if
|
|
(
|
|
p_stSlideObstacle
|
|
&& MEC_fn_bTypeOfGameMaterial ( DNM_M_hObstacleGetCollidedMaterial(p_stSlideObstacle), C_xDNM_CLIMB_TYPE_GAME_MATERIAL )
|
|
&& !MEC_fn_bTypeOfGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stSlideObstacle), C_xDNM_NO_COLLISION_TYPE_GAME_MATERIAL)
|
|
&& MEC_fn_bWallObstacle (p_stDynamic,p_stSlideObstacle)
|
|
)
|
|
{
|
|
xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stSlideObstacle), DNM_M_p_stObstacleGetNorm(p_stClimbObstacle) );
|
|
if (!MTH_M_bEqual(xDotProd,MTH_C_ZERO))
|
|
p_stSlideObstacle = NULL;
|
|
}
|
|
|
|
/* search ground to stop ( to stay compatible with previous climb mechanic )*/
|
|
if
|
|
(
|
|
DNM_M_bDynamicsIsCollisionReport(p_stDynamic)
|
|
&& ( (DNM_M_ulReportGetPrevSurfaceState(DNM_M_p_stDynamicsGetReport(p_stDynamic)) & C_WOT_ulGround) != C_WOT_ulGround )
|
|
&& !DNM_M_bDynamicsIsMechanicChange(p_stDynamic)
|
|
&& MTH_M_bLessZero (MTH3D_M_xGetZofVector(&stTangentMove))
|
|
)
|
|
{
|
|
for (lCounter2=0; lCounter2<lObstacle; lCounter2++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle + lCounter2;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if
|
|
(
|
|
!MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_NO_COLLISION_TYPE_GAME_MATERIAL)
|
|
&& MEC_fn_bGroundObstacle(p_stDynamic,p_stTmpObstacle)
|
|
)
|
|
{
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,p_stPreviousTranslation);
|
|
MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
|
|
DNM_M_vDynamicsSetStop (p_stDynamic,TRUE);
|
|
MEC_fn_vReportCollision (p_stDynamic,hSupObj,lObstacle,g_a_stObstacle,lCounter1-1);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p_stSlideObstacle && lCounter1>lCounter) lCounter=lCounter1;
|
|
|
|
/* report obstacles in the report.*/
|
|
MEC_fn_vReportCollision (p_stDynamic,hSupObj,lObstacle,g_a_stObstacle,lCounter-1);
|
|
|
|
/* we meet a climb face ...*/
|
|
if (p_stClimbObstacle)
|
|
{
|
|
DNM_M_vDynamicsSetWallNormal ( p_stDynamic, DNM_M_p_stObstacleGetNorm(p_stClimbObstacle) );
|
|
|
|
if(!p_stSlideObstacle)
|
|
{
|
|
if (!MEC_fn_bIsEdge(p_stClimbObstacle))
|
|
{
|
|
MTH3D_M_vAddVector (&stVector, p_stFrontTranslation, DNM_M_xObstacleGetTranslation (p_stClimbObstacle));
|
|
POS_fn_vSetTranslationVector ( hCurrentMatrix, &stVector );
|
|
}
|
|
else
|
|
{
|
|
/* p_SlideObstacle is used here as temporary variable */
|
|
for (lCounter=0; lCounter<lObstacle && !p_stSlideObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle + lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if ( MEC_fn_bWallObstacle ( p_stDynamic, p_stTmpObstacle ) && !MEC_fn_bIsEdge( p_stTmpObstacle ) )
|
|
p_stSlideObstacle = p_stTmpObstacle;
|
|
}
|
|
}
|
|
|
|
if (p_stSlideObstacle)
|
|
{
|
|
MTH3D_M_vAddVector (&stVector, p_stFrontTranslation, DNM_M_xObstacleGetTranslation (p_stSlideObstacle));
|
|
POS_fn_vSetTranslationVector ( hCurrentMatrix, &stVector );
|
|
p_stSlideObstacle = NULL;
|
|
}
|
|
else
|
|
{
|
|
MTH3D_M_vAddVector (&stVector, p_stFrontTranslation, DNM_M_xObstacleGetTranslation (p_stClimbObstacle));
|
|
POS_fn_vSetTranslationVector ( hCurrentMatrix, &stVector );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( p_stSlideObstacle && MEC_fn_bIsCollide(p_stSlideObstacle) && ( (g_lCallCounter>2) || DNM_M_bDynamicsIsMechanicChange(p_stDynamic) ) )
|
|
{
|
|
MEC_fn_vComputeAdjustVector (&stAdjustVector, p_stDynamic, lObstacle, g_a_stObstacle, lCounter-1);
|
|
|
|
xDotProd = MTH3D_M_xDotProductVector (&stAdjustVector,DNM_M_p_stObstacleGetNorm(p_stClimbObstacle));
|
|
MTH3D_M_vMulScalarVector (&stVector,xDotProd,DNM_M_p_stObstacleGetNorm(p_stClimbObstacle));
|
|
MTH3D_M_vSubVector (&stAdjustVector,&stAdjustVector,&stVector);
|
|
MTH3D_M_vAddVector (&stAdjustVector,&stAdjustVector,DNM_M_xObstacleGetTranslation (p_stClimbObstacle));
|
|
|
|
MTH3D_M_vAddVector (&stSafeTranslation, p_stFrontTranslation, &stAdjustVector);
|
|
MTH3D_M_vSubVector (&stVector, &stSafeTranslation, p_stPreviousTranslation);
|
|
MTH3D_M_vSubVector (&stMove,&stMove,&stVector);
|
|
|
|
}
|
|
else
|
|
/* we use its previous position that is safe.*/
|
|
MTH3D_M_vCopyVector (&stSafeTranslation,p_stPreviousTranslation);
|
|
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,&stSafeTranslation);
|
|
|
|
/* compute slide -> Current position is the new place were we try to go*/
|
|
MEC_fn_vWallObstacleManagement ( &stSlideMove, p_stDynamic, &stMove, DNM_M_p_stObstacleGetNorm(p_stClimbObstacle), DNM_M_p_stObstacleGetNorm(p_stSlideObstacle), xDT, TRUE );
|
|
|
|
xDotProd = MTH3D_M_xDotProductVector (&g_stFirstMove,&stSlideMove);
|
|
|
|
/* stWallMove contains the move due to wall slide. If it's not significant, it's no use to continue.*/
|
|
if (!MEC_fn_bIsNullVector(&stSlideMove)&&MTH_M_bGreaterEqualZero(xDotProd))
|
|
{
|
|
MEC_fn_vClimbObstacleManagement (p_stDynamic, hSupObj, xDT);
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
return;
|
|
}
|
|
else
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,&stSafeTranslation);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (p_stSlideObstacle)
|
|
{
|
|
// if ( p_stSlideObstacle && MEC_fn_bIsCollide(p_stSlideObstacle) )
|
|
{
|
|
MEC_fn_vComputeAdjustVector (&stAdjustVector, p_stDynamic, lObstacle, g_a_stObstacle, lCounter);
|
|
|
|
MTH3D_M_vAddVector (&stSafeTranslation, p_stFrontTranslation, &stAdjustVector);
|
|
MTH3D_M_vSubVector (&stVector, &stSafeTranslation, p_stPreviousTranslation);
|
|
MTH3D_M_vSubVector (&stMove,&stMove,&stVector);
|
|
|
|
}
|
|
// else
|
|
// MTH3D_M_vCopyVector (&stSafeTranslation,p_stPreviousTranslation);
|
|
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,&stSafeTranslation);
|
|
|
|
MEC_fn_vWallObstacleManagement ( &stSlideMove, p_stDynamic, &stMove, p_stY, DNM_M_p_stObstacleGetNorm(p_stSlideObstacle), xDT, TRUE );
|
|
|
|
xDotProd = MTH3D_M_xDotProductVector (&g_stFirstMove,&stSlideMove);
|
|
if (MTH_M_bLessZero(xDotProd))
|
|
{
|
|
/* stay here */
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,p_stPreviousTranslation);
|
|
MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
|
|
return;
|
|
}
|
|
|
|
if (!MEC_fn_bIsNullVector(&stSlideMove))
|
|
{
|
|
MEC_fn_vClimbObstacleManagement ( p_stDynamic, hSupObj, xDT );
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
return;
|
|
}
|
|
else
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,&stSafeTranslation);
|
|
}
|
|
else
|
|
{
|
|
POS_fn_vCopyMatrix ( hCurrentMatrix, hPreviousMatrix );
|
|
MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
|
|
DNM_M_vDynamicsSetStop ( p_stDynamic, TRUE );
|
|
|
|
/* resport previous state */
|
|
if (DNM_M_bDynamicsIsCollisionReport(p_stDynamic))
|
|
DNM_M_ulReportSetSurfaceState(DNM_M_p_stDynamicsGetReport(p_stDynamic),DNM_M_ulReportGetPrevSurfaceState (DNM_M_p_stDynamicsGetReport(p_stDynamic)) );
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* orient toward rock */
|
|
if ( p_stClimbObstacle && !MEC_fn_bIsEdge(p_stClimbObstacle) )
|
|
{
|
|
p_stNormal = DNM_M_p_stObstacleGetNorm (p_stClimbObstacle);
|
|
MTH3D_M_vSubVector (&stVector,p_stNormal,p_stY);
|
|
if (!MEC_fn_bIsNullVector(&stVector))
|
|
MEC_fn_vOrient ( p_stDynamic, p_stNormal );
|
|
}
|
|
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
return;
|
|
}
|
|
|
|
|
|
/* There is no obstacle at all.*/
|
|
POS_fn_vCopyMatrix ( hCurrentMatrix, hPreviousMatrix );
|
|
MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
|
|
DNM_M_vDynamicsSetStop (p_stDynamic,TRUE);
|
|
|
|
/* resport previous state */
|
|
if (DNM_M_bDynamicsIsCollisionReport(p_stDynamic))
|
|
DNM_M_ulReportSetSurfaceState(DNM_M_p_stDynamicsGetReport(p_stDynamic),DNM_M_ulReportGetPrevSurfaceState (DNM_M_p_stDynamicsGetReport(p_stDynamic)) );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void MEC_fn_vGroundObstacleManagement
|
|
(
|
|
struct DNM_stDynamics *p_stDynamic,
|
|
HIE_tdxHandleToSuperObject hSupObj,
|
|
MTH_tdxReal xDT
|
|
)
|
|
{
|
|
long lObstacle, lObstacle2;
|
|
long lCounter, lObstacleCounter;
|
|
long lWallCounter;
|
|
|
|
MTH_tdxReal xSlide;
|
|
MTH_tdxReal xFactor;
|
|
MTH_tdxReal xSpeedZ;
|
|
|
|
POS_tdstCompletePosition a2_stPosition[2];
|
|
POS_tdstCompletePosition *p_stPOS_DownPosition = a2_stPosition;
|
|
POS_tdstCompletePosition *p_stPOS_UpPosition = a2_stPosition+1;
|
|
POS_tdstCompletePosition stPreviousMatrix;
|
|
POS_tdxHandleToPosition hCurrentMatrix, hPreviousMatrix;
|
|
|
|
MTH3D_tdstVector stVector;
|
|
MTH3D_tdstVector stUpVector, stDownVector;
|
|
MTH3D_tdstVector stMove;
|
|
MTH3D_tdstVector stVertical;
|
|
MTH3D_tdstVector stNormalMove;
|
|
MTH3D_tdstVector stTangentMove;
|
|
MTH3D_tdstVector stAbsoluteTangentMove;
|
|
MTH3D_tdstVector stAdjustVector, stAdjustVector1;
|
|
MTH3D_tdstVector stPushVector;
|
|
MTH3D_tdstVector stWallMove;
|
|
MTH3D_tdstVector stSafeTranslation;
|
|
MTH3D_tdstVector stNormalizeTangentMove;
|
|
|
|
MTH3D_tdstVector *p_stCurrentTranslation;
|
|
MTH3D_tdstVector *p_stPreviousTranslation;
|
|
MTH3D_tdstVector *p_stUpTranslation;
|
|
MTH3D_tdstVector *p_stDownTranslation;
|
|
MTH3D_tdstVector *p_stNormal;
|
|
|
|
ACP_tdxBool bStep;
|
|
ACP_tdxBool bAdjust;
|
|
ACP_tdxBool bFirstGround;
|
|
ACP_tdxBool bOk = TRUE;
|
|
ACP_tdxBool bWallCheck = FALSE;
|
|
ACP_tdxBool bSqueezeByWall = FALSE;
|
|
ACP_tdxBool bCorner = FALSE;
|
|
|
|
MTH_tdxReal xMinSlope;
|
|
MTH_tdxReal xMaxSlope;
|
|
MTH_tdxReal xDotProduct;
|
|
MTH_tdxReal xNormTangentMove;
|
|
MTH_tdxReal xWallDistance = MTH_C_InfinitPlus;
|
|
MTH_tdxReal xTmpReal;
|
|
|
|
DNM_tdstMecObstacle *p_stGroundObstacle, *p_stWallObstacle, *p_stTmpObstacle, *p_stWallObstacle2, *p_stWallEdgeObstacle, *p_stMobileObstacle, stGroundObstacle;
|
|
DNM_tdstObstacle *p_stObstacle;
|
|
HIE_tdxHandleToSuperObject hSupObjCol;
|
|
|
|
#ifdef DNM_DEBUG
|
|
if(p_stDynamic == NULL)
|
|
return;
|
|
if(!HIE_fn_bIsSuperObjectValid(hSupObj))
|
|
return;
|
|
#endif
|
|
|
|
/* variable init*/
|
|
xMinSlope = MEC_fn_xMinSlope ( p_stDynamic);
|
|
xMaxSlope = MEC_fn_xMaxSlope ( p_stDynamic);
|
|
MTH3D_M_vSetVectorElements( &stVertical, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE);
|
|
MTH3D_M_vNullVector (&stAdjustVector);
|
|
MTH3D_M_vNullVector (&stPushVector);
|
|
p_stGroundObstacle = NULL;
|
|
p_stWallObstacle = NULL;
|
|
p_stWallEdgeObstacle = NULL;
|
|
p_stObstacle = NULL;
|
|
bAdjust = (g_lCallCounter==0);
|
|
|
|
/* Matrix init */
|
|
hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
|
|
hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
|
|
|
|
/* get previous obstacle if there is one*/
|
|
if (DNM_M_bDynamicsIsCollisionReport(p_stDynamic))
|
|
p_stObstacle = DNM_M_p_stReportGetGround (DNM_M_p_stDynamicsGetReport (p_stDynamic));
|
|
|
|
POS_fn_vCopyMatrix(p_stPOS_DownPosition, hCurrentMatrix);
|
|
POS_fn_vCopyMatrix(p_stPOS_UpPosition, hPreviousMatrix);
|
|
|
|
/* collision translation*/
|
|
/* if we don't call collisions each frame, we retrieve last collide position, and make as*/
|
|
/* if it's the PreviousMatrix.*/
|
|
if (fn_ucCollSetGetCollComputeFrequencySO(hSupObj)>1)
|
|
{
|
|
hPreviousMatrix = &stPreviousMatrix;
|
|
POS_fn_vCopyMatrix (hPreviousMatrix,DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic));
|
|
MEC_fn_vGetCollisionTranslation (p_stDynamic,hPreviousMatrix);
|
|
}
|
|
|
|
|
|
p_stCurrentTranslation = POS_fn_p_stGetTranslationVector ( hCurrentMatrix );
|
|
p_stPreviousTranslation = POS_fn_p_stGetTranslationVector ( hPreviousMatrix );
|
|
MTH3D_M_vSubVector (&stMove,p_stCurrentTranslation,p_stPreviousTranslation);
|
|
|
|
if (DNM_M_bDynamicsIsMechanicChange(p_stDynamic) && !g_lCallCounter)
|
|
{
|
|
if (MEC_fn_bCollision(&lObstacle,g_a_stObstacle,p_stDynamic,hSupObj,hPreviousMatrix,hPreviousMatrix,TRUE))
|
|
{
|
|
MEC_fn_vDeleteBaseBackFace ( lObstacle,g_a_stObstacle, p_stDynamic );
|
|
MEC_fn_vDeleteNullTranslationObstacle ( lObstacle, g_a_stObstacle );
|
|
MEC_fn_vComputeAdjustVector (&stAdjustVector, p_stDynamic, lObstacle, g_a_stObstacle, lObstacle);
|
|
MTH3D_M_vAddVector (p_stPreviousTranslation,p_stPreviousTranslation,&stAdjustVector);
|
|
}
|
|
}
|
|
|
|
/* stack protection -> no more than 5 recursives calls. ( experience teaches it's enough )*/
|
|
g_lCallCounter++;
|
|
if (g_lCallCounter>5)
|
|
{
|
|
DNM_M_vDynamicsSetForceSafeWalk (p_stDynamic,TRUE);
|
|
|
|
if (MEC_fn_bCollision(&lObstacle,g_a_stObstacle,p_stDynamic,hSupObj,hPreviousMatrix,hPreviousMatrix,TRUE))
|
|
{
|
|
MEC_fn_vDeleteBaseBackFace ( lObstacle,g_a_stObstacle, p_stDynamic );
|
|
MEC_fn_vDeleteNullTranslationObstacle ( lObstacle, g_a_stObstacle );
|
|
MEC_fn_vComputeAdjustVector (&stAdjustVector, p_stDynamic, lObstacle, g_a_stObstacle, lObstacle);
|
|
MTH3D_M_vAddVector (p_stPreviousTranslation,p_stPreviousTranslation,&stAdjustVector);
|
|
}
|
|
|
|
/* stay here */
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,p_stPreviousTranslation);
|
|
MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
|
|
return;
|
|
}
|
|
|
|
/* normal obstacle*/
|
|
/* If we are in contact with an obstacle, use its normal.*/
|
|
/* if not, make as if previous obstacle is horizontal.*/
|
|
p_stNormal = &stVertical;
|
|
|
|
if (p_stObstacle && !DNM_M_bDynamicsIsMechanicChange(p_stDynamic))
|
|
{
|
|
p_stNormal = DNM_M_p_stObstacleGetNorm (p_stObstacle);
|
|
if (MTH3D_M_bIsNullVector(p_stNormal))
|
|
{
|
|
p_stNormal = &stVertical;
|
|
}
|
|
}
|
|
|
|
/* normal and tangent move / previous ground obstacle met.*/
|
|
xDotProduct = MTH3D_M_xDotProductVector (&stMove,p_stNormal);
|
|
MTH3D_M_vMulScalarVector (&stNormalMove,xDotProduct,p_stNormal);
|
|
MTH3D_M_vSubVector (&stTangentMove,&stMove,&stNormalMove);
|
|
|
|
xNormTangentMove = MTH3D_M_xNormVector(&stTangentMove);
|
|
|
|
if (MTH_M_bGreater(xNormTangentMove,MTH_M_xDoubleToReal(1e-3)))
|
|
MTH3D_M_vDivScalarVector ( &stNormalizeTangentMove, &stTangentMove, xNormTangentMove )
|
|
else
|
|
MTH3D_M_vNullVector ( &stNormalizeTangentMove );
|
|
|
|
|
|
if (g_lCallCounter==1)
|
|
{
|
|
g_bHighSpeed = MTH_M_bGreater(xNormTangentMove,C_ulDNM_RAYMAN_ZDM_RADIUS) || DNM_M_bDynamicsIsForceSafeWalk(p_stDynamic) || DNM_M_bDynamicsIsMechanicChange(p_stDynamic);
|
|
DNM_M_vDynamicsSetForceSafeWalk ( p_stDynamic, FALSE );
|
|
}
|
|
else if (!g_bHighSpeed)
|
|
{
|
|
if (DNM_M_bDynamicsIsForceSafeWalk(p_stDynamic))
|
|
g_bHighSpeed = TRUE;
|
|
}
|
|
|
|
if (DNM_M_bDynamicsIsComplexSize(p_stDynamic) && MEC_fn_bIsPlatform(p_stDynamic))
|
|
{
|
|
MTH3D_M_vSubVector (&stAbsoluteTangentMove,p_stCurrentTranslation,POS_fn_p_stGetTranslationVector(DNM_M_p_stDynamicsGetAbsolutePreviousMatrix(p_stDynamic)));
|
|
xDotProduct = MTH3D_M_xDotProductVector (&stAbsoluteTangentMove,p_stNormal);
|
|
MTH3D_M_vMulScalarVector (&stVector,xDotProduct,p_stNormal);
|
|
MTH3D_M_vSubVector (&stAbsoluteTangentMove,&stAbsoluteTangentMove,&stVector);
|
|
}
|
|
else
|
|
MTH3D_M_vCopyVector ( &stAbsoluteTangentMove, &stTangentMove );
|
|
|
|
/* There is only a normal move. Probably, the actor falls with its gravity, so we call "jump" mechanic.*/
|
|
if ( MTH_M_bLess(xNormTangentMove,C_xDNM_NUL_MOVE) && MTH_M_bGreater(MTH3D_M_xNormVector(&stNormalMove),C_xDNM_NUL_MOVE) && ( !DNM_M_bDynamicsIsComplexSize(p_stDynamic) || !MEC_fn_bIsPlatform(p_stDynamic) ) && !DNM_M_bDynamicsIsMechanicChange(p_stDynamic) )
|
|
{
|
|
MEC_fn_vBaseObstacleManagement ( p_stDynamic, hSupObj, xDT );
|
|
|
|
if (DNM_M_ulReportGetSurfaceState(&g_stReport)&C_WOT_ulGround)
|
|
{
|
|
p_stGroundObstacle = DNM_M_p_stReportGetGround (&g_stReport);
|
|
xSlide = MEC_fn_xGetSlide (p_stDynamic,p_stGroundObstacle);
|
|
if (MTH_M_bEqual(xSlide,MTH_C_ZERO)) DNM_M_vDynamicsSetNoGravity (p_stDynamic,TRUE);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/* This part of the code compute the move we are going to pass to collisions.*/
|
|
/**/
|
|
/**/
|
|
/**/
|
|
/**/
|
|
/* The actor walk : P : previous position*/
|
|
/* C : current position ( it's an example )*/
|
|
/**/
|
|
/**/
|
|
/* O X <- p_stPOS_UpPosition*/
|
|
/* | **/
|
|
/* / \ **/
|
|
/* |-------->* */
|
|
/* / \ **/
|
|
/* -----------------P---------*---------------------------------------------------------------------*/
|
|
/* **/
|
|
/* **/
|
|
/* C*/
|
|
/* **/
|
|
/* * */
|
|
/* X <- p_stPOS_DownPosition*/
|
|
/**/
|
|
/**/
|
|
/**/
|
|
/**/
|
|
|
|
xSpeedZ = MTH_M_xMul ( MTH3D_M_xGetZofVector (DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic)), xDT );
|
|
|
|
xFactor = MTH_M_xMul (xMinSlope, xNormTangentMove);
|
|
if (MTH_M_bGreater (xFactor,MTH_M_xNeg(C_xDNM_ON_GROUND_DEFAULT_NORMAL_MOVE))) xFactor = MTH_M_xNeg(C_xDNM_ON_GROUND_DEFAULT_NORMAL_MOVE);
|
|
|
|
if (DNM_M_bDynamicsIsMechanicChange(p_stDynamic))
|
|
if (MTH_M_bGreater (xFactor,xSpeedZ)) xFactor = xSpeedZ;
|
|
|
|
p_stDownTranslation = POS_fn_p_stGetTranslationVector ( p_stPOS_DownPosition );
|
|
MTH3D_M_vCopyVector ( p_stDownTranslation, p_stPreviousTranslation);
|
|
MTH3D_M_vAddVector (p_stDownTranslation,p_stDownTranslation,&stTangentMove);
|
|
MTH3D_M_vMulScalarVector (&stDownVector,xFactor,p_stNormal);
|
|
MTH3D_M_vAddVector (p_stDownTranslation,p_stDownTranslation,&stDownVector);
|
|
|
|
lObstacle2 = 0;
|
|
if (g_bHighSpeed)
|
|
{
|
|
p_stUpTranslation = POS_fn_p_stGetTranslationVector ( p_stPOS_UpPosition );
|
|
MTH3D_M_vCopyVector ( p_stUpTranslation, p_stPreviousTranslation);
|
|
MTH3D_M_vAddVector (p_stUpTranslation,p_stUpTranslation,&stTangentMove);
|
|
|
|
if (MEC_fn_bCollision(&lObstacle2,g_a_stObstacle,p_stDynamic,hSupObj,hPreviousMatrix,p_stPOS_UpPosition,TRUE))
|
|
{
|
|
for (lCounter=0; lCounter<lObstacle2; lCounter++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle+lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if (!MEC_fn_bWallObstacle(p_stDynamic,p_stTmpObstacle))
|
|
MEC_fn_vInvalidateObstacle (p_stTmpObstacle);
|
|
// else
|
|
// {
|
|
// xDotProduct = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stTmpObstacle), &stNormalizeTangentMove );
|
|
// if ( MTH_M_bGreater(xDotProduct,MTH_M_xDoubleToReal(1e-3)) )
|
|
// if ( MTH_M_bGreaterZero(xDotProduct) )
|
|
// MEC_fn_vInvalidateObstacle(p_stTmpObstacle);
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
xFactor = MTH_M_xMul (xMaxSlope, xNormTangentMove);
|
|
if (MTH_M_bLess (xFactor,C_xDNM_ON_GROUND_DEFAULT_NORMAL_MOVE)) xFactor = C_xDNM_ON_GROUND_DEFAULT_NORMAL_MOVE;
|
|
|
|
p_stUpTranslation = POS_fn_p_stGetTranslationVector ( p_stPOS_UpPosition );
|
|
MTH3D_M_vCopyVector ( p_stUpTranslation, p_stPreviousTranslation);
|
|
MTH3D_M_vAddVector (p_stUpTranslation,p_stUpTranslation,&stTangentMove);
|
|
MTH3D_M_vMulScalarVector (&stUpVector,xFactor,p_stNormal);
|
|
MTH3D_M_vAddVector (p_stUpTranslation,p_stUpTranslation,&stUpVector);
|
|
|
|
/* call collisions*/
|
|
COL_g_lMaxNumberOfCollisions = COL_C_xMaxNumberOfCollisions - lObstacle2;
|
|
MEC_fn_bCollision(&lObstacle,g_a_stObstacle+lObstacle2,p_stDynamic,hSupObj,p_stPOS_UpPosition,p_stPOS_DownPosition,TRUE);
|
|
lObstacle += lObstacle2;
|
|
COL_g_lMaxNumberOfCollisions = COL_C_xMaxNumberOfCollisions;
|
|
|
|
if (lObstacle)
|
|
{
|
|
p_stGroundObstacle = MEC_fn_pSelectGround (p_stDynamic,lObstacle-lObstacle2,g_a_stObstacle+lObstacle2,&bFirstGround);
|
|
|
|
if (p_stGroundObstacle)
|
|
bStep = MEC_fn_bDetectStep (p_stDynamic, lObstacle-lObstacle2, g_a_stObstacle+lObstacle2, p_stGroundObstacle, &stAbsoluteTangentMove );
|
|
else
|
|
bStep = FALSE;
|
|
|
|
/* the actor falls ?*/
|
|
/* test only if he desn't climb a step */
|
|
// if (!bStep && (g_lCallCounter==1)) MEC_fn_vEdgeAnalysis (p_stDynamic, lObstacle, g_a_stObstacle, p_stGroundObstacle);
|
|
if (!bStep && (g_lCallCounter==1)) MEC_fn_vEdgeAnalysis (p_stDynamic, lObstacle-lObstacle2, g_a_stObstacle+lObstacle2, p_stGroundObstacle);
|
|
|
|
/* delete unnecessary obstacles*/
|
|
if (bFirstGround) MEC_fn_vDeleteWallEdge (lObstacle, g_a_stObstacle, p_stDynamic);
|
|
MEC_fn_vDeleteUnderGroundWall (lObstacle, g_a_stObstacle, p_stDynamic,p_stGroundObstacle);
|
|
// MEC_fn_vDeleteOnGroundBackFace (lObstacle-lObstacle2, g_a_stObstacle+lObstacle2, p_stDynamic, &stAbsoluteTangentMove, p_stGroundObstacle );
|
|
MEC_fn_vDeleteOnGroundBackFace (lObstacle, g_a_stObstacle, p_stDynamic, &stAbsoluteTangentMove, p_stGroundObstacle );
|
|
|
|
/* crash test*/
|
|
if (MEC_fn_bMainActor(hSupObj) && (g_lCallCounter==1))
|
|
MEC_fn_vCrashAnalysis ( p_stDynamic,lObstacle, g_a_stObstacle );
|
|
|
|
|
|
/* search first collided ground and wall */
|
|
p_stWallObstacle = NULL;
|
|
p_stMobileObstacle = NULL;
|
|
lObstacleCounter = 0;
|
|
|
|
if (lObstacle2)
|
|
{
|
|
for (lCounter=0; lCounter<lObstacle2; lCounter++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle+lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if ( MEC_fn_bIsCollide(p_stTmpObstacle) && !MEC_fn_bGroundObstacle(p_stDynamic,p_stTmpObstacle) )
|
|
bWallCheck = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (lCounter=0; lCounter<lObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle+lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if (MEC_fn_bGroundObstacle (p_stDynamic,p_stTmpObstacle))
|
|
{
|
|
if (p_stGroundObstacle==p_stTmpObstacle)
|
|
lObstacleCounter = lCounter;
|
|
}
|
|
else
|
|
{
|
|
if ( ((DNM_M_eObstacleGetType(p_stTmpObstacle)&DNM_ObsType_Mobile)==DNM_ObsType_Mobile) && !p_stMobileObstacle )
|
|
{
|
|
hSupObjCol = DNM_M_p_stObstacleGetObject (p_stTmpObstacle);
|
|
|
|
if (HIE_fn_bIsSuperObjectValid(hSupObjCol))
|
|
{
|
|
hSupObjCol = MEC_fn_hGetFatherActor (hSupObjCol);
|
|
|
|
if ((fn_ulStandardGameGetCustomBitsSO(hSupObjCol) & C_ulDNM_CAN_PUSH_RAYMAN_CUSTOM_BIT) == C_ulDNM_CAN_PUSH_RAYMAN_CUSTOM_BIT)
|
|
p_stMobileObstacle = p_stTmpObstacle;
|
|
}
|
|
}
|
|
|
|
if (MEC_fn_bWallObstacle (p_stDynamic,p_stTmpObstacle))
|
|
{
|
|
MTH3D_M_vSubVector ( &stVector, DNM_M_p_stObstacleGetContact(p_stTmpObstacle), p_stPreviousTranslation );
|
|
|
|
xTmpReal = MTH_M_xAdd ( MTH_M_xSqr(MTH3D_M_xGetXofVector(&stVector)),MTH_M_xSqr(MTH3D_M_xGetYofVector(&stVector)) );
|
|
|
|
if (MTH_M_bLess(xTmpReal,xWallDistance))
|
|
{
|
|
p_stWallObstacle = p_stTmpObstacle;
|
|
lObstacleCounter = lCounter;
|
|
xWallDistance = xTmpReal;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* swim case : we make as if the ceilling is a wall */
|
|
if (!p_stWallObstacle)
|
|
{
|
|
p_stWallObstacle = p_stTmpObstacle;
|
|
lObstacleCounter = lCounter;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* report obstacles in the report.*/
|
|
MEC_fn_vReportCollision (p_stDynamic,hSupObj,lObstacle,g_a_stObstacle,lObstacleCounter);
|
|
|
|
if (DNM_M_bDynamicsIsCanFall(p_stDynamic) && DNM_M_bDynamicsIsNeverFall(p_stDynamic) && !p_stWallObstacle)
|
|
{
|
|
MTH3D_M_vAddVector (p_stCurrentTranslation,p_stPreviousTranslation,&stTangentMove);
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
return;
|
|
}
|
|
|
|
/* we meet a ground ...*/
|
|
if (p_stGroundObstacle)
|
|
{
|
|
xSlide = MEC_fn_xGetSlide (p_stDynamic,p_stGroundObstacle);
|
|
if (MTH_M_bEqual(xSlide,MTH_C_ZERO)) DNM_M_vDynamicsSetNoGravity (p_stDynamic,TRUE);
|
|
|
|
if(!p_stWallObstacle)
|
|
{
|
|
/* and just a ground, so we can walk on it and it's all is ok.*/
|
|
MTH3D_M_vAddVector (&stVector, p_stDownTranslation, DNM_M_xObstacleGetTranslation (p_stGroundObstacle));
|
|
POS_fn_vSetTranslationVector ( hCurrentMatrix, &stVector );
|
|
|
|
if ( (g_lCallCounter==1) && ( DNM_M_bDynamicsIsCollisionReport(p_stDynamic) && ((DNM_M_ulReportGetPrevSurfaceState(DNM_M_p_stDynamicsGetReport(p_stDynamic))&C_WOT_ulWall)!=C_WOT_ulWall) ))
|
|
DNM_M_vDynamicsSetWallAdjust(p_stDynamic,TRUE);
|
|
|
|
}
|
|
else
|
|
{
|
|
if ( p_stMobileObstacle && (g_lCallCounter==1) )
|
|
{
|
|
DNM_M_MecObstacleCopyClone ( &stGroundObstacle, p_stGroundObstacle );
|
|
DNM_M_vDynamicsSetForceSafeWalk (p_stDynamic,TRUE);
|
|
|
|
|
|
if(MEC_fn_bCollision(&lObstacle,g_a_stObstacle,p_stDynamic,hSupObj,hPreviousMatrix,hPreviousMatrix,TRUE))
|
|
{
|
|
MEC_fn_vDeleteBaseBackFace ( lObstacle,g_a_stObstacle, p_stDynamic );
|
|
MEC_fn_vDeleteNullTranslationObstacle ( lObstacle, g_a_stObstacle );
|
|
|
|
lWallCounter = 0;
|
|
for (lCounter=0; lCounter<lObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle + lCounter;
|
|
if ( MEC_fn_bIsObstacleValid(p_stTmpObstacle) )
|
|
{
|
|
if ( MEC_fn_bWallObstacle(p_stDynamic,p_stTmpObstacle) && ((DNM_M_eObstacleGetType(p_stTmpObstacle)&DNM_ObsType_Mobile)!=DNM_ObsType_Mobile) )
|
|
lWallCounter++;
|
|
|
|
if (p_stMobileObstacle && MTH_M_bLess(MTH3D_M_xDotProductVector(DNM_M_p_stObstacleGetNorm(p_stMobileObstacle),DNM_M_p_stObstacleGetNorm(p_stTmpObstacle)),MTH_M_xDoubleToReal(-0.5))) /* 60° */
|
|
bSqueezeByWall = TRUE;
|
|
}
|
|
}
|
|
|
|
if (lWallCounter>0)
|
|
{
|
|
/* we collide at least one wall of the map -> complete method */
|
|
MEC_fn_vComputeAdjustVector (&stAdjustVector, p_stDynamic, lObstacle, g_a_stObstacle, lObstacle);
|
|
MTH3D_M_vAddVector ( p_stPreviousTranslation, p_stPreviousTranslation, &stAdjustVector );
|
|
MTH3D_M_vAddVector ( p_stCurrentTranslation, p_stPreviousTranslation, &stMove );
|
|
}
|
|
else
|
|
{
|
|
/* we collide only the ZDR */
|
|
p_stWallObstacle2 = NULL;
|
|
|
|
for (lCounter=0; lCounter<lObstacle && !p_stWallObstacle2; lCounter++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle + lCounter;
|
|
if ( MEC_fn_bIsObstacleValid(p_stTmpObstacle) )
|
|
{
|
|
if (p_stTmpObstacle && ((DNM_M_eObstacleGetType(p_stTmpObstacle)&DNM_ObsType_Mobile)==DNM_ObsType_Mobile))
|
|
{
|
|
p_stWallObstacle2 = p_stTmpObstacle;
|
|
|
|
if (MTH_M_bLess(MTH3D_M_xNormVector(DNM_M_xObstacleGetTranslation(p_stWallObstacle2)),C_ulDNM_RAYMAN_ZDM_RADIUS))
|
|
{
|
|
xDotProduct = MTH3D_M_xDotProductVector (DNM_M_xObstacleGetTranslation(p_stWallObstacle2),DNM_M_p_stObstacleGetNorm(&stGroundObstacle));
|
|
MTH3D_M_vMulScalarVector (&stVector,xDotProduct,DNM_M_p_stObstacleGetNorm(&stGroundObstacle));
|
|
MTH3D_M_vSubVector (&stVector,DNM_M_xObstacleGetTranslation(p_stWallObstacle2),&stVector);
|
|
MTH3D_M_vAddVector ( p_stPreviousTranslation, p_stPreviousTranslation, &stVector );
|
|
MTH3D_M_vAddVector ( p_stCurrentTranslation, p_stPreviousTranslation, &stMove );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MEC_fn_vGroundObstacleManagement ( p_stDynamic, hSupObj, xDT );
|
|
}
|
|
else
|
|
{
|
|
if (DNM_M_bDynamicsIsWallAdjust(p_stDynamic) && ( DNM_M_bDynamicsIsCollisionReport(p_stDynamic) && ((DNM_M_ulReportGetPrevSurfaceState(DNM_M_p_stDynamicsGetReport(p_stDynamic))&C_WOT_ulWall)!=C_WOT_ulWall) ) )
|
|
{
|
|
bWallCheck=TRUE;
|
|
DNM_M_vDynamicsSetWallAdjust(p_stDynamic,FALSE);
|
|
}
|
|
|
|
DNM_M_vDynamicsSetForceSafeWalk (p_stDynamic,TRUE);
|
|
|
|
/* and a wall. The actor must slide on the wall.*/
|
|
if ( p_stWallObstacle && ( DNM_M_bDynamicsIsMechanicChange(p_stDynamic) || (DNM_M_bDynamicsIsComplexSize(p_stDynamic) && MEC_fn_bIsPlatform(p_stDynamic)) || bWallCheck || bSqueezeByWall ) && MEC_fn_bIsCollide(p_stWallObstacle) && MTH_M_bEqualZero(xSlide) )
|
|
{
|
|
bOk = MEC_fn_vComputeAdjustVector (&stAdjustVector, p_stDynamic, lObstacle-lObstacle2, g_a_stObstacle+lObstacle2, lObstacle-lObstacle2);
|
|
if (lObstacle2)
|
|
{
|
|
bOk |= MEC_fn_vComputeAdjustVector (&stAdjustVector1, p_stDynamic, lObstacle2, g_a_stObstacle, lObstacle2);
|
|
}
|
|
else
|
|
{
|
|
MTH3D_M_vNullVector (&stAdjustVector1);
|
|
}
|
|
|
|
if ( !lObstacle2 || MEC_fn_bIsNullVector(&stAdjustVector) || MEC_fn_bIsNullVector(&stAdjustVector1) )
|
|
{
|
|
MTH3D_M_vAddVector ( &stAdjustVector, &stAdjustVector, &stAdjustVector1 );
|
|
}
|
|
else
|
|
{
|
|
MTH3D_M_vNormalizeVector ( &stVector, &stAdjustVector1 );
|
|
xDotProduct = MTH3D_M_xDotProductVector (&stAdjustVector,&stVector);
|
|
if (MTH_M_bLess(xDotProduct,MTH3D_M_xNormVector(&stAdjustVector1)))
|
|
{
|
|
MTH3D_M_vMulScalarVector (&stVector,xDotProduct,&stVector);
|
|
MTH3D_M_vSubVector (&stAdjustVector,&stAdjustVector,&stVector);
|
|
MTH3D_M_vAddVector (&stAdjustVector,&stAdjustVector,&stAdjustVector1);
|
|
}
|
|
}
|
|
|
|
xDotProduct = MTH3D_M_xDotProductVector (&stAdjustVector,DNM_M_p_stObstacleGetNorm(p_stGroundObstacle));
|
|
MTH3D_M_vMulScalarVector (&stVector,xDotProduct,DNM_M_p_stObstacleGetNorm(p_stGroundObstacle));
|
|
MTH3D_M_vSubVector (&stAdjustVector,&stAdjustVector,&stVector);
|
|
MTH3D_M_vAddVector (&stAdjustVector,&stAdjustVector,DNM_M_xObstacleGetTranslation (p_stGroundObstacle));
|
|
|
|
|
|
if (!DNM_M_bDynamicsIsSwim(p_stDynamic) /*&& !DNM_M_bDynamicsIsMechanicChange(p_stDynamic)*/)
|
|
{
|
|
xDotProduct = MTH3D_M_xDotProductVector (&stAdjustVector,DNM_M_p_stObstacleGetNorm(p_stGroundObstacle));
|
|
MTH3D_M_vMulScalarVector (&stVector,xDotProduct,DNM_M_p_stObstacleGetNorm(p_stGroundObstacle));
|
|
MTH3D_M_vSubVector (&stAdjustVector,&stAdjustVector,&stVector);
|
|
MTH3D_M_vAddVector (&stAdjustVector,&stAdjustVector,DNM_M_xObstacleGetTranslation (p_stGroundObstacle));
|
|
}
|
|
|
|
MTH3D_M_vAddVector (&stSafeTranslation, p_stDownTranslation, &stAdjustVector);
|
|
MTH3D_M_vSubVector (&stVector, &stSafeTranslation, p_stPreviousTranslation);
|
|
MTH3D_M_vSubVector (&stMove,&stMove,&stVector);
|
|
}
|
|
else
|
|
/* we use its previous position that is safe.*/
|
|
MTH3D_M_vCopyVector (&stSafeTranslation,p_stPreviousTranslation);
|
|
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,&stSafeTranslation);
|
|
|
|
/* compute wall slide -> Current position is the new place were we try to go*/
|
|
MEC_fn_vWallObstacleManagement ( &stWallMove, p_stDynamic, &stMove, DNM_M_p_stObstacleGetNorm(p_stGroundObstacle), DNM_M_p_stObstacleGetNorm(p_stWallObstacle), xDT, FALSE );
|
|
|
|
if (bOk && !(DNM_M_bDynamicsIsComplexSize(p_stDynamic) && MEC_fn_bIsPlatform(p_stDynamic)))
|
|
{
|
|
/* stWallMove contains the move due to wall slide. If it's not significant, it's no use to continue.*/
|
|
MTH3D_M_vSubVector ( &stVector, &stMove, &stWallMove );
|
|
// if (!MEC_fn_bIsNullVector(&stVector))
|
|
{
|
|
if (!MEC_fn_bIsNullVector(&stWallMove))
|
|
MEC_fn_vGroundObstacleManagement (p_stDynamic, hSupObj, xDT);
|
|
else
|
|
{
|
|
/* change z to be sure actor is in contact with ground */
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,&stSafeTranslation);
|
|
}
|
|
}
|
|
// else
|
|
// {
|
|
// MTH3D_M_vAddVector (&stVector, p_stDownTranslation, DNM_M_xObstacleGetTranslation (p_stGroundObstacle));
|
|
// POS_fn_vSetTranslationVector ( hCurrentMatrix, &stVector );
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
if (MEC_fn_bCollision(&lObstacle,g_a_stObstacle,p_stDynamic,hSupObj,hCurrentMatrix,hCurrentMatrix,TRUE))
|
|
{
|
|
MEC_fn_vDeleteBaseBackFace ( lObstacle,g_a_stObstacle, p_stDynamic );
|
|
MEC_fn_vDeleteNullTranslationObstacle ( lObstacle, g_a_stObstacle );
|
|
MEC_fn_vComputeAdjustVector (&stAdjustVector, p_stDynamic, lObstacle, g_a_stObstacle, lObstacle);
|
|
MTH3D_M_vAddVector (p_stCurrentTranslation,p_stCurrentTranslation,&stAdjustVector);
|
|
}
|
|
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
/* if (lObstacle2>0)
|
|
{
|
|
for (lCounter=0; lCounter<lObstacle2 && !bWall; lCounter++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle+lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle))
|
|
{
|
|
if (MEC_fn_bWallObstacle (p_stDynamic,p_stTmpObstacle))
|
|
bWall=TRUE;
|
|
}
|
|
}
|
|
} */
|
|
|
|
if ( p_stWallObstacle /*&& (!g_bHighSpeed||bWall)*/ )
|
|
{
|
|
if ( DNM_M_bDynamicsIsCollisionReport(p_stDynamic) && ((DNM_M_ulReportGetPrevSurfaceState(DNM_M_p_stDynamicsGetReport(p_stDynamic))&C_WOT_ulWall)!=C_WOT_ulWall) )
|
|
bWallCheck=TRUE;
|
|
|
|
/* there is no ground. So we can't walk.*/
|
|
MEC_fn_vComputeAdjustVector (&stAdjustVector, p_stDynamic, lObstacle-lObstacle2, g_a_stObstacle+lObstacle2, lObstacle-lObstacle2);
|
|
if (lObstacle2)
|
|
MEC_fn_vComputeAdjustVector (&stAdjustVector1, p_stDynamic, lObstacle2, g_a_stObstacle, lObstacle2);
|
|
else
|
|
MTH3D_M_vNullVector (&stAdjustVector1);
|
|
|
|
if ( !lObstacle2 || MEC_fn_bIsNullVector(&stAdjustVector) || MEC_fn_bIsNullVector(&stAdjustVector1) )
|
|
{
|
|
MTH3D_M_vAddVector ( &stAdjustVector, &stAdjustVector, &stAdjustVector1 );
|
|
}
|
|
else
|
|
{
|
|
MTH3D_M_vNormalizeVector ( &stVector, &stAdjustVector1 );
|
|
xDotProduct = MTH3D_M_xDotProductVector (&stAdjustVector,&stVector);
|
|
if (MTH_M_bLess(xDotProduct,MTH3D_M_xNormVector(&stAdjustVector1)))
|
|
{
|
|
MTH3D_M_vMulScalarVector (&stVector,xDotProduct,&stVector);
|
|
MTH3D_M_vSubVector (&stAdjustVector,&stAdjustVector,&stVector);
|
|
MTH3D_M_vAddVector (&stAdjustVector,&stAdjustVector,&stAdjustVector1);
|
|
}
|
|
}
|
|
|
|
MTH3D_M_vAddVector (&stSafeTranslation, p_stDownTranslation, &stAdjustVector);
|
|
|
|
MTH3D_M_vSubVector (&stVector, &stSafeTranslation, p_stPreviousTranslation);
|
|
MTH3D_M_vSubVector (&stMove,&stMove,&stVector);
|
|
|
|
|
|
DNM_M_vDynamicsSetForceSafeWalk (p_stDynamic,TRUE);
|
|
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,&stSafeTranslation);
|
|
|
|
/* We slide on the wall, and hope to find a ground under the new position.*/
|
|
MEC_fn_vWallObstacleManagement ( &stWallMove, p_stDynamic, &stMove, p_stNormal, DNM_M_p_stObstacleGetNorm(p_stWallObstacle), xDT, FALSE );
|
|
|
|
if (!MEC_fn_bIsNullVector(&stWallMove)) MEC_fn_vGroundObstacleManagement ( p_stDynamic, hSupObj, xDT );
|
|
else
|
|
MTH3D_M_vCopyVector (p_stCurrentTranslation,&stSafeTranslation);
|
|
}
|
|
else
|
|
{
|
|
DNM_M_vDynamicsSetForceSafeWalk (p_stDynamic,TRUE);
|
|
|
|
/* Never replace actor under the ground */
|
|
if ( MTH_M_bGreater(MTH3D_M_xNormVector(&stNormalMove),C_ulDNM_RAYMAN_ZDM_RADIUS) && MTH_M_bLessZero(MTH3D_M_xGetZofVector(&stNormalMove)) )
|
|
POS_fn_vCopyMatrix ( hCurrentMatrix, p_stPOS_DownPosition );
|
|
|
|
/* there is no ground, no wall, no valid obstacles. So we can't walk anymore.*/
|
|
if (DNM_M_bDynamicsIsNeverFall(p_stDynamic))
|
|
MTH3D_M_vAddVector (p_stCurrentTranslation,p_stPreviousTranslation,&stTangentMove);
|
|
|
|
if (g_lCallCounter>1)
|
|
POS_fn_vCopyMatrix ( hCurrentMatrix, hPreviousMatrix );
|
|
|
|
DNM_M_vDynamicsSetStop (p_stDynamic,FALSE);
|
|
}
|
|
}
|
|
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
return;
|
|
}
|
|
DNM_M_vDynamicsSetForceSafeWalk (p_stDynamic,TRUE);
|
|
|
|
/* Never replace actor under the ground */
|
|
if ( MTH_M_bGreater(MTH3D_M_xNormVector(&stNormalMove),C_ulDNM_RAYMAN_ZDM_RADIUS) && MTH_M_bLessZero(MTH3D_M_xGetZofVector(&stNormalMove)) )
|
|
POS_fn_vCopyMatrix ( hCurrentMatrix, p_stPOS_DownPosition );
|
|
|
|
/* There is no obstacle at all.*/
|
|
if (DNM_M_bDynamicsIsNeverFall(p_stDynamic))
|
|
MTH3D_M_vAddVector (p_stCurrentTranslation,p_stPreviousTranslation,&stTangentMove);
|
|
|
|
if (g_lCallCounter>1)
|
|
POS_fn_vCopyMatrix ( hCurrentMatrix, hPreviousMatrix );
|
|
|
|
DNM_M_vDynamicsSetStop (p_stDynamic,FALSE);
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
return;
|
|
}
|
|
|
|
|
|
void MEC_fn_vGroundGuess (DNM_tdstDynamics *p_stDynamic, MTH_tdxReal xDT)
|
|
{
|
|
POS_tdxHandleToPosition hCurrentMatrix, hPreviousMatrix;
|
|
MTH3D_tdstVector* p_stNormal;
|
|
MTH3D_tdstVector *p_stCurrentTranslation, *p_stPreviousTranslation;
|
|
MTH3D_tdstVector stMove, stVector;
|
|
MTH_tdxReal xDotProd;
|
|
|
|
p_stNormal = DNM_M_pDynamicsGetGroundNormal (p_stDynamic);
|
|
if (MTH3D_M_bIsNullVector(p_stNormal)) return;
|
|
|
|
hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
|
|
hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
|
|
|
|
p_stCurrentTranslation = POS_fn_p_stGetTranslationVector ( hCurrentMatrix );
|
|
p_stPreviousTranslation = POS_fn_p_stGetTranslationVector ( hPreviousMatrix );
|
|
MTH3D_M_vSubVector (&stMove,p_stCurrentTranslation,p_stPreviousTranslation);
|
|
|
|
xDotProd = MTH3D_M_xDotProductVector (&stMove,p_stNormal);
|
|
MTH3D_M_vNormalizeVector (&stVector,p_stNormal);
|
|
MTH3D_M_vMulScalarVector (&stVector,xDotProd,&stVector);
|
|
MTH3D_M_vSubVector (&stMove,&stMove,&stVector);
|
|
|
|
MTH3D_M_vAddVector (p_stCurrentTranslation,p_stPreviousTranslation,&stMove);
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
}
|
|
|
|
|
|
void MEC_fn_vSpiderObstacleManagement ( struct DNM_stDynamics *p_stDynamic, HIE_tdxHandleToSuperObject hSupObj, MTH_tdxReal xDT )
|
|
{
|
|
long lObstacle;
|
|
long lCounter;
|
|
DNM_tdstMecObstacle *p_stObstacle, *p_stTmpObstacle;
|
|
MTH_tdxReal xNormalMove;
|
|
MTH3D_tdstVector stVector;
|
|
|
|
POS_tdstCompletePosition a2_stPosition[2];
|
|
POS_tdstCompletePosition *p_stPOS_StartPosition = a2_stPosition;
|
|
POS_tdstCompletePosition *p_stPOS_EndPosition = a2_stPosition+1;
|
|
POS_tdxHandleToPosition hCurrentMatrix, hPreviousMatrix;
|
|
MTH3D_tdstVector *p_stCurrentTranslation;
|
|
MTH3D_tdstVector *p_stPreviousTranslation;
|
|
MTH3D_tdstVector *p_stStartTranslation;
|
|
MTH3D_tdstVector *p_stEndTranslation;
|
|
MTH3D_tdstVector stMove;
|
|
MTH3D_tdstVector *p_stX, *p_stY, *p_stZ;
|
|
|
|
/* XB 05/05/99 */
|
|
/* ACP_tdxBool bCollision = TRUE; */
|
|
/* End XB 05/05/99 */
|
|
|
|
|
|
#ifdef DNM_DEBUG
|
|
if(p_stDynamic == NULL)
|
|
return;
|
|
if(!HIE_fn_bIsSuperObjectValid(hSupObj))
|
|
return;
|
|
#endif
|
|
|
|
|
|
/* Current Position Matrix */
|
|
hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
|
|
hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
|
|
|
|
|
|
POS_fn_vCopyMatrix(p_stPOS_StartPosition, hCurrentMatrix);
|
|
POS_fn_vCopyMatrix(p_stPOS_EndPosition, hCurrentMatrix);
|
|
|
|
p_stCurrentTranslation = POS_fn_p_stGetTranslationVector ( hCurrentMatrix );
|
|
p_stPreviousTranslation = POS_fn_p_stGetTranslationVector ( hPreviousMatrix );
|
|
MTH3D_M_vSubVector (&stMove,p_stCurrentTranslation,p_stPreviousTranslation);
|
|
|
|
/* normal and tangent move */
|
|
POS_fn_vGetRotationVector ( hCurrentMatrix, &p_stX, &p_stY, &p_stZ );
|
|
xNormalMove = MTH_M_xMul ( C_xDNM_SPIDER_SLOPE_LIMIT, MTH3D_M_xNormVector(&stMove) );
|
|
if (MTH_M_bLess (xNormalMove,C_xDNM_SPIDER_DEFAULT_NORMAL_MOVE))
|
|
xNormalMove = C_xDNM_SPIDER_DEFAULT_NORMAL_MOVE;
|
|
|
|
p_stStartTranslation = POS_fn_p_stGetTranslationVector ( p_stPOS_StartPosition );
|
|
MTH3D_M_vMulScalarVector (&stVector, xNormalMove, p_stZ);
|
|
MTH3D_M_vAddVector ( p_stStartTranslation, p_stCurrentTranslation, &stVector );
|
|
|
|
p_stEndTranslation = POS_fn_p_stGetTranslationVector ( p_stPOS_EndPosition );
|
|
MTH3D_M_vMulScalarVector (&stVector, xNormalMove, p_stZ);
|
|
MTH3D_M_vSubVector ( p_stEndTranslation, p_stCurrentTranslation, &stVector );
|
|
|
|
if(MEC_fn_bCollision(&lObstacle,g_a_stObstacle,p_stDynamic,hSupObj,p_stPOS_StartPosition,p_stPOS_EndPosition,TRUE))
|
|
{
|
|
MTH3D_tdstVector* p_stNormal;
|
|
MTH3D_tdstVector stRotationAxis;
|
|
|
|
MEC_fn_vComputeAdjustVector (&stVector, p_stDynamic, lObstacle, g_a_stObstacle, lObstacle);
|
|
MTH3D_M_vAddVector (p_stCurrentTranslation,p_stEndTranslation,&stVector);
|
|
|
|
p_stObstacle = NULL;
|
|
for (lCounter=0; lCounter<lObstacle && !p_stObstacle; lCounter++)
|
|
{
|
|
p_stTmpObstacle = g_a_stObstacle + lCounter;
|
|
if (MEC_fn_bIsObstacleValid(p_stTmpObstacle)) p_stObstacle = p_stTmpObstacle;
|
|
}
|
|
|
|
/* orient actor */
|
|
POS_fn_vGetRotationVector ( hCurrentMatrix, &p_stX, &p_stY, &p_stZ );
|
|
p_stNormal = DNM_M_p_stObstacleGetNorm (p_stObstacle);
|
|
|
|
MTH3D_M_vCrossProductVectorWithoutBuffer (&stRotationAxis, p_stY, p_stZ);
|
|
MTH3D_M_vCopyVector ( p_stZ, p_stNormal );
|
|
MTH3D_M_vCrossProductVectorWithoutBuffer (p_stY, p_stZ, &stRotationAxis);
|
|
MTH3D_M_vCrossProductVectorWithoutBuffer (p_stX, p_stY, p_stZ);
|
|
MEC_fn_vUpdateMatrix ( p_stDynamic, hCurrentMatrix );
|
|
|
|
MEC_fn_vReportCollision (p_stDynamic,hSupObj,lObstacle,g_a_stObstacle,lObstacle-1);
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
return;
|
|
}
|
|
|
|
MEC_fn_vComputeSpeed (p_stDynamic,xDT);
|
|
}
|
|
|
|
|