/* *======================================================================================= * 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; lCounterlObstacleCounter) 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; lCounter1) { 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; lCounterlCounter) 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; lCounter12) ) { 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; lCounterlCounter) 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; lCounter2) || 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; lCounter0) { /* 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 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; lCounter1) 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