/* *======================================================================================= * Name : MecCol.c * Author : J Thénoz Date : 01/05/98 * Description : Mechanic collision functions *======================================================================================= */ #include "cpa_expt.h" #include "ACP_Base.h" #include "MEC/MECInc.h" #include "MEC/DnmDynam.h" #include "MEC/ParsData.h" #include "MEC/DNMSurSt.h" #include "MEC/mbase.h" #include "Extheade.h" #include "COL.h" #include "MEC/MecDef.h" #include "MEC/MECCol.h" #include "MEC/MECTools.h" #include "PCS.h" /* Physical Collide Set */ #include "SCT.h" /* SeCTor*/ #include "FIL.h" /* SeCTor*/ #include "PRT.h" /* PaRTicules*/ #include "GAM.h" /* GAMe*/ //DNM_tdstMecObstacle g_a_stObstacle [COL_C_xMaxNumberOfCollisions]; DNM_tdstMecObstacle *g_a_stObstacle = (DNM_tdstMecObstacle *) COL_g_stCollisionCase; ACP_tdxBool g_bWaterNoCollide; ACP_tdxBool MEC_fn_bCollision ( long* p_lObstacle, DNM_tdstMecObstacle *p_stObstacle, struct DNM_stDynamics* p_stDynamic, HIE_tdxHandleToSuperObject p_stSupObj, POS_tdstCompletePosition *p_stStartPosition, POS_tdstCompletePosition *p_stEndPosition, ACP_tdxBool bBackFace ) { long lCounter; DNM_tdstMecObstacle *p_stTmpObstacle; DNM_tdstMecObstacle stHandObstacle; POS_tdxHandleToPosition hSupObjMatrix; MTH3D_tdstVector stMove, stVector; MTH3D_tdstVector *p_stStartTranslation, *p_stEndTranslation; MTH3D_tdstVector *p_stX, *p_stY, *p_stZ; /* XB 05/05/99 */ /* ACP_tdxBool bIndexedTriangles = FALSE; */ /* End XB 05/05/99 */ ACP_tdxBool bObstacleOk = FALSE; MTH_tdxReal xDotProd; ACP_tdxBool bWaterFace = FALSE; MTH_tdxReal xDotProdMax; *p_lObstacle = 0; xDotProdMax = MTH_C_MinusONE; *p_lObstacle = COL_lHaveITakeSThgIntoTheMug (p_stObstacle, p_stSupObj, p_stStartPosition, p_stEndPosition); /* delete back faces */ if (!bBackFace) MEC_fn_vDeleteBaseBackFace ( *p_lObstacle,p_stObstacle, p_stDynamic ); MEC_fn_vDeleteNoCollidedGroundFace (*p_lObstacle,p_stObstacle,p_stDynamic); if (*p_lObstacle<=0) return FALSE; if (DNM_M_bDynamicsIsHanging(p_stDynamic)) MEC_fn_vDeleteHangingObstacle (*p_lObstacle,p_stObstacle,p_stDynamic); p_stStartTranslation = POS_fn_p_stGetTranslationVector (p_stStartPosition); p_stEndTranslation = POS_fn_p_stGetTranslationVector (p_stEndPosition); MTH3D_M_vSubVector ( &stMove, p_stStartTranslation, p_stEndTranslation ); MEC_fn_vComputeCollisionTranslation (*p_lObstacle,p_stObstacle,&stMove); hSupObjMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(p_stSupObj); POS_fn_vGetRotationVector ( hSupObjMatrix, &p_stX, &p_stY, &p_stZ ); for (lCounter=0; lCounter<*p_lObstacle; lCounter++) { p_stTmpObstacle = p_stObstacle+lCounter; if (MEC_fn_bIsObstacleValid(p_stTmpObstacle)) { ACP_tdxBool bCollisionOk = TRUE; /* hands */ if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetMyMaterial(p_stTmpObstacle),C_xDNM_HAND_TYPE_GAME_MATERIAL)) { bCollisionOk = FALSE; if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_HANG_TYPE_GAME_MATERIAL) ) { /* collide only hand with ground */ if (MEC_fn_bGroundObstacle(p_stDynamic,p_stTmpObstacle)) { /* choose best hand obstacle */ MTH3D_M_vSubVector (&stVector,DNM_M_p_stObstacleGetContact(p_stTmpObstacle),POS_fn_p_stGetTranslationVector(hSupObjMatrix)); if (!MEC_fn_bIsNullVector(&stVector)) MTH3D_M_vNormalizeVector (&stVector,&stVector); xDotProd = MTH_M_xAbs(MTH3D_M_xDotProductVector (p_stY,&stVector)); if (xDotProd>xDotProdMax) { xDotProdMax = xDotProd; DNM_M_MecObstacleCopyClone ( &stHandObstacle, p_stTmpObstacle ); } } } } /* water */ else if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_WATER_TYPE_GAME_MATERIAL)) { if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetMyMaterial(p_stTmpObstacle),C_xDNM_WATER_TYPE_GAME_MATERIAL)) { if (!bWaterFace) { /* delete water back face */ xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stTmpObstacle),DNM_M_pObstacleGetZoneMove(p_stTmpObstacle) ); if ( MTH_M_bGreater ( MTH_M_xAbs ( MTH3D_M_xGetZofVector (DNM_M_pObstacleGetZoneMove(p_stTmpObstacle))), 0.03 ) ) { if ( MTH_M_bLess(xDotProd, MTH_C_ZERO) ) { MEC_fn_vReportCollision (p_stDynamic, p_stSupObj, 1, p_stTmpObstacle, 0); /* the obstacle is used for repositionning only if required*/ bCollisionOk = fn_bBrainWaterCollideSO(p_stSupObj); if (!bCollisionOk) g_bWaterNoCollide = TRUE; bWaterFace = TRUE; } else bCollisionOk = FALSE; } else { MTH3D_M_vSubVector ( &stVector, DNM_M_p_stObstacleGetContact(p_stTmpObstacle), DNM_M_pObstacleGetZonePosition(p_stTmpObstacle) ); MTH3D_M_vAddVector ( &stVector, &stVector, DNM_M_pObstacleGetZoneMove(p_stTmpObstacle) ); xDotProd = MTH3D_M_xDotProductVector ( DNM_M_p_stObstacleGetNorm(p_stTmpObstacle),&stVector ); if (MTH_M_bLessEqual(xDotProd,MTH_C_ZERO)) { MEC_fn_vReportCollision (p_stDynamic, p_stSupObj, 1, p_stTmpObstacle, 0); bCollisionOk = fn_bBrainWaterCollideSO(p_stSupObj); if (!bCollisionOk) g_bWaterNoCollide = TRUE; bWaterFace = TRUE; } else bCollisionOk = FALSE; } if (MTH_M_bGreater(MTH3D_M_xGetZofVector(DNM_M_p_stObstacleGetNorm(p_stTmpObstacle)),MTH_C_ZERO)) bCollisionOk = FALSE; } else { bCollisionOk = FALSE; } } else /*we do not report the collision because it does not exist: do not use the obstable for repositionning*/ bCollisionOk = FALSE; } else { /* No collision faces */ if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_NO_COLLISION_TYPE_GAME_MATERIAL)) { /* Climb faces */ if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_CLIMB_TYPE_GAME_MATERIAL)) bCollisionOk = DNM_M_bDynamicsIsClimb(p_stDynamic); /* Gi faces */ else if (MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_GI_TYPE_GAME_MATERIAL)) bCollisionOk = DNM_M_bDynamicsIsGi(p_stDynamic); /* Other faces */ else if (MEC_fn_bTestMaskGameMaterial(DNM_M_hObstacleGetCollidedMaterial(p_stTmpObstacle),C_xDNM_COLLISION_REPORT_MASK)) { bCollisionOk=FALSE; MEC_fn_vReportCollision (p_stDynamic, p_stSupObj, 1, p_stTmpObstacle, 0); } /* no report */ else bCollisionOk=FALSE; } } if (!bCollisionOk) MEC_fn_vInvalidateObstacle(p_stTmpObstacle); else bObstacleOk=TRUE; } } /* report hand obstacle */ if (xDotProdMax != MTH_C_MinusONE) MEC_fn_vReportCollision (p_stDynamic, p_stSupObj, 1, &stHandObstacle, 0); return bObstacleOk; } #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ ACP_tdxBool MEC_fn_bInCollision ( struct DNM_stDynamics *p_stDynamic, HIE_tdxHandleToSuperObject hSupObj ) { /* DNM_tdstMecObstacle a_stObstacle[COL_C_xMaxNumberOfCollisions];*/ POS_tdxHandleToPosition hCurrentMatrix; POS_tdxHandleToPosition hPreviousMatrix; hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic); hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic); return COL_lHaveITakeSThgIntoTheMug (g_a_stObstacle, hSupObj, hPreviousMatrix, hCurrentMatrix) > 0; } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /* report collide actor */ void MEC_fn_vReportCollideActor (HIE_tdxHandleToSuperObject hCollideSupObj,DNM_tdstMecObstacle* p_stCollideObstacle) { struct DNM_stDynamics* p_stDynamic; DNM_tdstObstacle* p_stObstacle; MTH3D_tdstVector stVector; HIE_tdxHandleToSuperObject hSupObj; hSupObj = DNM_M_p_stObstacleGetObject (p_stCollideObstacle); if (!HIE_fn_bIsSuperObjectValid(hSupObj)) return; hSupObj = MEC_fn_hGetFatherActor (hSupObj); p_stDynamic= fn_p_stDynamGetDynamicsSO (hSupObj); if (!p_stDynamic) return; /* no report so nothing to do here */ if (!DNM_M_bDynamicsIsCollisionReport(p_stDynamic)) return; /* flag */ DNM_M_ulReportAddSurfaceState (DNM_M_p_stDynamicsGetReport(p_stDynamic),C_WOT_ulForceMobile); /* obstacle */ p_stObstacle = DNM_M_p_stReportGetCharacter ( DNM_M_p_stDynamicsGetReport(p_stDynamic) ); DNM_M_xObstacleSetRate (p_stObstacle,0); MTH3D_M_vNegVector (&stVector,DNM_M_p_stObstacleGetNorm(p_stCollideObstacle)); DNM_M_ObstacleSetNorm (p_stObstacle,&stVector); DNM_M_ObstacleSetContact (p_stObstacle,DNM_M_p_stObstacleGetContact(p_stCollideObstacle)); DNM_M_p_stObstacleSetObject (p_stObstacle,hCollideSupObj); DNM_M_vObstacleSetCollidedMaterial (p_stObstacle,DNM_M_hObstacleGetMyMaterial(p_stCollideObstacle)); DNM_M_vObstacleSetMyMaterial (p_stObstacle,DNM_M_hObstacleGetCollidedMaterial(p_stCollideObstacle)); } /* report collision */ void MEC_fn_vReportCollision ( struct DNM_stDynamics* p_stDynamic, HIE_tdxHandleToSuperObject hSupObj, long lNbObstacle, DNM_tdstMecObstacle a_stObstacle[COL_C_xMaxNumberOfCollisions], long lObstacle ) { MTH_tdxReal xDotProduct; MTH_tdxReal xPreviousRate, xCurrentRate; MTH3D_tdstVector stVerticalVector; MTH3D_tdstVector* p_stNormalVector; DNM_tdstMecObstacle* p_stTmpObstacle = NULL; long lCounter; ACP_tdxBool bStop = FALSE; ACP_tdxBool bHurt = FALSE; ACP_tdxBool bObstacle = FALSE; ACP_tdxBool bCeil = FALSE; ACP_tdxBool bWall = FALSE; ACP_tdxBool bGround = FALSE; ACP_tdxBool bActor = FALSE; ACP_tdxBool bWater = FALSE; ACP_tdxBool bObstacleEdge; ACP_tdxBool bCeilEdge; ACP_tdxBool bWallEdge; ACP_tdxBool bGroundEdge; ACP_tdxBool bActorEdge; ACP_tdxBool bWaterEdge; ACP_tdxBool bEdge; MTH3D_M_vSetVectorElements (&stVerticalVector, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE); xPreviousRate = MTH_C_2; for (lCounter=0; lCounterMEC_fn_xGroundLimit(p_stDynamic) ) { /* ground */ if (!bGround) { DNM_M_MecReportSetGround (&g_stReport,p_stTmpObstacle); bGroundEdge = bEdge; bGround = TRUE; } else if (bGroundEdge && !bEdge) { DNM_M_MecReportSetGround (&g_stReport,p_stTmpObstacle); bGroundEdge = FALSE; } } else if (xDotProduct>MEC_fn_xWallLimit(p_stDynamic)) { /* wall */ if (!bWall) { DNM_M_MecReportSetWall (&g_stReport,p_stTmpObstacle); bWallEdge = bEdge; bWall = TRUE; } else if (bWallEdge && !bEdge) { DNM_M_MecReportSetWall (&g_stReport,p_stTmpObstacle); bWallEdge = FALSE; } } else { /* ceil */ if (!bCeil) { DNM_M_MecReportSetCeil (&g_stReport,p_stTmpObstacle); bCeilEdge = bEdge; bCeil = TRUE; } else if (bCeilEdge && !bEdge) { DNM_M_MecReportSetCeil (&g_stReport,p_stTmpObstacle); bCeilEdge = FALSE; } } } } else bStop=TRUE; } } if (bActor) { DNM_M_ulReportAddSurfaceState (&g_stReport,C_WOT_ulMobile); MEC_fn_vReportCollideActor (hSupObj,DNM_M_p_stReportGetCharacter(&g_stReport)); } if (bWater) DNM_M_ulReportAddSurfaceState (&g_stReport,C_WOT_ulWater); if (bGround) { DNM_M_ulReportAddSurfaceState (&g_stReport,C_WOT_ulGround); if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic)) DNM_M_vDynamicsSetGroundNormal (p_stDynamic,DNM_M_p_stObstacleGetNorm(DNM_M_p_stReportGetGround(&g_stReport))); } if (bWall) { DNM_M_ulReportAddSurfaceState (&g_stReport,C_WOT_ulWall); if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic)) DNM_M_vDynamicsSetWallNormal (p_stDynamic,DNM_M_p_stObstacleGetNorm(DNM_M_p_stReportGetWall(&g_stReport))); } if (bCeil) DNM_M_ulReportAddSurfaceState (&g_stReport,C_WOT_ulCeiling); } void MEC_fn_vFillCollisionReport ( struct DNM_stDynamics* p_stDynamic ) { DNM_tdstReport* p_stReport; if (!DNM_M_bDynamicsIsCollisionReport(p_stDynamic)) return; if (DNM_M_ulReportGetSurfaceState(&g_stReport)==0) return; p_stReport = DNM_M_p_stDynamicsGetReport (p_stDynamic); DNM_M_ReportSetObstacle ( p_stReport, DNM_M_p_stReportGetObstacle(&g_stReport) ); if ( DNM_M_ulReportGetSurfaceState(&g_stReport) & C_WOT_ulMobile ) { DNM_M_ulReportAddSurfaceState (p_stReport,C_WOT_ulMobile); DNM_M_ReportSetCharacter ( p_stReport, DNM_M_p_stReportGetCharacter(&g_stReport) ); } if ( DNM_M_ulReportGetSurfaceState(&g_stReport) & C_WOT_ulWater ) { DNM_M_ulReportAddSurfaceState (p_stReport,C_WOT_ulWater); DNM_M_ReportSetWater ( p_stReport, DNM_M_p_stReportGetWater(&g_stReport) ); } if ( DNM_M_ulReportGetSurfaceState(&g_stReport) & C_WOT_ulGround ) { DNM_M_ulReportAddSurfaceState (p_stReport,C_WOT_ulGround); DNM_M_ReportSetGround ( p_stReport, DNM_M_p_stReportGetGround(&g_stReport) ); } if ( DNM_M_ulReportGetSurfaceState(&g_stReport) & C_WOT_ulWall ) { DNM_M_ulReportAddSurfaceState (p_stReport,C_WOT_ulWall); DNM_M_ReportSetWall ( p_stReport, DNM_M_p_stReportGetWall(&g_stReport) ); } if ( DNM_M_ulReportGetSurfaceState(&g_stReport) & C_WOT_ulCeiling ) { DNM_M_ulReportAddSurfaceState (p_stReport,C_WOT_ulCeiling); DNM_M_ReportSetCeil ( p_stReport, DNM_M_p_stReportGetCeil(&g_stReport) ); } } ACP_tdxBool MEC_fn_vComputeAdjustVector (MTH3D_tdstVector *p_stAdjustVector, struct DNM_stDynamics* p_stDynamic, long lObstacle, DNM_tdstMecObstacle *p_stObstacle, long lObstacleMin) { long lCounter; DNM_tdeObstacleType xObstacleType; ACP_tdxBool bAdjustVector = FALSE; /* XB 05/05/99 */ /* ACP_tdxBool bJustOneDynamic = TRUE; */ /* End XB 05/05/99 */ ACP_tdxBool bContinue; ACP_tdxBool bConflict = FALSE; /* XB 05/05/99 */ /* ACP_tdxBool bMobileWall = FALSE; */ /* End XB 05/05/99 */ DNM_tdstMecObstacle* p_stTmpObstacle, *p_stWaterObstacle; MTH_tdxReal xDotProd; MTH3D_tdstVector stNormalAdjustVector, stTangentAdjustVector, stVector; MTH3D_tdstVector stAdjustAxis; p_stWaterObstacle = NULL; MTH3D_M_vNullVector (p_stAdjustVector); for (lCounter=0; lCounter=2) return; /*here either we have a ground/non-ground obstable pair, or we have only a ground obstacle (bGround is true in either case)*/ /*compute the normed vector from the contact point to the center of the terminal zone position*/ // MTH3D_M_vAddVector (&stVector, DNM_M_pObstacleGetZonePosition(p_stGround), DNM_M_xObstacleGetTranslation(p_stGround)); // MTH3D_M_vSubVector (&stVector, &stVector, &stContact); // MTH3D_M_vNormalizeVector (&stVector,&stVector); if ( bNotGround ) { MTH3D_M_vAddVector (&stEdgeVector,DNM_M_p_stObstacleGetNorm(p_stGround),DNM_M_p_stObstacleGetNorm(p_stNotGround)); bNotGround = !MEC_fn_bIsNullVector(&stEdgeVector); /*if the vector is null, we have only one edge normal (backface)*/ } if ( bNotGround ) /*we have 2 edge normals*/ { MTH_tdxReal xDotProd; MTH3D_M_vNormalizeVector (&stEdgeVector,&stEdgeVector); xDotProd = MTH3D_M_xDotProductVector (&stVector1,&stEdgeVector); if ( MTH_M_bLessZero(xDotProd) ) return; } if ( MTH_M_bLess(MTH3D_M_xGetZofVector(&stVector1), C_xDNM_EDGE_GROUND_LIMIT) ) { DNM_M_bDynamicsSetCanFall(p_stDynamic,TRUE); /* compute fall translation */ if (DNM_M_bDynamicsIsComplexSize(p_stDynamic) ) { MTH3D_M_vSetZofVector ( &stVector1, MTH_C_ZERO ); if (!MEC_fn_bIsNullVector(&stVector1)) MTH3D_M_vNormalizeVector (&stVector1,&stVector1) else MTH3D_M_vNullVector (&stVector1); DNM_M_vDynamicsSetFallTranslation (p_stDynamic,&stVector1); } } } /* is the actor */ void MEC_fn_vCrashAnalysis ( struct DNM_stDynamics *p_stDynamic, long lObstacle, DNM_tdstMecObstacle *p_stObstacle ) { long lCounter; DNM_tdstMecObstacle *p_stTmpObstacle; DNM_tdstMecObstacle *p_stGroundObstacle, *p_stCeilObstacle; p_stGroundObstacle = NULL; p_stCeilObstacle = NULL; DNM_M_vDynamicsSetCrash(p_stDynamic,FALSE); p_stTmpObstacle = p_stObstacle; for (lCounter=0; lCounter