/* ************************************************************************************************** * Tool functions for camera AI. ************************************************************************************************** */ #define D_CineInfo_StructureDefine #include "AIUseCPA.h" #include "specif/AITools.h" #include "GEO.h" #include "GLI.h" #include "COL.h" #include "PO.h" /*XB980821*/ #ifndef D_THROW_IPO #include "IPO.h" #endif /* D_THROW_IPO */ /*End XB*/ /* Shaitan Clean Env {*/ /*#include "ENV.h"*/ /*End Shaitan Clean Env }*/ #include "SND.h" /* Shaitan Clean Env {*/ /*#include "SRF.h"*/ /*End Shaitan Clean Env }*/ #include "SCT.h" #include "GAM.h" #include "CAM_Base.h" #include "CAM_Vis.h" #include "CAM_Tool.h" #include "safe.h" /* ************************************************************************************************** ************************************************************************************************** TOOLS ************************************************************************************************** ************************************************************************************************** */ /* *================================================================================================= * Fast memcpy *================================================================================================= */ void CAM_memcpy(void *dest, void *src, long size) { register long *psrc = (long*)src; register long *pdest = (long*)dest; register long lsize = size; while(lsize >= 4) { *pdest++ = *psrc++; lsize -= 4; } while(lsize) { *((char *)pdest++) = *((char *)psrc++); lsize--; } } /* *================================================================================================= * Activate or desactivate an internal flag. *================================================================================================= */ void CAM_fn_vSetResetInternalFlag ( MS_tdxHandleToCineinfo _hCineInfo, unsigned short *_p_uwCurrentValue, unsigned short *_p_uwVisibilityValue, unsigned short *_p_uwWorkValue, long _lTypeOfChange, long _lChangingMode, unsigned short _uwFlag ) { if (_lTypeOfChange == 1) { CAM_fn_vSetCineinfoWorkFromCurrent(_hCineInfo); if (_lChangingMode) *_p_uwWorkValue |= _uwFlag; else *_p_uwWorkValue &= ~_uwFlag; } else { if (_lChangingMode) { *_p_uwCurrentValue |= _uwFlag; *_p_uwVisibilityValue |= _uwFlag; *_p_uwWorkValue |= _uwFlag; } else { *_p_uwCurrentValue &= ~_uwFlag; *_p_uwVisibilityValue &= ~_uwFlag; *_p_uwWorkValue &= ~_uwFlag; } } } /* *================================================================================================= * Force the camera to be at a given position. *================================================================================================= */ void CAM_fn_vForceCameraPos(HIE_tdxHandleToSuperObject _hSuperObjCamera, MTH3D_tdstVector *_p_stPosition) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ DNM_tdstReport *p_stReport; /* MTH3D_tdstVector stTempVector;*/ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ p_stReport = fn_pstGetDNMReport(_hSuperObjCamera); /* * Force position in global and local matrix. */ POS_fn_vSetTranslationVector(HIE_fn_hGetSuperObjectGlobalMatrix(_hSuperObjCamera), _p_stPosition); POS_fn_vSetTranslationVector(HIE_fn_hGetSuperObjectMatrix(_hSuperObjCamera), _p_stPosition); /* * Init Last move in report camera */ /* MTH3D_M_vNullVector(&stTempVector);*/ /* MTH3D_M_vCopyVector(DNM_M_p_stReportGetLastMove(p_stReport), &stTempVector);*/ MTH3D_M_vNullVector(DNM_M_p_stReportGetLastMove(p_stReport)); /* * Recompute sector of camera. */ fn_vSectInfoInitForSingleCharacter(_hSuperObjCamera, _p_stPosition); } /* *================================================================================================= * Force the camera to be at a given position. *================================================================================================= */ void CAM_fn_vForceCameraTgt ( HIE_tdxHandleToSuperObject _hSuperObjCamera, MTH3D_tdstVector *_p_stPosition, MTH3D_tdstVector *_p_stRefAxisZ ) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MS_tdxHandleToDynam h_Dynam; MS_tdxHandleToCineinfo hCineInfo; DNM_tdstParsingDatas *p_stParsingDatas; DNM_tdstReport *p_stReport; MTH3D_tdstVector stX, stY, stZ; MTH3D_tdstVector stCameraPosition; /* MTH3D_tdstVector stTempVector;*/ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ hCineInfo = M_GetMSHandle(_hSuperObjCamera, Cineinfo); h_Dynam = M_GetMSHandle(_hSuperObjCamera, Dynam); p_stReport = fn_pstGetDNMReport(_hSuperObjCamera); p_stParsingDatas = fn_p_stDynamGetParsingDatas(h_Dynam); /* * Get current camera position. */ POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectGlobalMatrix(_hSuperObjCamera), &stCameraPosition); /* * Compute system axis. */ MTH3D_M_vCopyVector(&stZ, _p_stRefAxisZ); CAM_fn_vComputeCameraSystemAxis ( fn_p_stDynamGetDynamics(h_Dynam), _hSuperObjCamera, &stCameraPosition, _p_stPosition, &stX, &stY, &stZ ); /* * Set Rotation Matrix */ POS_fn_vSetRotationMatrix(HIE_fn_hGetSuperObjectMatrix(_hSuperObjCamera), &stX, &stY, &stZ); POS_fn_vSetRotationMatrix(HIE_fn_hGetSuperObjectGlobalMatrix(_hSuperObjCamera), &stX, &stY, &stZ); /* * - Set Target pos in ParsingDatas structure * - Init Last move Target in report camera * - Init Last Good Target Position in report camera */ MTH3D_M_vCopyVector(DNM_M_p_stCPDGetTarget(p_stParsingDatas), _p_stPosition); /* MTH3D_M_vNullVector(&stTempVector);*/ /* MTH3D_M_vCopyVector(DNM_M_p_stReportGetLastTgtMove(p_stReport), &stTempVector);*/ MTH3D_M_vNullVector(DNM_M_p_stReportGetLastTgtMove(p_stReport)); } /* *================================================================================================= * Test if perso is moving *================================================================================================= */ ACP_tdxBool CAM_fn_bPersoIsMoving(CAM_tdstUpdateCamera *_p_stStruct, MTH3D_tdstVector *_p_stMove) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MTH3D_tdstVector stMove; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ CAM_fn_vAverageSpeed(_p_stStruct->hCineinfo, CAM_C_xAverageForComputeLinearSpeed, &stMove); if(MTH_M_bGreater(MTH3D_M_xNormVector(&stMove), CAM_C_xMinLinearSpeedTgtPerso)) { if(_p_stMove) { MTH3D_M_vCopyVector(_p_stMove, &stMove); } return TRUE; } if(_p_stMove) MTH3D_M_vNullVector(_p_stMove); return FALSE; } /* *================================================================================================= * Test if perso is moving *================================================================================================= */ ACP_tdxBool CAM_fn_bPersoIsTurning(HIE_tdxHandleToSuperObject _h_SuperObjPerso, MTH_tdxReal *_p_xAngularSpeed) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MS_tdxHandleToDynam h_Dynam; DNM_tdstDynamics *p_stDynamics; DNM_tdstReport *p_stReport; /* DNM_tdstMove *p_stSpeed;*/ MTH_tdxReal xAngle; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ if(_p_xAngularSpeed) *_p_xAngularSpeed = MTH_C_ZERO; h_Dynam = M_GetMSHandle(_h_SuperObjPerso, Dynam); if(h_Dynam == NULL) return FALSE; p_stDynamics = fn_p_stDynamGetDynamics(h_Dynam); if(p_stDynamics == NULL) return FALSE; p_stReport = DNM_M_p_stDynamicsGetReport(p_stDynamics); if(p_stReport == NULL) return FALSE; xAngle = MTH_M_xRotationGetAngle(MTH_M_p_stMoveGetAngular(DNM_M_p_stReportGetAbsoluteCurrSpeed(p_stReport))); if(MTH_M_bGreater(xAngle, CAM_C_xMinAngularSpeedTgtPerso)) { if(_p_xAngularSpeed) *_p_xAngularSpeed = xAngle; return TRUE; } return FALSE; } /* *================================================================================================= * Get normal of face of perso. *================================================================================================= */ ACP_tdxBool CAM_fn_bPersoOnFace(HIE_tdxHandleToSuperObject _h_SuperObjPerso, MTH3D_tdstVector *_p_stNormal) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MS_tdxHandleToDynam h_Dynam; DNM_tdstDynamics *p_stDynamics; DNM_tdstReport *p_stReport; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* * Get the normal of the face the targeted perso is walking on. */ h_Dynam = M_GetMSHandle(_h_SuperObjPerso, Dynam); if(h_Dynam == NULL) return FALSE; p_stDynamics = fn_p_stDynamGetDynamics(h_Dynam); if(p_stDynamics == NULL) return FALSE; p_stReport = DNM_M_p_stDynamicsGetReport(p_stDynamics); if(p_stReport == NULL) return FALSE; /* Check if perso is on a ground */ if(!(p_stReport->m_ulCurrSurfaceState & C_WOT_ulGround)) return FALSE; MTH3D_M_vCopyVector(_p_stNormal, &p_stReport->m_stGround.m_stNorm); return TRUE; } /* *================================================================================================= * Get the current father of a perso. *================================================================================================= */ HIE_tdxHandleToSuperObject CAM_fn_hGetFather(HIE_tdxHandleToSuperObject _h_SuperObjPerso) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MS_tdxHandleToDynam h_Dynam; DNM_tdstDynamics *p_stDynamics; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ if(_h_SuperObjPerso == NULL) return NULL; h_Dynam = M_GetMSHandle(_h_SuperObjPerso, Dynam); if(h_Dynam == NULL) return NULL; p_stDynamics = fn_p_stDynamGetDynamics(h_Dynam); if(p_stDynamics == NULL) return NULL; if (!DNM_M_bDynamicsIsComplexSize(p_stDynamics)) return NULL; return DNM_M_hDynamicsGetPlatformSO(p_stDynamics); } /* *================================================================================================= * Projection of a vector on to a plane defined by a norm *================================================================================================= */ void CAM_fn_vComputeProjection ( MTH3D_tdstVector *_p_sDestVector, MTH3D_tdstVector *_p_sSrcVector, MTH3D_tdstVector *_p_sNormVector ) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MTH_tdxReal xScalar; MTH3D_tdstVector stNormPart; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ if(!MTH_M_bEqualZero(xScalar = MTH3D_M_xDotProductVector(_p_sSrcVector, _p_sNormVector))) { MTH3D_M_vMulScalarVector(&stNormPart, xScalar, _p_sNormVector); /* MTH3D_M_vSubVector(&stNormPart, _p_sSrcVector, &stNormPart);*/ /* MTH3D_M_vCopyVector(_p_sDestVector, &stNormPart);*/ MTH3D_M_vSubVector(_p_sDestVector, _p_sSrcVector, &stNormPart); } else { MTH3D_M_vCopyVector(_p_sDestVector, _p_sSrcVector); } } /* *================================================================================================= * computing rotation between two vectors *================================================================================================= */ MTH_tdxReal CAM_fn_xComputeRotation ( MTH3D_tdstVector *_p_stDestVector, MTH3D_tdstVector *_p_stSrcVector, MTH3D_tdstVector *_p_stAxisVector ) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MTH_tdxReal xCos; MTH_tdxReal xDenom, xNumer; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* formula : cos(a,b) = a.b / sqrt(a.a * b.b) operation : 1 div, 1 sqrt, 10 mul, 6 add */ if( MTH3D_M_bIsNullVector(_p_stSrcVector) || MTH3D_M_bIsNullVector(_p_stDestVector) ) return MTH_C_ZERO; xDenom = MTH_M_xMul( MTH3D_M_xSqrVector( _p_stSrcVector ), MTH3D_M_xSqrVector( _p_stDestVector ) ); xNumer = MTH3D_M_xDotProductVector( _p_stSrcVector, _p_stDestVector ); xCos = MTH_M_xDiv( xNumer, MTH_M_xSqrt( xDenom ) ); if(_p_stAxisVector) { MTH3D_M_vCrossProductVector(_p_stAxisVector, _p_stSrcVector, _p_stDestVector); if(!MTH3D_M_bIsNullVector(_p_stAxisVector)) { MTH3D_M_vNormalizeVector(_p_stAxisVector, _p_stAxisVector); } } if (MTH_M_bLess(xCos,MTH_C_MinusONE)) xCos = MTH_C_MinusONE; else if (MTH_M_bGreater(xCos,MTH_C_ONE)) xCos =MTH_C_ONE; return (MTH_M_xACos(xCos)); } /* *================================================================================================= * Two vectors are equal with epsilon ? *================================================================================================= */ ACP_tdxBool CAM_fn_bEqualVectorWithEpsilon ( MTH3D_tdstVector *_p_stVector1, MTH3D_tdstVector *_p_stVector2, MTH_tdxReal _xEpsilon ) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MTH3D_tdstVector stDiffVector; MTH_tdxReal xDist; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MTH3D_M_vSubVector(&stDiffVector, _p_stVector1, _p_stVector2); xDist = MTH3D_M_xSqrVector(&stDiffVector); if(MTH_M_bGreater(xDist, MTH_M_xSqr(_xEpsilon))) return FALSE; else return TRUE; } /* *================================================================================================= * Check validity of the computed angles *================================================================================================= */ void CAM_fn_vCheckValidityOfComputedAngles ( MS_tdxHandleToInternalCineinfo _hIntCineInfo, MTH_tdxReal *_p_xHorizontalAngle, MTH_tdxReal *_p_xVerticalAngle ) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MTH_tdxReal xAbsHorizontalAngle, xAbsVerticalAngle; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ xAbsHorizontalAngle = MTH_M_xAbs(*_p_xHorizontalAngle); xAbsVerticalAngle = MTH_M_xAbs(*_p_xVerticalAngle); if(MTH_M_bGreater(xAbsVerticalAngle, MTH_C_PiBy2)) { if (MTH_M_bGreater(*_p_xVerticalAngle, MTH_C_ZERO)) *_p_xVerticalAngle = MTH_M_xSub(MTH_C_Pi, *_p_xVerticalAngle); else *_p_xVerticalAngle = MTH_M_xSub(MTH_M_xNeg(MTH_C_Pi), *_p_xVerticalAngle); } *_p_xHorizontalAngle = CAM_fn_xSetAngleInInterval02Pi(*_p_xHorizontalAngle); *_p_xVerticalAngle = CAM_fn_xSetAngleInInterval02Pi(*_p_xVerticalAngle); } /* *================================================================================================= * Compute horizontal angle and vertical angle between two Vector *================================================================================================= */ void CAM_fn_vComputeAnglesBetweenTwoVectors ( MS_tdxHandleToInternalCineinfo _hIntCineInfo, MTH3D_tdstVector *_p_stSourceVector, MTH3D_tdstVector *_p_stTargetVector, MTH_tdxReal *_p_xHorizontalAngle, MTH_tdxReal *_p_xVerticalAngle, MTH3D_tdstVector *_p_stRefAxisZ ) { *_p_xHorizontalAngle = CAM_fn_xComputeHorizontalAngle(_p_stSourceVector, _p_stTargetVector, _p_stRefAxisZ); *_p_xVerticalAngle = CAM_fn_xComputeVerticalAngle(_p_stSourceVector, _p_stTargetVector, _p_stRefAxisZ); CAM_fn_vCheckValidityOfComputedAngles(_hIntCineInfo, _p_xHorizontalAngle, _p_xVerticalAngle); } /* *================================================================================================= * Set the angle in ]-Pi,Pi] : *================================================================================================= */ MTH_tdxReal CAM_fn_xSetAngleInIntervalPiPi(MTH_tdxReal _xAngle) { if(MTH_M_bGreater(_xAngle, MTH_C_Pi)) return (MTH_M_xSub(_xAngle, MTH_C_2Pi)); else if(MTH_M_bLessEqual(_xAngle, MTH_M_xNeg(MTH_C_Pi))) return (MTH_M_xAdd(_xAngle, MTH_C_2Pi)); else return (_xAngle); } /* *================================================================================================= * Set the angle in [0,2Pi[ : *================================================================================================= */ MTH_tdxReal CAM_fn_xSetAngleInInterval02Pi(MTH_tdxReal _xAngle) { if (MTH_M_bLess(_xAngle, MTH_C_ZERO)) return(MTH_M_xAdd(_xAngle, MTH_C_2Pi)); else if (MTH_M_bGreaterEqual(_xAngle, MTH_C_2Pi)) return(MTH_M_xSub(_xAngle, MTH_C_2Pi)); else return (_xAngle); } /* ************************************************************************************************** ************************************************************************************************** ************************************************************************************************** ************************************************************************************************** */ /* *================================================================================================= * Test if camera has reached the wanted position. * Compute the current camera pos with the actuel global matrix. *================================================================================================= */ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ ACP_tdxBool CAM_fn_bPositionIsReached ( HIE_tdxHandleToSuperObject _hCamera, MTH3D_tdstVector *_p_stWantedPosition, MTH_tdxReal _xDistMin, MTH3D_tdstVector *_p_stCurrentPosition ) { POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectGlobalMatrix(_hCamera), _p_stCurrentPosition); return(CAM_fn_bEqualVectorWithEpsilon(_p_stCurrentPosition, _p_stWantedPosition, _xDistMin)); } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /* *================================================================================================= * Compute sight axis of a perso. Sight axis depend on the perso matrix and dynamical state. *================================================================================================= */ void CAM_fn_vGetPersoSightAxis(CAM_tdstUpdateCamera *_p_stStruct, MTH3D_tdstVector *_p_stAxis, MTH3D_tdstVector *_p_stAxisZ) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MTH3D_tdstVector stFirstComplementaryAxis; MTH3D_tdstVector stSecondComplementaryAxis; POS_tdstCompletePosition *p_stPersoGlobalMatrix; MTH3D_tdstVector stTmpVector1, stTmpVector2; /* MTH_tdxReal xSign;*/ unsigned char ucChannel; HIE_tdxHandleToSuperObject hPerso; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ hPerso = _p_stStruct->hCineinfoWork->hSuperObjectTargeted; fn_vGetPersoSightAxisSystem ( _p_stStruct->hCineinfo, _p_stAxis,/*&stAxis */ &stFirstComplementaryAxis, &stSecondComplementaryAxis ); if ((ucChannel = _p_stStruct->hCineinfoWork->cChannel) != C_ucUnknownChannel) { /* FBF blindage acces modules {*/ #ifdef ACTIVE_EDITOR fn_vCheckModuleAccess(hPerso,TRUE, &ucChannel); #endif /* } fin blindage acces modules */ hPerso = fn_hGetSuperObjectInChannel(fn_h3dDataGetChannelSOList(M_GetMSHandle(hPerso, 3dData)),(short) ucChannel); } p_stPersoGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(hPerso); /* if (MTH_M_bEqual(MTH_M_xAbs((xSign = MTH3D_M_xGetXofVector(_p_stAxis))), MTH_C_ONE)) { POS_fn_vGetRotationMatrix( p_stPersoGlobalMatrix, _p_stAxis, &stTmpVector1, &stTmpVector2); if (_p_stAxisZ) MTH3D_M_vCopyVector(_p_stAxisZ, &stTmpVector2); } else { if (MTH_M_bEqual(MTH_M_xAbs((xSign=MTH3D_M_xGetZofVector(_p_stAxis))), MTH_C_ONE)) { POS_fn_vGetRotationMatrix(p_stPersoGlobalMatrix, &stTmpVector1, &stTmpVector2, _p_stAxis); if (_p_stAxisZ) MTH3D_M_vNegVector(_p_stAxisZ, &stTmpVector2); } else { xSign = MTH3D_M_xGetYofVector(_p_stAxis); POS_fn_vGetRotationMatrix(p_stPersoGlobalMatrix, &stTmpVector1, _p_stAxis, &stTmpVector2); if (_p_stAxisZ) MTH3D_M_vCopyVector(_p_stAxisZ, &stTmpVector2); } } if (MTH_M_bLessZero(xSign)) { MTH3D_M_vNegVector(_p_stAxis, _p_stAxis); }*/ /* Force axis to be -Y*/ POS_fn_vGetRotationMatrix(p_stPersoGlobalMatrix, &stTmpVector1, _p_stAxis, &stTmpVector2); if (_p_stAxisZ) MTH3D_M_vCopyVector(_p_stAxisZ, &stTmpVector2); MTH3D_M_vNegVector(_p_stAxis, _p_stAxis); } /* ************************************************************************************************** ************************************************************************************************** ************************************************************************************************** ************************************************************************************************** */ MTH_tdxReal Cam_fn_xComputeProjectionRail ( MTH3D_tdstVector *_p_stTargetedPersoPos, MTH3D_tdstVector *_p_stWpPosition, MTH3D_tdstVector *_p_stDestWpPosition ) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MTH3D_tdstVector stAxe; MTH3D_tdstVector stTargetWp; MTH3D_tdstVector stProjectedVector; MTH3D_tdstVector stProjectedPoint; MTH_tdxReal xFactor; MTH_tdxReal xDotProduct; MTH_tdxReal xSqrNorm; MTH_tdxReal xDist1, xDist2; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MTH3D_M_vSubVector(&stTargetWp, _p_stTargetedPersoPos, _p_stWpPosition); MTH3D_M_vSubVector(&stAxe, _p_stDestWpPosition, _p_stWpPosition); /* * Factor of projection of Vector on Rail Axis */ xSqrNorm = MTH3D_M_xSqrVector(&stAxe); if (MTH_M_bIsNull(xSqrNorm)) { return (MTH_C_InfinitPlus); } xDotProduct = MTH3D_M_xDotProductVector(&stAxe, &stTargetWp); xFactor = MTH_M_xDiv(xDotProduct, xSqrNorm); if(MTH_M_bLessZero(xFactor)) { xDist1 = MTH3D_M_xVectorGap(_p_stWpPosition, _p_stTargetedPersoPos); xDist2 = MTH3D_M_xVectorGap(_p_stDestWpPosition, _p_stTargetedPersoPos); if (MTH_M_bGreater(xDist1,xDist2)) return (xDist2); else return (xDist1); } MTH3D_M_vMulScalarVector(&stProjectedVector, xFactor, &stAxe); MTH3D_M_vAddVector(&stProjectedPoint, &stProjectedVector, _p_stWpPosition); return (MTH3D_M_xVectorGap(&stProjectedPoint, _p_stTargetedPersoPos)); } /* *================================================================================================= * Compute the camera moving on a rail *================================================================================================= */ void Cam_fn_vComputeMovingOnRail ( CAM_tdstUpdateCamera *_p_stStruct, MTH3D_tdstVector *_p_stWantedPosition, MTH3D_tdstVector *_p_stWpPosition, MTH3D_tdstVector *_p_stPreviousWpPosition, MTH_tdxReal _xDistWanted ) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MTH3D_tdstVector stRailAxis; MTH3D_tdstVector stTargetCamera; MTH3D_tdstVector stVector; MTH3D_tdstVector stVector1; MTH3D_tdstVector stProjectedVector; MTH3D_tdstVector stCameraNextWp; MTH3D_tdstVector stProjectedPoint; MTH3D_tdstVector stWpDestination; MTH_tdxReal xFactor; MTH_tdxReal xDotProduct; MTH_tdxReal xNorm; MTH_tdxReal xActualNorm; MTH_tdxReal xSqrNorm; MTH_tdxReal xDistWanted; char cCameraIsOnWp = 0; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ CAM_fn_vComputeReferencePoint(_p_stStruct); MTH3D_M_vSubVector(&stCameraNextWp, _p_stWpPosition, &_p_stStruct->stCurrentCameraPos); MTH3D_M_vCopyVector(&stWpDestination, _p_stWpPosition); MTH3D_M_vSubVector(&stTargetCamera, &_p_stStruct->stTargetedPersoPos, &_p_stStruct->stCurrentCameraPos); /* * Factor of projection of Vector on Rail Axis */ xSqrNorm = MTH3D_M_xSqrVector(&stCameraNextWp); if (MTH_M_bIsNull(xSqrNorm)) { MTH3D_M_vSubVector(&stCameraNextWp, &_p_stStruct->stCurrentCameraPos, _p_stPreviousWpPosition); MTH3D_M_vCopyVector(&stWpDestination, _p_stPreviousWpPosition); xSqrNorm = MTH3D_M_xSqrVector(&stCameraNextWp); if (MTH_M_bIsNull(xSqrNorm)) { MTH3D_M_vCopyVector(_p_stWantedPosition, &_p_stStruct->stCurrentCameraPos); return; } cCameraIsOnWp = 1; } xDotProduct = MTH3D_M_xDotProductVector(&stCameraNextWp, &stTargetCamera); xFactor = MTH_M_xDiv(xDotProduct, xSqrNorm); if (!MTH_M_bIsNullWithEpsilon(xFactor,MTH_M_xFloatToReal(0.0001f))) { /* axis of rail */ if (cCameraIsOnWp) {MTH3D_M_vSubVector(&stCameraNextWp, &_p_stStruct->stCurrentCameraPos, &stWpDestination);} else {MTH3D_M_vSubVector(&stCameraNextWp, &stWpDestination, &_p_stStruct->stCurrentCameraPos);} MTH3D_M_vMulScalarVector(&stProjectedVector, xFactor, &stCameraNextWp); MTH3D_M_vSubVector(&stVector1, &stTargetCamera, &stProjectedVector); MTH3D_M_vAddVector(&stProjectedPoint, &_p_stStruct->stCurrentCameraPos, &stProjectedVector); xNorm = MTH3D_M_xSqrVector(&stVector1); xDistWanted = MTH_M_xSqr(_xDistWanted); xActualNorm = MTH3D_M_xVectorGap(&stProjectedPoint, &_p_stStruct->stCurrentCameraPos); if (!MTH_M_bGreater(xNorm, xDistWanted)) { xNorm = MTH_M_xSqrt(MTH_M_xSub(xDistWanted, xNorm)); if (MTH_M_bGreater(xNorm, xActualNorm)) { xNorm = MTH_M_xSub(xNorm, xActualNorm); if (MTH_M_bGreaterZero(xFactor)) {MTH3D_M_vCopyVector(&stWpDestination, _p_stPreviousWpPosition);}/* Change he sens of moving*/ else {if (cCameraIsOnWp) {return;}}/* No moving*/ } else { xNorm = MTH_M_xSub(xActualNorm, xNorm); if (MTH_M_bLessZero(xFactor)) {MTH3D_M_vCopyVector(&stWpDestination, _p_stPreviousWpPosition);} /* Change he sens of moving*/ else {if (cCameraIsOnWp) {return;}}/* No moving*/ } } else { /* * Go to the projected point */ if (MTH_M_bLessZero(xFactor)) {MTH3D_M_vCopyVector(&stWpDestination, _p_stPreviousWpPosition);} /* Change he sens of moving*/ else {if (cCameraIsOnWp) return;} /* No moving*/ xNorm = xActualNorm; } MTH3D_M_vSubVector(&stRailAxis, &stWpDestination, &_p_stStruct->stCurrentCameraPos); if (MTH_M_bGreater(xNorm,MTH3D_M_xNormVector(&stRailAxis))) { MTH3D_M_vCopyVector(_p_stWantedPosition, &stWpDestination); } else { MTH3D_M_vNormalizeVector(&stRailAxis,&stRailAxis); MTH3D_M_vMulScalarVector(&stVector, xNorm, &stRailAxis); MTH3D_M_vAddVector(_p_stWantedPosition, &_p_stStruct->stCurrentCameraPos, &stVector); } } } /* ************************************************************************************************** ************************************************************************************************** ************************************************************************************************** ************************************************************************************************** */ /* *================================================================================================= * Init camera stucture. *================================================================================================= */ void CAM_fn_vInitCameraStructure(HIE_tdxHandleToSuperObject _hSuperObjPerso, CAM_tdstUpdateCamera *_p_stStruct) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ MS_tdxHandleToDynam hDynam; MTH3D_tdstVector stTempVector; DNM_tdstDynamics *p_stDynamics; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ memset(_p_stStruct, 0, sizeof(CAM_tdstUpdateCamera)); /* * Init camera stucture. */ hDynam = M_GetMSHandle(_hSuperObjPerso, Dynam); _p_stStruct->p_stDynamics = fn_p_stDynamGetDynamics(hDynam); _p_stStruct->p_stReport = DNM_M_p_stDynamicsGetReport(_p_stStruct->p_stDynamics); _p_stStruct->hCineinfo = M_GetMSHandle(_hSuperObjPerso, Cineinfo); _p_stStruct->hCineinfoWork = M_GetCineinfo(_hSuperObjPerso, Work); _p_stStruct->hCineinfoCurrent = M_GetCineinfo(_hSuperObjPerso, Current); _p_stStruct->hCineinfoInit = M_GetCineinfo(_hSuperObjPerso, Init); _p_stStruct->hCineinfoVisibility = M_GetCineinfo(_hSuperObjPerso, Visibility); _p_stStruct->hSuperObjCamera = _hSuperObjPerso; /* * Current camera pos. */ POS_fn_vGetTranslationVector ( HIE_fn_hGetSuperObjectGlobalMatrix(_hSuperObjPerso), &_p_stStruct->stCurrentCameraPos ); /* * Does targeted perso is moving ? * We update _p_stStruct->stTgtPersoMove only if perso is moving (cause we want to * remember the last move vector of the perso). */ if(_p_stStruct->hCineinfoWork->hSuperObjectTargeted != NULL) { /* Absolute move */ _p_stStruct->cTgtPersoIsMovingAbsolute = CAM_fn_bPersoIsMoving ( _p_stStruct, &_p_stStruct->stTgtPersoMoveAbsolute ); /* Relative move */ if(CAM_fn_hGetFather(_p_stStruct->hCineinfoWork->hSuperObjectTargeted) == NULL) { _p_stStruct->cTgtPersoIsMovingRelative = _p_stStruct->cTgtPersoIsMovingAbsolute; MTH3D_M_vCopyVector(&_p_stStruct->stTgtPersoMoveRelative, &_p_stStruct->stTgtPersoMoveAbsolute); } else { hDynam = M_GetMSHandle(_p_stStruct->hCineinfoWork->hSuperObjectTargeted, Dynam); p_stDynamics = fn_p_stDynamGetDynamics(hDynam); POS_fn_vGetTranslationVector(DNM_M_p_stDynamicsGetPrevPreviousMatrix(p_stDynamics), &stTempVector); POS_fn_vGetTranslationVector(DNM_M_p_stDynamicsGetPreviousMatrix(p_stDynamics), &_p_stStruct->stTgtPersoMoveRelative); MTH3D_M_vSubVector(&_p_stStruct->stTgtPersoMoveRelative, &stTempVector, &_p_stStruct->stTgtPersoMoveRelative); if(MTH_M_bGreater(MTH3D_M_xNormVector(&_p_stStruct->stTgtPersoMoveRelative), CAM_C_xMinLinearSpeedTgtPerso)) _p_stStruct->cTgtPersoIsMovingRelative = 1; else _p_stStruct->cTgtPersoIsMovingRelative = 0; } } } /* ************************************************************************************************** ************************************************************************************************** ************************************************************************************************** ************************************************************************************************** */ /* *================================================================================================= * Description: * Send parameters to Parsing * Fill the Macdpid structur *================================================================================================= */ void CAM_fn_vSendParametersToParsing(CAM_tdstUpdateCamera *_p_stStruct) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ tdstMACDPID *p_stMACDPID; DNM_tdstDynamics *p_stDynamics; MS_tdxHandleToDynam h_Dynam; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ if((h_Dynam = M_GetMSHandle(_p_stStruct->hSuperObjCamera, Dynam)) == NULL ) return; if((p_stDynamics = fn_p_stDynamGetDynamics(h_Dynam)) == NULL) return; p_stMACDPID = DNM_M_p_stDynamicsGetExternalDatas(p_stDynamics); /* * Cut angle factor. */ M_xMACDPIDGetCutAngleFactorPos(p_stMACDPID) = CAM_C_xCutAngleFactorPos; M_xMACDPIDGetCutAngleFactorTgt(p_stMACDPID) = CAM_C_xCutAngleFactorTgt; /* Angle Theta */ M_xMACDPIDSetTheta(p_stMACDPID, _p_stStruct->hCineinfoWork->xAngleTheta); /* Target and move vector */ MTH3D_M_vCopyVector(M_p_stMACDPIDGetTarget(p_stMACDPID), &_p_stStruct->stCptPos.stTarget); MTH3D_M_vCopyVector(M_p_stMACDPIDGetMovePos(p_stMACDPID), &_p_stStruct->stCptPos.stMovePos); /* Linear speed and speeding up */ M_xMACDPIDGetLinearSpeed(p_stMACDPID) = _p_stStruct->stCptPos.xLinearSpeed; if(MTH_M_bEqual(_p_stStruct->hCineinfoWork->xLinearIncreaseSpeed, MTH_C_ZERO)) _p_stStruct->hCineinfoWork->xLinearIncreaseSpeed = MTH_M_xFloatToReal(0.001f); M_xMACDPIDGetLinearIncreaseSpeed(p_stMACDPID) = _p_stStruct->hCineinfoWork->xLinearIncreaseSpeed; M_xMACDPIDGetLinearDecreaseSpeed(p_stMACDPID) = _p_stStruct->hCineinfoWork->xLinearDecreaseSpeed; /* Angular speed and speeding up */ M_xMACDPIDGetAngularSpeed(p_stMACDPID) = _p_stStruct->stCptPos.xAngularSpeed; if(MTH_M_bEqual(_p_stStruct->hCineinfoWork->xAngularIncreaseSpeed, MTH_C_ZERO)) _p_stStruct->hCineinfoWork->xLinearIncreaseSpeed = MTH_M_xFloatToReal(0.001f); M_xMACDPIDGetAngularIncreaseSpeed(p_stMACDPID) = _p_stStruct->hCineinfoWork->xAngularIncreaseSpeed; M_xMACDPIDGetAngularDecreaseSpeed(p_stMACDPID) = _p_stStruct->hCineinfoWork->xAngularDecreaseSpeed; /* Target speed and speeding up */ M_xMACDPIDGetTargetSpeed(p_stMACDPID) = _p_stStruct->stCptPos.xTargetSpeed; if(MTH_M_bEqual(_p_stStruct->hCineinfoWork->xAngularIncreaseSpeed, MTH_C_ZERO)) _p_stStruct->hCineinfoWork->xTargetIncreaseSpeed = MTH_M_xFloatToReal(0.001f); M_xMACDPIDGetTargetIncreaseSpeed(p_stMACDPID) = _p_stStruct->hCineinfoWork->xTargetIncreaseSpeed; M_xMACDPIDGetTargetDecreaseSpeed(p_stMACDPID) = _p_stStruct->hCineinfoWork->xTargetDecreaseSpeed; /* Reference point for camera position (only for angular parsing) */ MTH3D_M_vCopyVector(M_p_stMACDPIDGetPosReferencePoint(p_stMACDPID), &_p_stStruct->stTargetedPersoPos); /* Reference axis Z to twist camera */ MTH3D_M_vCopyVector(M_p_stMACDPIDGetRefAxisZ(p_stMACDPID), &_p_stStruct->stCptPos.stRefAxisZ); /* * DNM Flags. * Change DNM flags depending on context. */ /*---*/ if(_p_stStruct->hCineinfo->ucVolIAFlags & C_VolIAFlags_InitJustCopiedInCurrent) { _p_stStruct->hCineinfoWork->uwDNMFlags |= DNM_CAM_C_NoLinearParsing; _p_stStruct->hCineinfoWork->uwDNMFlags |= DNM_CAM_C_NoAngularParsing; _p_stStruct->hCineinfoWork->uwDNMFlags |= DNM_CAM_C_NoTargetParsing; } /*---*/ if(_p_stStruct->hCineinfoWork->hSuperObjectTargeted == NULL) { MTH3D_M_vNullVector(M_p_stMACDPIDGetPosReferencePoint(p_stMACDPID)); } /*---*/ if(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_PositionIsAlreadyComputed) { _p_stStruct->hCineinfoWork->uwDNMFlags |= DNM_CAM_C_NoAngularParsing; MTH3D_M_vNullVector(M_p_stMACDPIDGetPosReferencePoint(p_stMACDPID)); } /*---*/ if(_p_stStruct->hCineinfoWork->uwDNMFlags & DNM_CAM_C_FixedOrientation) _p_stStruct->hCineinfoWork->uwDNMFlags |= DNM_CAM_C_NoTargetParsing; /*---*/ if(_p_stStruct->hCineinfoWork->uwDNMFlags & DNM_CAM_C_NoLinearParsing) { _p_stStruct->hCineinfoWork->uwDNMFlags |= DNM_CAM_C_NoLinearInertia; M_xMACDPIDGetCutAngleFactorPos(p_stMACDPID) = MTH_C_ONE; } /*---*/ if(_p_stStruct->hCineinfoWork->uwDNMFlags & DNM_CAM_C_NoAngularParsing) { _p_stStruct->hCineinfoWork->uwDNMFlags |= DNM_CAM_C_NoAngularInertia; M_xMACDPIDGetCutAngleFactorPos(p_stMACDPID) = MTH_C_ONE; } /*---*/ if(_p_stStruct->hCineinfoWork->uwDNMFlags & DNM_CAM_C_NoTargetParsing) { _p_stStruct->hCineinfoWork->uwDNMFlags |= DNM_CAM_C_NoTargetInertia; M_xMACDPIDGetCutAngleFactorTgt(p_stMACDPID) = MTH_C_ONE; } /*---*/ M_uwMACDPIDGetFlags(p_stMACDPID) = _p_stStruct->hCineinfoWork->uwDNMFlags; /* If no collision, force camera sector to be the same as targeted perso */ if((_p_stStruct->hCineinfoWork->hSuperObjectTargeted) && (_p_stStruct->hCineinfoWork->uwDNMFlags & DNM_CAM_C_NoObstacle)) { /* the camera is forced in the sector of its target */ fn_vSectInfoSetCurrentSector(M_GetMSHandle(_p_stStruct->hSuperObjCamera,SectInfo), fn_h_SectInfoGetCurrentSector(M_GetMSHandle(_p_stStruct->hCineinfoWork->hSuperObjectTargeted,SectInfo))); //fn_vSectInfoInitForSingleCharacter(_p_stStruct->hSuperObjCamera, &_p_stStruct->stTargetedPersoRealPos); } if(!(_p_stStruct->cTgtPersoIsMovingAbsolute)) { M_xMACDPIDGetCutAngleFactorPos(p_stMACDPID) = M_xMACDPIDGetCutAngleFactorTgt(p_stMACDPID) = MTH_C_ONE; } } extern char cRefAxisIsAlreadyComputed; extern char cNoDynChangeTheta; extern char cCanTestStatic; void CAM_fn_vForceBestPosition(HIE_tdxHandleToSuperObject _hCamera) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* HIE_tdxHandleToSuperObject hCamera;*/ MS_tdxHandleToCineinfo hCineinfo; CAM_tdstUpdateCamera stStruct; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ hCineinfo = M_GetMSHandle(_hCamera, Cineinfo); /* * To have the actual good camera parameters. */ CAM_fn_vSetCineinfoWorkFromCurrent(hCineinfo); CAM_fn_vInitCameraStructure(_hCamera, &stStruct); cRefAxisIsAlreadyComputed = stStruct.hCineinfoWork->uwIAFlags & C_IAFlags_RefAxisIsAlreadyComputed ? 1 : 0; cNoDynChangeTheta = stStruct.hCineinfoWork->uwIAFlags & C_IAFlags_NoDynChangeTheta ? 1 : 0; cCanTestStatic = 1; /* * Compute target and real wanted camera pos (this is necessary * for failure when we want a more correct position. */ CAM_fn_vComputeReferencePoint(&stStruct); CAM_fn_vComputeTarget(&stStruct); CAM_fn_vComputeRealWantedPos(&stStruct); CAM_fn_vComputeMovePosWithDynTheta(&stStruct); /* * If no perso, can't do it. */ if(stStruct.hCineinfoCurrent->hSuperObjectTargeted == NULL) return; /* * Force visibility failure. */ CAM_fn_vForceFailureVisibility(&stStruct); CAM_fn_vComputeFailureVisibility(&stStruct); /* stStruct.hCineinfoWork->uwDNMFlags |= (DNM_CAM_C_NoLinearParsing|DNM_CAM_C_NoAngularParsing);*/ }