1838 lines
59 KiB
C
1838 lines
59 KiB
C
/*
|
|
**************************************************************************************************
|
|
* For camera visibility tests.
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
#define D_CineInfo_StructureDefine
|
|
|
|
#include "AIUseCPA.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 <ASSERT.h>
|
|
/*XB*/
|
|
#if defined(U64)
|
|
void qsort(void *,size_t,size_t,int (*)(const void *,const void *));
|
|
#endif
|
|
/*End XB*/
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
VISIBILITY : FILL ARRAY OF SIN AND COS
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
/* Array that contains angles to test in both normal and failure mode */
|
|
unsigned short guw_NbVectorArrayCpt = 0;
|
|
typedef struct
|
|
{
|
|
MTH3D_tdstVector stDir;
|
|
MTH_tdxReal xPound;
|
|
} tdst_PosPound;
|
|
tdst_PosPound gast_VectorArrayCpt[256];
|
|
|
|
/* To compute pound : Contains the ideal parameters */
|
|
struct tdstInternalStructurCineinfo_ gst_Ideal;
|
|
|
|
/* To indicate that the ray to test visibility can test static hierarchy */
|
|
char cCanTestStatic = 1;
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
VISIBILITY : BASIC TEST OF VISIBILITY
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Is sector is in list ?
|
|
*=================================================================================================
|
|
*/
|
|
char CAM_fn_cIsSectorInCollisionList(HIE_tdxHandleToSuperObject _hFirstSector, HIE_tdxHandleToSuperObject _hTestSector)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
int i;
|
|
SECT_tdxHandleOfElementLstCollisionInteraction hList;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
SECT_M_ForEachCollisionNodeInCollisionInteractionList(_hFirstSector, hList, i)
|
|
{
|
|
if(SECT_GetSectorInCollisionList(hList) == _hTestSector)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Truncate a vector element to avoid computing errors to change the validity of a segment.
|
|
*=================================================================================================
|
|
*/
|
|
#define M_Trunc(Vector, Type)\
|
|
{\
|
|
int _iTemp_;\
|
|
_iTemp_ = (int) MTH_M_xMul(MTH3D_M_xGet##Type##ofVector(&Vector), 1000);\
|
|
MTH3D_M_vSet##Type##ofVector(&Vector, MTH_M_xDiv((MTH_tdxReal) _iTemp_, 1000));\
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Visibility test with a segment in dynamic world.
|
|
* We only test actors which priority is fewer than camera one.
|
|
*=================================================================================================
|
|
*/
|
|
char CAM_fn_cSendSegmentInDynamicWorld
|
|
(
|
|
MTH3D_tdstVector *_p_stSource,
|
|
MTH3D_tdstVector *_p_stDest,
|
|
HIE_tdxHandleToSuperObject _hSector,
|
|
HIE_tdxHandleToSuperObject _hCamera
|
|
)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
long j;
|
|
SECT_tdxHandleOfElementLstCharacter hCharacterList;
|
|
HIE_tdxHandleToSuperObject hTreatCharacter;
|
|
unsigned char ucCameraPriority;
|
|
MTH3D_tdstVector stTempVector;
|
|
MS_tdxHandleToCollSet hCollset;
|
|
MS_tdxHandleToStandardGame hStdGame;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/* Get camera priority to test character one with */
|
|
ucCameraPriority = CS_fn_ucGetCharacterPriority(M_GetMSHandle(_hCamera, CollSet));
|
|
MTH3D_M_vSubVector(&stTempVector, _p_stDest, _p_stSource);
|
|
SECT_M_ForEachCharListInSector(_hSector, hCharacterList, j)
|
|
{
|
|
hTreatCharacter = SECT_GetCharacterInList(hCharacterList);
|
|
hCollset = M_GetMSHandle(hTreatCharacter, CollSet);
|
|
hStdGame = M_GetMSHandle(hTreatCharacter, StandardGame);
|
|
|
|
if ( (hCollset && (CS_fn_ucGetCharacterPriority(hCollset) == ucCameraPriority)) ||
|
|
(hStdGame && (fn_ulStandardGameGetCustomBits(hStdGame) & GAM_C_CustBitCameraHit)) )
|
|
/*if (!hCollset || (CS_fn_ucGetCharacterPriority(hCollset) == ucCameraPriority))*/
|
|
{
|
|
/*if (CS_fn_ucGetCharacterPriority(hCollset) == ucCameraPriority)*/
|
|
{
|
|
/* Perso must have an anim, so must have some children */
|
|
if(HIE_fn_lGetNumberOfChildren(hTreatCharacter))
|
|
{
|
|
if
|
|
(
|
|
HIE_bDetectIntersectSegmentWithSuperObject
|
|
(
|
|
_p_stSource,
|
|
/* _p_stDest,*/
|
|
&stTempVector,
|
|
hTreatCharacter
|
|
)
|
|
)
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Visibility test with a segment in static world and dynamic world.
|
|
* We test :
|
|
* - In current actor sector
|
|
* - In current camera sector
|
|
* - In the sectors of collision list of actor
|
|
* - In the sectors of collision list of camera
|
|
*=================================================================================================
|
|
*/
|
|
char CAM_fn_cSendSegment
|
|
(
|
|
CAM_tdstUpdateCamera *_p_stStruct,
|
|
MTH3D_tdstVector *_p_stSource,
|
|
MTH3D_tdstVector *_p_stDest
|
|
)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stTempVector;
|
|
int i;
|
|
MS_tdxHandleToSectInfo hPersoCineinfo;
|
|
MS_tdxHandleToSectInfo hCamCineinfo;
|
|
SECT_tdxHandleOfElementLstCollisionInteraction hList;
|
|
MTH3D_tdstVector stSource, stDest;
|
|
HIE_tdxHandleToSuperObject hPersoTargeted;
|
|
HIE_tdxHandleToSuperObject hCamera;
|
|
HIE_tdxHandleToSuperObject hCurrentSectorPerso;
|
|
HIE_tdxHandleToSuperObject hCurrentSectorCamera;
|
|
HIE_tdxHandleToSuperObject hSectorInCollision;
|
|
char cVisibilityWithDynWorld;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
if(MTH3D_M_bEqualVector(_p_stSource, _p_stDest))
|
|
return 0;
|
|
|
|
/*
|
|
* Determin if we must test in dynamic world.
|
|
*/
|
|
cVisibilityWithDynWorld = _p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoVisibilityWithDynHie ? 0 : 1;
|
|
|
|
/*
|
|
* We truncate source and destination vector to avoid computing errors.
|
|
* Positions that are closer from each other are then considered to be equal.
|
|
*/
|
|
/*MTH3D_M_vCopyVector(&stSource, _p_stSource);
|
|
MTH3D_M_vCopyVector(&stDest, _p_stDest);*/
|
|
stSource = *_p_stSource;
|
|
stDest = *_p_stDest;
|
|
M_Trunc(stSource, X);
|
|
M_Trunc(stSource, Y);
|
|
M_Trunc(stSource, Z);
|
|
M_Trunc(stDest, X);
|
|
M_Trunc(stDest, Y);
|
|
M_Trunc(stDest, Z);
|
|
|
|
/*
|
|
* Retrieve sector of camera and targeted perso.
|
|
*/
|
|
hCamera = _p_stStruct->hSuperObjCamera;
|
|
hCamCineinfo = M_GetMSHandle(hCamera, SectInfo);
|
|
hCurrentSectorPerso = hCurrentSectorCamera = fn_h_SectInfoGetCurrentSector(hCamCineinfo);
|
|
|
|
hPersoTargeted = _p_stStruct->hCineinfoWork->hSuperObjectTargeted;
|
|
if(hPersoTargeted)
|
|
{
|
|
hPersoCineinfo = M_GetMSHandle(hPersoTargeted, SectInfo);
|
|
hCurrentSectorPerso = fn_h_SectInfoGetCurrentSector(hPersoCineinfo);
|
|
}
|
|
|
|
/*
|
|
* Compute segment.
|
|
*/
|
|
MTH3D_M_vSubVector(&stTempVector, &stDest, &stSource);
|
|
|
|
/*
|
|
* Current actor sector
|
|
*----------------------
|
|
*/
|
|
|
|
/* STATIC */
|
|
if
|
|
(
|
|
cCanTestStatic
|
|
&& HIE_bDetectIntersectSegmentWithSuperObject
|
|
(
|
|
&stSource,
|
|
/* &stDest,*/
|
|
&stTempVector,
|
|
hCurrentSectorPerso
|
|
)
|
|
)
|
|
return 1;
|
|
|
|
/* DYNAMIC */
|
|
if
|
|
(
|
|
(cVisibilityWithDynWorld)
|
|
&& CAM_fn_cSendSegmentInDynamicWorld
|
|
(
|
|
&stSource,
|
|
&stDest,
|
|
hCurrentSectorPerso,
|
|
hCamera
|
|
)
|
|
)
|
|
return 1;
|
|
|
|
/*
|
|
* Current camera sector (if it's not the same than actor one)
|
|
*-------------------------------------------------------------
|
|
*/
|
|
if(hCurrentSectorPerso != hCurrentSectorCamera)
|
|
{
|
|
/* STATIC */
|
|
if
|
|
(
|
|
cCanTestStatic
|
|
&& HIE_bDetectIntersectSegmentWithSuperObject
|
|
(
|
|
&stSource,
|
|
/* &stDest,*/
|
|
&stTempVector,
|
|
hCurrentSectorCamera
|
|
)
|
|
)
|
|
return 1;
|
|
|
|
/* DYNAMIC */
|
|
if
|
|
(
|
|
(cVisibilityWithDynWorld)
|
|
&& CAM_fn_cSendSegmentInDynamicWorld
|
|
(
|
|
&stSource,
|
|
&stDest,
|
|
hCurrentSectorCamera,
|
|
hCamera
|
|
)
|
|
)
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Collision sectors of perso
|
|
*----------------------------
|
|
*/
|
|
SECT_M_ForEachCollisionNodeInCollisionInteractionList
|
|
(
|
|
hCurrentSectorPerso,
|
|
hList,
|
|
i
|
|
)
|
|
{
|
|
hSectorInCollision = SECT_GetSectorInCollisionList(hList);
|
|
|
|
/* Sector is not camera one (already treated) */
|
|
if(hSectorInCollision != hCurrentSectorCamera)
|
|
{
|
|
/* STATIC */
|
|
if
|
|
(
|
|
cCanTestStatic
|
|
&& HIE_bDetectIntersectSegmentWithSuperObject
|
|
(
|
|
&stSource,
|
|
/* &stDest,*/
|
|
&stTempVector,
|
|
hSectorInCollision
|
|
)
|
|
)
|
|
return 1;
|
|
|
|
/* DYNAMIC */
|
|
if
|
|
(
|
|
(cVisibilityWithDynWorld)
|
|
&& CAM_fn_cSendSegmentInDynamicWorld
|
|
(
|
|
&stSource,
|
|
&stDest,
|
|
hSectorInCollision,
|
|
hCamera
|
|
)
|
|
)
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Collision sectors of camera
|
|
*-----------------------------
|
|
*/
|
|
if(hCurrentSectorPerso != hCurrentSectorCamera)
|
|
{
|
|
SECT_M_ForEachCollisionNodeInCollisionInteractionList
|
|
(
|
|
hCurrentSectorCamera,
|
|
hList,
|
|
i
|
|
)
|
|
{
|
|
hSectorInCollision = SECT_GetSectorInCollisionList(hList);
|
|
if
|
|
(
|
|
/* Sector is not in perso list */
|
|
!CAM_fn_cIsSectorInCollisionList
|
|
(
|
|
hCurrentSectorPerso,
|
|
hSectorInCollision
|
|
)
|
|
/* Sector is not perso one */
|
|
&& (hSectorInCollision != hCurrentSectorPerso)
|
|
)
|
|
{
|
|
/* STATIC */
|
|
if
|
|
(
|
|
cCanTestStatic
|
|
&& HIE_bDetectIntersectSegmentWithSuperObject
|
|
(
|
|
&stSource,
|
|
/* &stDest,*/
|
|
&stTempVector,
|
|
hSectorInCollision
|
|
)
|
|
)
|
|
return 1;
|
|
|
|
/* DYNAMIC */
|
|
if
|
|
(
|
|
(cVisibilityWithDynWorld)
|
|
&& CAM_fn_cSendSegmentInDynamicWorld
|
|
(
|
|
&stSource,
|
|
&stDest,
|
|
hSectorInCollision,
|
|
hCamera
|
|
)
|
|
)
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Visibility with multi segment.
|
|
* This function send "_lNbRay" segment and failed with the first one.
|
|
*=================================================================================================
|
|
*/
|
|
char CAM_fn_cSendMultiSegment
|
|
(
|
|
CAM_tdstUpdateCamera *_p_stStruct,
|
|
MTH3D_tdstVector *_p_stSourcePos,
|
|
MTH3D_tdstVector *_p_stTargetPos,
|
|
MTH_tdxReal _xRadiusCamera,
|
|
MTH_tdxReal _xRadiusTarget,
|
|
long _lNbRay
|
|
)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stDirection;
|
|
MTH3D_tdstVector stPositionSource, stPositionSource1;
|
|
MTH3D_tdstVector stPositionTarget, stPositionTarget1;
|
|
MTH_tdstRotation stRotation;
|
|
MTH3D_tdstVector stAxisZ, stVector;
|
|
long i;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/*
|
|
* Center if just one ray.
|
|
*/
|
|
if(_lNbRay == 1)
|
|
{
|
|
return CAM_fn_cSendSegment
|
|
(
|
|
_p_stStruct,
|
|
_p_stSourcePos,
|
|
_p_stTargetPos
|
|
);
|
|
}
|
|
|
|
/*
|
|
* Compute the first vector (ray of a sphere from center of source to _xRadiusCamera).
|
|
*/
|
|
MTH3D_M_vSubVector(&stDirection, _p_stTargetPos, _p_stSourcePos);
|
|
MTH3D_M_vNormalizeVector(&stDirection, &stDirection);
|
|
|
|
MTH3D_M_vSetBaseKVector(&stAxisZ);
|
|
MTH3D_M_vCrossProductVectorWithoutBuffer(&stVector, &stDirection, &stAxisZ);
|
|
if(MTH3D_M_bIsNullVector(&stVector))
|
|
{
|
|
MTH3D_M_vSetBaseIVector(&stAxisZ);
|
|
MTH3D_M_vCrossProductVectorWithoutBuffer(&stVector, &stDirection, &stAxisZ);
|
|
}
|
|
MTH3D_M_vNormalizeVector(&stVector, &stVector);
|
|
MTH3D_M_vMulScalarVector(&stVector, _xRadiusCamera, &stVector);
|
|
|
|
/* Rotation axis is vector source to target */
|
|
MTH_M_RotationSetAxis(&stRotation, &stDirection);
|
|
|
|
/* Normal rotation angle is 2Pi / Nb ray */
|
|
MTH_M_xRotationSetAngle(&stRotation, MTH_M_xDiv(MTH_C_2Pi, _lNbRay));
|
|
|
|
for(i = 0; i < _lNbRay; i++)
|
|
{
|
|
/* Compute source point position */
|
|
/*MTH3D_M_vCopyVector(&stPositionSource, &stVector);
|
|
MTH3D_M_vMulScalarVector(&stPositionSource, _xRadiusCamera, &stPositionSource);*/
|
|
MTH3D_M_vMulScalarVector(&stPositionSource, _xRadiusCamera, &stVector); /* remplace les 2 lignes du dessus*/
|
|
MTH3D_M_vAddVector(&stPositionSource1, &stPositionSource, _p_stSourcePos);
|
|
|
|
/* Compute target point position */
|
|
/*MTH3D_M_vCopyVector(&stPositionTarget, &stVector);
|
|
MTH3D_M_vMulScalarVector(&stPositionTarget, _xRadiusTarget, &stPositionTarget);*/
|
|
MTH3D_M_vMulScalarVector(&stPositionTarget, _xRadiusTarget, &stVector); /* remplace les 2 lignes du dessus*/
|
|
MTH3D_M_vAddVector(&stPositionTarget1, &stPositionTarget, _p_stTargetPos);
|
|
|
|
/* Throw a ray */
|
|
if
|
|
(
|
|
CAM_fn_cSendSegment
|
|
(
|
|
_p_stStruct,
|
|
&stPositionSource1,
|
|
&stPositionTarget1
|
|
)
|
|
)
|
|
return 1;
|
|
|
|
/* Rotate to find the new position */
|
|
MTH_p_stRotationMulVector(&stRotation, &stVector, &stVector);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Compute impact point of camera from a source to a dest point.
|
|
* There must be an impact !!! (don't call this function to test a collision, but when a collision
|
|
* occured to retreive impact point).
|
|
*=================================================================================================
|
|
*/
|
|
|
|
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
|
|
char CAM_fn_cComputeImpactPointWithCameraSphere
|
|
(
|
|
CAM_tdstUpdateCamera *_p_stStruct,
|
|
MTH3D_tdstVector *_p_stSource,
|
|
MTH3D_tdstVector *_p_stTarget,
|
|
MTH3D_tdstVector *_p_stImpact
|
|
)
|
|
{
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
POS_tdstCompletePosition stMatrix1, stMatrix2;
|
|
/*HIE_tdxHandleToSuperObject hTmpSector;*/
|
|
char cRes1;
|
|
DNM_tdstMecObstacle stObstacle;
|
|
MTH_tdxReal xNorm;
|
|
/*MS_tdxHandleToSectInfo hSectInfo = M_GetMSHandle(_p_stStruct->hSuperObjCamera, SectInfo);*/
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
if(_p_stImpact == NULL)
|
|
return 1;
|
|
|
|
/*
|
|
* Test with camera sphere
|
|
*-------------------------
|
|
*/
|
|
POS_fn_vSetIdentityMatrix(&stMatrix1);
|
|
POS_fn_vSetIdentityMatrix(&stMatrix2);
|
|
POS_fn_vSetTranslationVector(&stMatrix1, _p_stSource);
|
|
POS_fn_vSetTranslationVector(&stMatrix2, _p_stTarget);
|
|
|
|
/* Save sector */ /*INUTILE CAR LE TEST DE COLLISION NE MET PLUS A JOUR LES INFOS DE SECTEUR*/
|
|
/*hTmpSector = fn_h_SectInfoGetCurrentSector(hSectInfo);*/
|
|
cRes1 = (char) CAM_lHaveITakeSThgIntoTheMug
|
|
(
|
|
&stObstacle,
|
|
_p_stStruct->hSuperObjCamera,
|
|
&stMatrix1,
|
|
&stMatrix2
|
|
);
|
|
|
|
/* Restore sector */
|
|
/*fn_vSectInfoSetCurrentSector(hSectInfo, hTmpSector);*/
|
|
if(!cRes1)
|
|
{
|
|
MTH3D_M_vNullVector(_p_stImpact);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Compute impact point
|
|
*----------------------
|
|
*/
|
|
MTH3D_M_vSubVector(_p_stImpact, _p_stTarget, _p_stSource);
|
|
MTH3D_M_vMulScalarVector(_p_stImpact, DNM_M_xObstacleGetRate(&stObstacle), _p_stImpact);
|
|
xNorm = MTH_M_xSub(MTH3D_M_xNormVector(_p_stImpact), MTH_M_xFloatToReal(0.02f));
|
|
if (MTH_M_bLessZero(xNorm))
|
|
{
|
|
MTH3D_M_vCopyVector(_p_stImpact,_p_stSource);
|
|
}
|
|
else
|
|
{
|
|
MTH3D_M_vNormalizeVector(_p_stImpact, _p_stImpact);
|
|
MTH3D_M_vMulScalarVector(_p_stImpact, xNorm, _p_stImpact);
|
|
MTH3D_M_vAddVector(_p_stImpact, _p_stImpact, _p_stSource);
|
|
}
|
|
return 1;
|
|
}
|
|
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
|
|
|
|
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
VISIBILITY : MORE HIGH LEVEL TEST OF VISIBILITY
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Can't camera go to a given point ?
|
|
*=================================================================================================
|
|
*/
|
|
char CAM_fn_cCameraCantGo
|
|
(
|
|
CAM_tdstUpdateCamera *_p_stStruct,
|
|
MTH3D_tdstVector *_p_stSourcePos,
|
|
MTH3D_tdstVector *_p_stTargetPos
|
|
)
|
|
{
|
|
return CAM_fn_cSendMultiSegment
|
|
(
|
|
_p_stStruct,
|
|
_p_stSourcePos,
|
|
_p_stTargetPos,
|
|
CAM_C_xRayCameraSphereToGo1,
|
|
CAM_C_xRayCameraSphereToGo2,
|
|
CAM_C_xNumRayCameraCanGo
|
|
);
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Can't camera go to a given point ? For failure, we must be sure that this will be correct.
|
|
*=================================================================================================
|
|
*/
|
|
char CAM_fn_cCameraCantGoFailure
|
|
(
|
|
CAM_tdstUpdateCamera *_p_stStruct,
|
|
MTH3D_tdstVector *_p_stSourcePos,
|
|
MTH3D_tdstVector *_p_stTargetPos
|
|
)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stTempVector;
|
|
MTH_tdxReal xNorm;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/* First the destination point is farest with the ZDM ray of camera */
|
|
MTH3D_M_vSubVector(&stTempVector, _p_stTargetPos, _p_stSourcePos);
|
|
xNorm = MTH3D_M_xNormVector(&stTempVector);
|
|
xNorm = MTH_M_xAdd(xNorm, MTH_M_xFloatToReal(0.35f));
|
|
MTH3D_M_vNormalizeVector(&stTempVector, &stTempVector);
|
|
MTH3D_M_vMulScalarVector(&stTempVector, xNorm, &stTempVector);
|
|
MTH3D_M_vAddVector(&stTempVector, &stTempVector, _p_stSourcePos);
|
|
|
|
/* First the few ray */
|
|
return CAM_fn_cSendMultiSegment
|
|
(
|
|
_p_stStruct,
|
|
_p_stSourcePos,
|
|
&stTempVector,
|
|
CAM_C_xRayCameraSphereToGo1,
|
|
CAM_C_xRayCameraSphereToGo2,
|
|
CAM_C_xNumRayCameraCanGo
|
|
);
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Can't camera see a given point ?
|
|
*=================================================================================================
|
|
*/
|
|
char CAM_fn_cCameraCantSee
|
|
(
|
|
CAM_tdstUpdateCamera *_p_stStruct,
|
|
MTH3D_tdstVector *_p_stSourcePos,
|
|
MTH3D_tdstVector *_p_stTargetPos
|
|
)
|
|
{
|
|
return CAM_fn_cSendMultiSegment
|
|
(
|
|
_p_stStruct,
|
|
_p_stSourcePos,
|
|
_p_stTargetPos,
|
|
CAM_C_xRayCameraSphereToSee1,
|
|
CAM_C_xRayCameraSphereToSee2,
|
|
CAM_C_xNumRayCameraCanSee
|
|
);
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Is wanted pos not good ?
|
|
* This function determis if a given position is correct.
|
|
*=================================================================================================
|
|
*/
|
|
char CAM_fn_cIsWantedPosIncorrect
|
|
(
|
|
CAM_tdstUpdateCamera *_p_stStruct,
|
|
MTH3D_tdstVector *_p_stWantedPos,
|
|
char _cMode
|
|
)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stTempVector;
|
|
char cCant;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/*
|
|
* Wanted too short from target : Exit
|
|
*/
|
|
MTH3D_M_vSubVector(&stTempVector, _p_stWantedPos, &_p_stStruct->stTargetedPersoRealPos);
|
|
if(MTH_M_bLess(MTH3D_M_xNormVector(&stTempVector), CAM_C_xMinDistPersoToComputePos))
|
|
return 1;
|
|
|
|
/*
|
|
* Test visibility : Target to real wanted
|
|
*------------------------------------------
|
|
*/
|
|
if(_cMode & C_mode_MUSTSEE)
|
|
{
|
|
/*
|
|
* In failure mode, we send a ray cause we want to be sure that position
|
|
* is not already in collision.
|
|
* Else we send a normal ray.
|
|
*/
|
|
cCant = ((_cMode & C_mode_FAILURE) ? CAM_fn_cCameraCantGoFailure : CAM_fn_cCameraCantSee) (_p_stStruct, &_p_stStruct->stTargetedPersoRealPos, _p_stWantedPos);
|
|
/*EQUIVALENT A CECI, MAIS GENERE NORMALEMENT MOINS DE CODE
|
|
if(_cMode & C_mode_FAILURE)
|
|
cCant = CAM_fn_cCameraCantGoFailure(_p_stStruct, &_p_stStruct->stTargetedPersoRealPos, _p_stWantedPos);
|
|
else
|
|
cCant = CAM_fn_cCameraCantSee(_p_stStruct, &_p_stStruct->stTargetedPersoRealPos, _p_stWantedPos);*/
|
|
|
|
if(cCant)
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Test visibility : Current to real wanted position
|
|
*----------------------------------------------------
|
|
*/
|
|
if(_cMode & C_mode_MUSTGO)
|
|
{
|
|
cCant = CAM_fn_cCameraCantGo(_p_stStruct, &_p_stStruct->stCurrentCameraPos, _p_stWantedPos);
|
|
|
|
if(cCant)
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
COMPUTE A NEW GOOD IDEAL POS
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Compute a good position with a given direction.
|
|
*=================================================================================================
|
|
*/
|
|
char CAM_fn_cFindCorrectPosWithDir
|
|
(
|
|
CAM_tdstUpdateCamera *_p_stStruct,
|
|
MTH3D_tdstVector *_p_stDir,
|
|
MTH3D_tdstVector *_p_stCompute,
|
|
char _cMode
|
|
)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stTestedPos;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/*
|
|
* Compute new pos with direction
|
|
*/
|
|
MTH3D_M_vAddVector(&stTestedPos, _p_stDir, &_p_stStruct->stTargetedPersoPos);
|
|
|
|
/*
|
|
* Test position.
|
|
*/
|
|
if(CAM_fn_cIsWantedPosIncorrect(_p_stStruct, &stTestedPos, _cMode))
|
|
return 0;
|
|
/*
|
|
* Position correct : Success.
|
|
*/
|
|
else
|
|
{
|
|
MTH3D_M_vCopyVector(_p_stCompute, &stTestedPos);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Compute the pound of a position. Less it is, better it is.
|
|
*=================================================================================================
|
|
*/
|
|
MTH_tdxReal CAM_fnx_ComputePosPound(CAM_tdstUpdateCamera *_pst_Struct, MTH3D_tdstVector *_pst_Dir)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH_tdxReal x_Pound, x_Angle, x_Angle1;
|
|
MTH_tdxReal x_P1, x_P2, x_P3;
|
|
MTH3D_tdstVector st_TempVector;
|
|
struct tdstInternalStructurCineinfo_ *pst_Memo;
|
|
struct tdstInternalStructurCineinfo_ st_Temp;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/*
|
|
* Compute requested position.
|
|
*/
|
|
MTH3D_M_vAddVector(&st_TempVector, &_pst_Struct->stTargetedPersoPos, _pst_Dir);
|
|
|
|
/*
|
|
* Compute parameters of camera for that position. We compute the parameters in a private
|
|
* internal structure (cause we don't want to save them).
|
|
*/
|
|
pst_Memo = _pst_Struct->hCineinfoWork;
|
|
|
|
st_Temp.hSuperObjectTargeted = _pst_Struct->hCineinfoWork->hSuperObjectTargeted;
|
|
st_Temp.hSecondSuperObjectTargeted = _pst_Struct->hCineinfoWork->hSecondSuperObjectTargeted;
|
|
st_Temp.cChannel = _pst_Struct->hCineinfoWork->cChannel;
|
|
|
|
_pst_Struct->hCineinfoWork = &st_Temp;
|
|
CAM_fn_vComputeCineinfoWorkForAPosition(_pst_Struct, &st_TempVector);
|
|
_pst_Struct->hCineinfoWork = pst_Memo;
|
|
|
|
/*
|
|
* Compute pound of that position depending on ideal parameters.
|
|
*/
|
|
|
|
/* Alpha */
|
|
x_Angle = MTH_M_bGreater(gst_Ideal.xAngleAlpha, MTH_C_Pi) ? MTH_M_xSub(MTH_C_2Pi, gst_Ideal.xAngleAlpha) : gst_Ideal.xAngleAlpha;
|
|
x_Angle1 = MTH_M_bGreater(st_Temp.xAngleAlpha, MTH_C_Pi) ? MTH_M_xSub(MTH_C_2Pi, st_Temp.xAngleAlpha) : st_Temp.xAngleAlpha;
|
|
x_P1 = MTH_M_xAbs(MTH_M_xSub(x_Angle, x_Angle1));
|
|
|
|
x_P1 = MTH_M_xLongToReal(MTH_M_xRealToLongRound(MTH_M_xMul(x_P1, MTH_M_xFloatToReal(100))));
|
|
x_P1 = MTH_M_xMul(x_P1, MTH_M_xFloatToReal(0.01f));
|
|
|
|
/* Theta */
|
|
x_Angle = MTH_M_bGreater(gst_Ideal.xAngleTheta, MTH_C_Pi) ? MTH_M_xSub(MTH_C_2Pi, gst_Ideal.xAngleTheta) : gst_Ideal.xAngleTheta;
|
|
x_Angle1 = MTH_M_bGreater(st_Temp.xAngleTheta, MTH_C_Pi) ? MTH_M_xSub(st_Temp.xAngleTheta, MTH_C_2Pi) : st_Temp.xAngleTheta;
|
|
x_P2 = MTH_M_xAbs(MTH_M_xSub(x_Angle, x_Angle1));
|
|
|
|
x_P2 = MTH_M_xLongToReal(MTH_M_xRealToLongRound(MTH_M_xMul(x_P2, MTH_M_xFloatToReal(100))));
|
|
// x_P2 = MTH_M_xMul(x_P2, MTH_M_xFloatToReal(0.01f));
|
|
x_P2 = MTH_M_xMul(x_P2, MTH_M_xFloatToReal(0.10f));
|
|
|
|
/* Distance to target */
|
|
x_P3 = MTH_M_xAbs(MTH_M_xSub(gst_Ideal.xDistMin, st_Temp.xDistMin));
|
|
|
|
x_P3 = MTH_M_xLongToReal(MTH_M_xRealToLongRound(MTH_M_xMul(x_P3, MTH_M_xFloatToReal(100))));
|
|
x_P3 = MTH_M_xMul(x_P3, MTH_M_xFloatToReal(0.01f));
|
|
|
|
/*
|
|
* Compute final pound.
|
|
*/
|
|
x_Pound = MTH_M_xAdd(x_P1, x_P2);
|
|
x_Pound = MTH_M_xAdd(x_Pound, MTH_M_xMul(x_P3, MTH_M_xFloatToReal(0.1f)));
|
|
|
|
return x_Pound;
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Determin if a vector need to be eliminate.
|
|
*=================================================================================================
|
|
*/
|
|
char CAM_fnc_IsDirectionCorrect
|
|
(
|
|
CAM_tdstUpdateCamera *_p_stStruct,
|
|
MTH3D_tdstVector *_pst_Dir,
|
|
MTH_tdxReal _x_Pound,
|
|
MTH_tdxReal _x_PoundRef,
|
|
char _c_Mode
|
|
)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stTempVector;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/* Compute real position */
|
|
MTH3D_M_vAddVector(&stTempVector, _pst_Dir, &_p_stStruct->stTargetedPersoRealPos);
|
|
|
|
/*
|
|
* If we want a "more correct" position, assure that this new
|
|
* position is better than current one.
|
|
*------------------------------------------------------------
|
|
*/
|
|
if(_c_Mode & C_mode_MORE_CORRECT)
|
|
{
|
|
/* More bad than current pos */
|
|
if(MTH_M_bGreaterEqual(_x_Pound, _x_PoundRef))
|
|
return 0;
|
|
|
|
/* Too close from current pos */
|
|
_x_PoundRef = MTH_M_xSub(_x_PoundRef, _x_Pound);
|
|
if(MTH_M_bLess(_x_PoundRef, MTH_M_xFloatToReal(0.05f)))
|
|
return 0;
|
|
|
|
/* Position must reset last failed wanted */
|
|
if(!CAM_fn_cCanResetConstraintMoveVisFailure(_p_stStruct, &stTempVector))
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Norm of vector too small (to near from perso)
|
|
*-----------------------------------------------
|
|
*/
|
|
|
|
if(MTH_M_bLess(MTH3D_M_xNormVector(_pst_Dir), CAM_C_xMinDistPersoToComputePos))
|
|
return 0;
|
|
|
|
/*
|
|
* Vectors too near from wanted camera position
|
|
*-----------------------------------------------
|
|
*/
|
|
if
|
|
(
|
|
(!(_c_Mode & C_mode_FAILURE))
|
|
&& CAM_fn_bEqualVectorWithEpsilon
|
|
(
|
|
&stTempVector,
|
|
&_p_stStruct->stWantedCameraPos,
|
|
CAM_C_xEpsilonForEqualVectors
|
|
)
|
|
)
|
|
return 0;
|
|
|
|
/*
|
|
* Vectors too near from current camera position
|
|
*-----------------------------------------------
|
|
*/
|
|
if
|
|
(
|
|
((!(_c_Mode & C_mode_FAILURE)) || (_c_Mode & C_mode_MORE_CORRECT))
|
|
&& CAM_fn_bEqualVectorWithEpsilon
|
|
(
|
|
&stTempVector,
|
|
&_p_stStruct->stCurrentCameraPos,
|
|
CAM_C_xEpsilonForEqualVectors
|
|
)
|
|
)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Compare two positions.
|
|
* To sort vectors depending on their pounds (less to greater).
|
|
*=================================================================================================
|
|
*/
|
|
int CAM_fni_ComparePositions(const void *_pv_Elem1, const void *_pv_Elem2)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH_tdxReal xPound1, xPound2;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
xPound1 = ((tdst_PosPound *) _pv_Elem1)->xPound;
|
|
xPound2 = ((tdst_PosPound *) _pv_Elem2)->xPound;
|
|
return (MTH_M_bGreater(xPound2, xPound1)) ? -1 : (MTH_M_bEqual(xPound2, xPound1)) ? 0 : 1;
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Fill array gast_VectorArrayCpt to set angles to test.
|
|
*=================================================================================================
|
|
*/
|
|
void CAM_fn_vFillVectorArray(CAM_tdstUpdateCamera *_p_stStruct, char _cMode)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stAxis, stTempVector, *p_stDir;
|
|
MTH_tdxReal xAngle, xBaseAngle, xNormIdeal, xSaveTheta;
|
|
unsigned long ulCounter, ulMax, ulAngle;
|
|
struct tdstInternalStructurCineinfo_ stTemp;
|
|
CAM_tdstUpdateCamera stStruct;
|
|
enum e_ucCameraStates_ eState;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/*
|
|
* Init structures for compute.
|
|
*/
|
|
CAM_fn_vInitCameraStructure(_p_stStruct->hSuperObjCamera, &stStruct);
|
|
stStruct.hCineinfoWork = &stTemp;
|
|
memcpy(&stTemp, &gst_Ideal, sizeof(struct tdstInternalStructurCineinfo_));
|
|
CAM_fn_vComputeReferencePoint(&stStruct);
|
|
|
|
/*
|
|
* Get ideal norm.
|
|
*/
|
|
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stRealWantedCameraPos, &_p_stStruct->stTargetedPersoPos);
|
|
xNormIdeal = MTH3D_M_xNormVector(&stTempVector);
|
|
|
|
/*
|
|
* Get axis of face perso is walking on.
|
|
*/
|
|
if(!CAM_fn_bPersoOnFace(_p_stStruct->hCineinfoWork->hSuperObjectTargeted, &stAxis))
|
|
{
|
|
MTH3D_M_vSetVectorElements(&stAxis, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE);
|
|
}
|
|
|
|
/*
|
|
* Base rotation angle depending on failure mode or not.
|
|
*/
|
|
xBaseAngle = (_cMode & C_mode_FAILURE) ? CAM_C_xBaseAngleComputePosFailure : CAM_C_xBaseAngleComputePosNormal;
|
|
/* EQUIVALENT A:
|
|
if(_cMode & C_mode_FAILURE)
|
|
xBaseAngle = CAM_C_xBaseAngleComputePosFailure;
|
|
else
|
|
xBaseAngle = CAM_C_xBaseAngleComputePosNormal;*/
|
|
|
|
/*
|
|
* Fill array with all vectors computed with angles.
|
|
*--------------------------------------------------
|
|
*/
|
|
ulCounter = 0;
|
|
ulMax = MTH_M_xDiv(MTH_C_2Pi, xBaseAngle);
|
|
xAngle = stTemp.xAngleAlpha;
|
|
|
|
/* !!! To force ComputeMovePos to take walues from work and not from current ! */
|
|
eState = stStruct.hCineinfo->eState;
|
|
stStruct.hCineinfo->eState = CAM_e_State_GoToOptimal;
|
|
|
|
xSaveTheta = stTemp.xAngleTheta;
|
|
for ( ulAngle = 0; ulAngle < ulMax; ulAngle ++ )
|
|
{
|
|
/* Compute wanted position with a given alpha */
|
|
stTemp.xAngleAlpha = xAngle;
|
|
stTemp.xAngleAlpha = CAM_fn_xSetAngleInInterval02Pi(stTemp.xAngleAlpha);
|
|
stTemp.xAngleTheta = xSaveTheta;
|
|
stStruct.hCineinfoWork->uwIAFlags |= C_IAFlags_NoShiftUntilPosReached;
|
|
CAM_fn_vComputeMovePosWithDynTheta(&stStruct);
|
|
|
|
/* Compute direction with good dist */
|
|
p_stDir = &gast_VectorArrayCpt[ulCounter].stDir;
|
|
MTH3D_M_vSubVector(p_stDir, &stStruct.stWantedCameraPos, &stStruct.stTargetedPersoPos);
|
|
gast_VectorArrayCpt[ulCounter].xPound = CAM_fnx_ComputePosPound(_p_stStruct, p_stDir);
|
|
ulCounter++;
|
|
|
|
/* The same dir with a different norm : We took xNormIdeal/2 */
|
|
if(!CONSTANT_NODISTVIS)
|
|
{
|
|
if(_cMode & C_mode_FAILURE)
|
|
{
|
|
p_stDir = &gast_VectorArrayCpt[ulCounter].stDir;
|
|
MTH3D_M_vSubVector(p_stDir, &stStruct.stWantedCameraPos, &stStruct.stTargetedPersoPos);
|
|
MTH3D_M_vNormalizeVector(p_stDir, p_stDir);
|
|
MTH3D_M_vMulScalarVector(p_stDir, MTH_M_xMul(xNormIdeal, MTH_M_xFloatToReal(0.5f)), p_stDir);
|
|
gast_VectorArrayCpt[ulCounter].xPound = CAM_fnx_ComputePosPound(_p_stStruct, p_stDir);
|
|
ulCounter++;
|
|
if(_cMode & C_mode_MORE_CORRECT)
|
|
{
|
|
p_stDir = &gast_VectorArrayCpt[ulCounter].stDir;
|
|
MTH3D_M_vSubVector(p_stDir, &stStruct.stWantedCameraPos, &stStruct.stTargetedPersoPos);
|
|
MTH3D_M_vNormalizeVector(p_stDir, p_stDir);
|
|
MTH3D_M_vMulScalarVector(p_stDir, MTH_M_xMul(xNormIdeal, MTH_M_xFloatToReal(0.33f)), p_stDir);
|
|
gast_VectorArrayCpt[ulCounter].xPound = CAM_fnx_ComputePosPound(_p_stStruct, p_stDir);
|
|
ulCounter++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* WITH THETA = 0 */
|
|
stTemp.xAngleTheta = MTH_C_ZERO;
|
|
stStruct.hCineinfoWork->uwIAFlags |= C_IAFlags_NoShiftUntilPosReached;
|
|
CAM_fn_vComputeMovePosWithDynTheta(&stStruct);
|
|
|
|
/* Compute direction with good dist */
|
|
p_stDir = &gast_VectorArrayCpt[ulCounter].stDir;
|
|
MTH3D_M_vSubVector(p_stDir, &stStruct.stWantedCameraPos, &stStruct.stTargetedPersoPos);
|
|
gast_VectorArrayCpt[ulCounter].xPound = CAM_fnx_ComputePosPound(_p_stStruct, p_stDir);
|
|
ulCounter++;
|
|
|
|
/* WITH THETA = Pi/4 */
|
|
stTemp.xAngleTheta = MTH_C_PiBy4;
|
|
stStruct.hCineinfoWork->uwIAFlags |= C_IAFlags_NoShiftUntilPosReached;
|
|
CAM_fn_vComputeMovePosWithDynTheta(&stStruct);
|
|
|
|
/* Compute direction with good dist */
|
|
p_stDir = &gast_VectorArrayCpt[ulCounter].stDir;
|
|
MTH3D_M_vSubVector(p_stDir, &stStruct.stWantedCameraPos, &stStruct.stTargetedPersoPos);
|
|
gast_VectorArrayCpt[ulCounter].xPound = CAM_fnx_ComputePosPound(_p_stStruct, p_stDir);
|
|
ulCounter++;
|
|
|
|
/* WITH THETA = -Pi/4 */
|
|
stTemp.xAngleTheta = -MTH_C_PiBy4;
|
|
stStruct.hCineinfoWork->uwIAFlags |= C_IAFlags_NoShiftUntilPosReached;
|
|
CAM_fn_vComputeMovePosWithDynTheta(&stStruct);
|
|
|
|
/* Compute direction with good dist */
|
|
p_stDir = &gast_VectorArrayCpt[ulCounter].stDir;
|
|
MTH3D_M_vSubVector(p_stDir, &stStruct.stWantedCameraPos, &stStruct.stTargetedPersoPos);
|
|
gast_VectorArrayCpt[ulCounter].xPound = CAM_fnx_ComputePosPound(_p_stStruct, p_stDir);
|
|
ulCounter++;
|
|
|
|
|
|
xAngle += xBaseAngle;
|
|
}
|
|
guw_NbVectorArrayCpt = ulCounter;
|
|
|
|
stStruct.hCineinfo->eState = eState;
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Compute a new good ideal pos depending on real wanted position.
|
|
* _p_stComputeVector will receive computed position (if algo didn't fail).
|
|
* Returns: 1 in success
|
|
* 0 if failed
|
|
*=================================================================================================
|
|
*/
|
|
char CAM_fn_cFindNewGoodIdealPos
|
|
(
|
|
CAM_tdstUpdateCamera *_p_stStruct,
|
|
MTH3D_tdstVector *_p_stComputeVector,
|
|
char _cMode
|
|
)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
unsigned long ulCounter;
|
|
MTH3D_tdstVector stTempVector, *p_stDir;
|
|
MTH_tdxReal xPoundRef;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
MTH3D_M_vNullVector(_p_stComputeVector);
|
|
|
|
/*
|
|
* Compute pound of current wanted pos. When we want a better position, this is
|
|
* the reference pound (all positions with a greater poud will be eliminate).
|
|
*/
|
|
xPoundRef = MTH_C_ZERO;
|
|
if(_cMode & C_mode_MORE_CORRECT)
|
|
{
|
|
if(_cMode & C_mode_FAILURE)
|
|
{
|
|
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stCurrentCameraPos, &_p_stStruct->stTargetedPersoPos);
|
|
}
|
|
else
|
|
{
|
|
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stWantedCameraPos, &_p_stStruct->stTargetedPersoPos);
|
|
}
|
|
xPoundRef = CAM_fnx_ComputePosPound(_p_stStruct, &stTempVector);
|
|
}
|
|
|
|
/*
|
|
* Fill array of vectors to test.
|
|
*/
|
|
CAM_fn_vFillVectorArray(_p_stStruct, _cMode);
|
|
|
|
/*
|
|
* Sort array by priority.
|
|
*/
|
|
qsort
|
|
(
|
|
gast_VectorArrayCpt,
|
|
guw_NbVectorArrayCpt,
|
|
sizeof(tdst_PosPound),
|
|
CAM_fni_ComparePositions
|
|
);
|
|
|
|
/*
|
|
* Compute vector to test, and test...
|
|
*/
|
|
for ( ulCounter = 0; ulCounter < guw_NbVectorArrayCpt; ulCounter ++ )
|
|
{
|
|
p_stDir = &gast_VectorArrayCpt[ulCounter].stDir;
|
|
if
|
|
(
|
|
CAM_fnc_IsDirectionCorrect
|
|
(
|
|
_p_stStruct,
|
|
p_stDir,
|
|
gast_VectorArrayCpt[ulCounter].xPound,
|
|
xPoundRef,
|
|
_cMode
|
|
)
|
|
&&
|
|
CAM_fn_cFindCorrectPosWithDir
|
|
(
|
|
_p_stStruct,
|
|
p_stDir,
|
|
_p_stComputeVector,
|
|
_cMode
|
|
)
|
|
)
|
|
{
|
|
if(ulCounter == 0)
|
|
return 1;
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* We must find a position to force the camera, cause we can't go to a new computed position
|
|
* without collision or visibility.
|
|
* We search a new good position but don't test if we can go to it.
|
|
*=================================================================================================
|
|
*/
|
|
void CAM_fn_vForceFailureVisibility(CAM_tdstUpdateCamera *_p_stStruct)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stComputeVector, stTempVector;
|
|
char cMode;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/*
|
|
* Find a new position but we don't care if we can go to.
|
|
*/
|
|
cMode = C_mode_MUSTSEE|C_mode_FAILURE;
|
|
if(CONSTANT_FORCEBESTPOS)
|
|
cMode |= C_mode_MORE_CORRECT;
|
|
|
|
if(!CAM_fn_cFindNewGoodIdealPos(_p_stStruct, &stComputeVector, cMode))
|
|
return;
|
|
|
|
/*
|
|
* Determin if we cut or not. If camera can see the computed one, or if distance if
|
|
* short enought, don't cut.
|
|
*/
|
|
MTH3D_M_vSubVector(&stTempVector, &stComputeVector, &_p_stStruct->stCurrentCameraPos);
|
|
_p_stStruct->hCineinfo->eState = CAM_e_State_FailureVisibility;
|
|
|
|
/*
|
|
* To remember the position where we want to go.
|
|
*/
|
|
MTH3D_M_vCopyVector(&_p_stStruct->hCineinfo->stLastFailedWanted, &stComputeVector);
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Compute the move after a failure visibility.
|
|
*=================================================================================================
|
|
*/
|
|
void CAM_fn_vComputeFailureVisibility(CAM_tdstUpdateCamera *_p_stStruct)
|
|
{
|
|
if(_p_stStruct->hCineinfo->eState == CAM_e_State_FailureVisibility)
|
|
{
|
|
/*
|
|
* Force camera to pos at stLastFailedWanted.
|
|
* Force target.
|
|
*/
|
|
CAM_fn_vForceCameraPos(_p_stStruct->hSuperObjCamera, &_p_stStruct->hCineinfo->stLastFailedWanted);
|
|
CAM_fn_vForceCameraTgt(_p_stStruct->hSuperObjCamera, &_p_stStruct->stCptPos.stTarget, &_p_stStruct->stCptPos.stRefAxisZ);
|
|
MTH3D_M_vCopyVector(&_p_stStruct->stCurrentCameraPos, &_p_stStruct->hCineinfo->stLastFailedWanted);
|
|
|
|
/*
|
|
* This is the new ideal position.
|
|
*/
|
|
CAM_fn_vMakeAsNewIdealPosition(_p_stStruct, &_p_stStruct->hCineinfo->stLastFailedWanted);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Call to check if perso if not closest from camera.
|
|
* If it's a case, we try to find a new good ideal position.
|
|
*=================================================================================================
|
|
*/
|
|
void CAM_fn_vTestBadDistance(CAM_tdstUpdateCamera *_p_stStruct)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stTempVector, stComputeVector;
|
|
char cMode;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/*
|
|
* State must be optimal of computed optimal. We make the test cause a previous function
|
|
* can have change the state to force to failure.
|
|
*/
|
|
if
|
|
(
|
|
(_p_stStruct->hCineinfo->eState != CAM_e_State_GoToOptimal)
|
|
&& (_p_stStruct->hCineinfo->eState != CAM_e_State_GoToComputedOptimal)
|
|
)
|
|
return;
|
|
|
|
/*
|
|
* Flags must be correct.
|
|
*/
|
|
if
|
|
(
|
|
(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_TargetIsAlreadyComputed)
|
|
|| (_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_PositionIsAlreadyComputed)
|
|
|| (_p_stStruct->hCineinfo->ucVolIAFlags & C_VolIAFlags_InitJustCopiedInCurrent)
|
|
)
|
|
return;
|
|
|
|
/*
|
|
* Get vector of current camera pos to real target to get distance.
|
|
*/
|
|
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stCurrentCameraPos, &_p_stStruct->stTargetedPersoRealPos);
|
|
|
|
/*
|
|
* Failed in distance if :
|
|
* - Distance is less than minimal one.
|
|
* - We are in collision or camera doesn't move.
|
|
*/
|
|
if
|
|
(
|
|
(MTH_M_bGreater(MTH3D_M_xNormVector(&stTempVector), CAM_C_xMinDistPerso))
|
|
|| (
|
|
(!(DNM_M_bReportCollision(_p_stStruct->p_stReport)))
|
|
&& (!(_p_stStruct->hCineinfo->ucVolIAFlags & C_VolIAFlags_CameraNotMove))
|
|
)
|
|
)
|
|
return;
|
|
|
|
/*
|
|
* If current wanted position is correct, don't search, that's it !
|
|
*/
|
|
if(!CAM_fn_cIsWantedPosIncorrect(_p_stStruct, &_p_stStruct->stWantedCameraPos, C_mode_MUSTGO|C_mode_MUSTSEE))
|
|
return;
|
|
|
|
/*
|
|
* We try to find another correct position.
|
|
* If not, failure.
|
|
* If yes, this is the new ideal one.
|
|
*/
|
|
/* ANNECY MT - 03/08/99 { */
|
|
/* _p_stStruct->hCineinfo->wCounter1 = 0; */
|
|
_p_stStruct->hCineinfo->xCounter1 = MTH_C_ZERO;
|
|
/* END ANNECY MT } */
|
|
|
|
cMode = C_mode_MUSTGO|C_mode_MUSTSEE;
|
|
if(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoVisibility)
|
|
cMode &= ~C_mode_MUSTSEE;
|
|
|
|
if(!CAM_fn_cFindNewGoodIdealPos(_p_stStruct, &stComputeVector, cMode))
|
|
CAM_fn_vForceFailureVisibility(_p_stStruct);
|
|
else
|
|
{
|
|
CAM_fn_vMakeAsNewIdealPosition(_p_stStruct, &stComputeVector);
|
|
_p_stStruct->hCineinfo->ucPerIAFlags |= C_PerIAFlags_ConstraintMoveVisFailure;
|
|
}
|
|
}
|
|
|
|
/*
|
|
*=====================================================================================================
|
|
* Test visibility of camera.
|
|
* Returns 1 if camera must pass in a special state cause of unvisibility.
|
|
* Returns 0 else.
|
|
*=====================================================================================================
|
|
*/
|
|
void CAM_fn_vTestBadVisibility(CAM_tdstUpdateCamera *_p_stStruct)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stComputeVector, stTempVector;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
/*
|
|
* State must be optimal of computed optimal. We make the test cause a previous function
|
|
* can have change the state to force to failure.
|
|
*/
|
|
if
|
|
(
|
|
(_p_stStruct->hCineinfo->eState != CAM_e_State_GoToOptimal)
|
|
&& (_p_stStruct->hCineinfo->eState != CAM_e_State_GoToComputedOptimal)
|
|
)
|
|
return;
|
|
|
|
/*
|
|
* Flags must be correct.
|
|
*/
|
|
if
|
|
(
|
|
(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoVisibility)
|
|
// || (_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_TargetIsAlreadyComputed)
|
|
|| (_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_PositionIsAlreadyComputed)
|
|
|| (_p_stStruct->hCineinfo->ucVolIAFlags & C_VolIAFlags_InitJustCopiedInCurrent)
|
|
)
|
|
return;
|
|
|
|
/*
|
|
* Counter must be correct to test visibility.
|
|
*/
|
|
/* ANNECY MT - 03/08/99 { */
|
|
/* _p_stStruct->hCineinfo->wCounter2++; */
|
|
_p_stStruct->hCineinfo->xCounter2 = MTH_M_xAdd(_p_stStruct->hCineinfo->xCounter2,MTH_M_xFloatToReal(g_stEngineStructure.stEngineTimer.ulUsefulDeltaTime));
|
|
|
|
/* if(_p_stStruct->hCineinfo->wCounter2 < CAM_C_xTickTestVisibility) */
|
|
if(MTH_M_bLess(_p_stStruct->hCineinfo->xCounter2 , CAM_C_xTickTimeTestVisibility))
|
|
return;
|
|
|
|
|
|
/* _p_stStruct->hCineinfo->wCounter2 = 0; */
|
|
_p_stStruct->hCineinfo->xCounter2 = MTH_C_ZERO;
|
|
|
|
/* OPTIM RAY : Only if last trame, we don't failed */
|
|
/* if(_p_stStruct->hCineinfo->wCounter3 == 0) */
|
|
|
|
if(MTH_M_bIsNull(_p_stStruct->hCineinfo->xCounter3))
|
|
{
|
|
/* If camera doesn't move, don't test static hierarchy */
|
|
/* if(_p_stStruct->hCineinfo->wCounter4 > 10) */
|
|
if(MTH_M_bGreater(_p_stStruct->hCineinfo->xCounter4 , MTH_M_xMul(MTH_M_xFloatToReal(10000.0f),g_stEngineStructure.stEngineTimer.xFrameLength)))
|
|
/* END ANNECY MT } */
|
|
// {
|
|
// if(_p_stStruct->hCineinfo->wCounter4)
|
|
cCanTestStatic = 0;
|
|
else
|
|
{
|
|
MTH3D_tdstVector stVectorNull;
|
|
|
|
MTH3D_M_vNullVector(&stVectorNull);
|
|
|
|
/* If last move is quiet equal to ray, don't test static */
|
|
MTH3D_M_vCopyVector(&stComputeVector, DNM_M_p_stReportGetLastMove(_p_stStruct->p_stReport));
|
|
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stTargetedPersoRealPos, &_p_stStruct->stCurrentCameraPos);
|
|
|
|
if
|
|
(
|
|
(!CAM_fn_bEqualVectorWithEpsilon(&stComputeVector, &stVectorNull,MTH_M_xFloatToReal(0.0001f)))
|
|
&& (!CAM_fn_bEqualVectorWithEpsilon(&stTempVector, &stVectorNull,MTH_M_xFloatToReal(0.0001f)))
|
|
)
|
|
{
|
|
MTH3D_M_vNormalizeVector(&stComputeVector, &stComputeVector);
|
|
MTH3D_M_vNormalizeVector(&stTempVector, &stTempVector);
|
|
if(MTH_M_bGreater(MTH_M_xAbs(MTH3D_M_xDotProductVector(&stTempVector, &stComputeVector)), MTH_M_xFloatToReal(0.9f)))
|
|
cCanTestStatic = 0;
|
|
}
|
|
}
|
|
// }
|
|
}
|
|
|
|
/*
|
|
* Determin if we can see target real position.
|
|
* If we see it, exit cause no failed.
|
|
*/
|
|
/* ANNECY MT - 03/08/99 { */
|
|
if(!CAM_fn_cCameraCantSee(_p_stStruct, &_p_stStruct->stTargetedPersoRealPos, &_p_stStruct->stCurrentCameraPos))
|
|
{
|
|
/* _p_stStruct->hCineinfo->wCounter3 = 0; */
|
|
_p_stStruct->hCineinfo->xCounter3 = MTH_C_ZERO;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* FAILURE.
|
|
* Check for a too long time without seeing target.
|
|
*/
|
|
/* _p_stStruct->hCineinfo->wCounter3++; */
|
|
_p_stStruct->hCineinfo->xCounter3 = MTH_M_xAdd(_p_stStruct->hCineinfo->xCounter3,MTH_M_xFloatToReal(g_stEngineStructure.stEngineTimer.ulUsefulDeltaTime));
|
|
|
|
/* if(MTH_M_bGreater(_p_stStruct->hCineinfo->wCounter3, CAM_C_xTickFailureCantSee)) */
|
|
if(MTH_M_bGreater(_p_stStruct->hCineinfo->xCounter3 , CAM_C_xTickTimeFailureCantSee))
|
|
{
|
|
/* _p_stStruct->hCineinfo->wCounter3 = 0; */
|
|
_p_stStruct->hCineinfo->xCounter3 = MTH_C_ZERO;
|
|
CAM_fn_vForceFailureVisibility(_p_stStruct);
|
|
return;
|
|
}
|
|
/* END ANNECY MT } */
|
|
|
|
/*
|
|
* Test if we can go to wanted position. If yes, exit cause no failed.
|
|
*/
|
|
if(!CAM_fn_cIsWantedPosIncorrect(_p_stStruct, &_p_stStruct->stWantedCameraPos, C_mode_MUSTGO|C_mode_MUSTSEE))
|
|
return;
|
|
|
|
/*
|
|
* We try to find another correct position.
|
|
* If not, failure.
|
|
* If yes, this is the new ideal one.
|
|
*/
|
|
/* ANNECY MT - 03/08/99 { */
|
|
/*
|
|
_p_stStruct->hCineinfo->wCounter1 = 0;
|
|
_p_stStruct->hCineinfo->wCounter3 = 0;
|
|
*/
|
|
_p_stStruct->hCineinfo->xCounter1 = MTH_C_ZERO;
|
|
_p_stStruct->hCineinfo->xCounter3 = MTH_C_ZERO;
|
|
/* END ANNECY MT } */
|
|
|
|
if(!CAM_fn_cFindNewGoodIdealPos(_p_stStruct, &stComputeVector, C_mode_MUSTGO|C_mode_MUSTSEE))
|
|
CAM_fn_vForceFailureVisibility(_p_stStruct);
|
|
else
|
|
{
|
|
CAM_fn_vMakeAsNewIdealPosition(_p_stStruct, &stComputeVector);
|
|
_p_stStruct->hCineinfo->ucPerIAFlags |= C_PerIAFlags_ConstraintMoveVisFailure;
|
|
}
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Call to check if camera collide with a face with an opposite normal
|
|
* If it's a case, we try to find a new good ideal position.
|
|
*=================================================================================================
|
|
*/
|
|
void CAM_fn_vTestOppositeCollision(CAM_tdstUpdateCamera *_p_stStruct)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stCameraMove;
|
|
char cMode;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/*
|
|
* State must be optimal of computed optimal. We make the test cause a previous function
|
|
* can have change the state to force to failure.
|
|
*/
|
|
if
|
|
(
|
|
(_p_stStruct->hCineinfo->eState != CAM_e_State_GoToOptimal)
|
|
&& (_p_stStruct->hCineinfo->eState != CAM_e_State_GoToComputedOptimal)
|
|
)
|
|
return;
|
|
|
|
/*
|
|
* Flags must be correct.
|
|
*/
|
|
if
|
|
(
|
|
(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_TargetIsAlreadyComputed)
|
|
|| (_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_PositionIsAlreadyComputed)
|
|
|| (_p_stStruct->hCineinfo->ucVolIAFlags & C_VolIAFlags_InitJustCopiedInCurrent)
|
|
)
|
|
return;
|
|
|
|
/*
|
|
* We must be in collision.
|
|
*/
|
|
if (!(DNM_M_bReportCollision(_p_stStruct->p_stReport)))
|
|
return;
|
|
|
|
/*
|
|
* Check a meca report for an opposite collision.
|
|
*/
|
|
if(!(DNM_M_bReportIsWall(_p_stStruct->p_stReport)))
|
|
return;
|
|
|
|
/*
|
|
* We try to find another correct position.
|
|
* If not, failure.
|
|
* If yes, this is the new ideal one.
|
|
*/
|
|
/* ANNECY MT - 03/08/99 { */
|
|
/* _p_stStruct->hCineinfo->wCounter1 = 0; */
|
|
_p_stStruct->hCineinfo->xCounter1 = MTH_C_ZERO;
|
|
/* END ANNECY MT } */
|
|
|
|
cMode = C_mode_MUSTGO|C_mode_MUSTSEE;
|
|
if(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoVisibility)
|
|
cMode &= ~C_mode_MUSTSEE;
|
|
|
|
if(!CAM_fn_cFindNewGoodIdealPos(_p_stStruct, &stCameraMove, cMode))
|
|
CAM_fn_vForceFailureVisibility(_p_stStruct);
|
|
else
|
|
CAM_fn_vMakeAsNewIdealPosition(_p_stStruct, &stCameraMove);
|
|
}
|
|
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*=====================================================================================================
|
|
* Compute cineinfowork parameters to go to a specific position.
|
|
* - hCineinfoWork must be correct.
|
|
* - In that structure, must be correct :
|
|
* * super object (first and second)
|
|
* * channel number
|
|
*=====================================================================================================
|
|
*/
|
|
void CAM_fn_vComputeCineinfoWorkForAPosition(CAM_tdstUpdateCamera *_p_stStruct, MTH3D_tdstVector *_p_stPosition)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stDir;
|
|
MTH3D_tdstVector stCamTargetVector;
|
|
MTH_tdxReal xAlphaAngle, xThetaAngle;
|
|
MTH_tdxReal xNorm;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/* Compute normal axis (super object direction or vector direction in cineinfo */
|
|
CAM_fn_vComputeRefAxis(_p_stStruct, &stDir);
|
|
|
|
/* Compute rotated axis */
|
|
MTH3D_M_vSubVector(&stCamTargetVector, _p_stPosition, &_p_stStruct->stTargetedPersoPos);
|
|
xNorm = MTH3D_M_xNormVector(&stCamTargetVector);
|
|
|
|
/* Compute alpha and theta angles */
|
|
CAM_fn_vComputeAnglesBetweenTwoVectors
|
|
(
|
|
_p_stStruct->hCineinfoWork,
|
|
&stDir,
|
|
&stCamTargetVector,
|
|
&xAlphaAngle,
|
|
&xThetaAngle,
|
|
&_p_stStruct->stCptPos.stRefAxisZ
|
|
);
|
|
|
|
/*
|
|
* Set new parameters
|
|
*/
|
|
_p_stStruct->hCineinfoWork->xDistMin = xNorm;
|
|
_p_stStruct->hCineinfoWork->xDistMax = xNorm;
|
|
_p_stStruct->hCineinfoWork->xAngleAlpha = xAlphaAngle;
|
|
_p_stStruct->hCineinfoWork->xAngleTheta = xThetaAngle;
|
|
}
|
|
void CAM_fn_vComputeCineinfoCurrentForAPosition(CAM_tdstUpdateCamera *_p_stStruct, MTH3D_tdstVector *_p_stPosition)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
struct tdstInternalStructurCineinfo_ *p_stMemo;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
p_stMemo = _p_stStruct->hCineinfoWork;
|
|
_p_stStruct->hCineinfoWork = _p_stStruct->hCineinfoCurrent;
|
|
CAM_fn_vComputeCineinfoWorkForAPosition(_p_stStruct, _p_stPosition);
|
|
_p_stStruct->hCineinfoWork = p_stMemo;
|
|
}
|
|
|
|
/*
|
|
*=================================================================================================
|
|
* Compute a new ideal position.
|
|
*=================================================================================================
|
|
*/
|
|
void CAM_fn_vMakeAsNewIdealPosition(CAM_tdstUpdateCamera *_p_stStruct, MTH3D_tdstVector *_p_stPosition)
|
|
{
|
|
/*
|
|
* Now, cut angle can go in the sens it wants...
|
|
*/
|
|
_p_stStruct->hCineinfo->cLastCutAngleSens = 0;
|
|
|
|
/*
|
|
* This is now a computed ideal position. Remember actual current cineinfo
|
|
* (just the first time, look at function).
|
|
*/
|
|
/* if(!(_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_VisibilityCopied))*/
|
|
/* {*/
|
|
CAM_fn_vSetCineinfoVisibilityFromCurrent(_p_stStruct->hCineinfo);
|
|
/* memcpy(_p_stStruct->hCineinfo->hVisibility, _p_stStruct->hCineinfo->hWork, sizeof(struct tdstInternalStructurCineinfo_));*/
|
|
/* _p_stStruct->hCineinfo->ucPerIAFlags |= C_PerIAFlags_VisibilityCopied;*/
|
|
/* }*/
|
|
|
|
/*
|
|
* Compute parameters for that position.
|
|
*/
|
|
CAM_fn_vComputeCineinfoCurrentForAPosition(_p_stStruct, _p_stPosition);
|
|
|
|
/*
|
|
* New state.
|
|
*/
|
|
_p_stStruct->hCineinfo->eState = CAM_e_State_GoToComputedOptimal;
|
|
|
|
/*
|
|
* When we compute a position, we don't want shift alpha and theta to live...
|
|
*/
|
|
_p_stStruct->hCineinfo->ucPerIAFlags |= C_PerIAFlags_NoShift;
|
|
|
|
/*
|
|
* Compute for now. We copy in work the filed of cineinfcurrent that have been
|
|
* modified by SetCineinfo...
|
|
*/
|
|
_p_stStruct->hCineinfoWork->xAngleAlpha = _p_stStruct->hCineinfoCurrent->xAngleAlpha;
|
|
_p_stStruct->hCineinfoWork->xAngleTheta = _p_stStruct->hCineinfoCurrent->xAngleTheta;
|
|
_p_stStruct->hCineinfoWork->xDistMin = _p_stStruct->hCineinfoCurrent->xDistMin;
|
|
_p_stStruct->hCineinfoWork->xDistMax = _p_stStruct->hCineinfoCurrent->xDistMax;
|
|
|
|
/*
|
|
* Compute move.
|
|
*/
|
|
CAM_fn_vComputeMovePos(_p_stStruct);
|
|
|
|
/*
|
|
* Remember positions.
|
|
*/
|
|
MTH3D_M_vCopyVector(&_p_stStruct->hCineinfo->stLastFailedOrigin, &_p_stStruct->stCurrentCameraPos);
|
|
MTH3D_M_vCopyVector(&_p_stStruct->hCineinfo->stLastFailedWanted, _p_stPosition);
|
|
}
|
|
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*=====================================================================================================
|
|
* Determin if we can reset stLastFailedWanted.
|
|
*=====================================================================================================
|
|
*/
|
|
char CAM_fn_cCanResetConstraintMoveVisFailure(CAM_tdstUpdateCamera *_p_stStruct, MTH3D_tdstVector *_p_stWanted)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stTempVector, stTempVector1;
|
|
MTH_tdxReal xNorm, xNorm1;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/*
|
|
* Normal state : Ok.
|
|
*/
|
|
if(_p_stStruct->hCineinfo->eState == CAM_e_State_GoToOptimal)
|
|
return 1;
|
|
|
|
/*
|
|
* If camera doesn't move for a too long time, we can reset.
|
|
*/
|
|
/* ANNECY MT - 03/08/99 { */
|
|
/* if(_p_stStruct->hCineinfo->wCounter4 >= CAM_C_xTickFindBetterPosIfNoMove) */
|
|
if(MTH_M_bGreaterEqual(_p_stStruct->hCineinfo->xCounter4,CAM_C_xTickTimeFindBetterPosIfNoMove))
|
|
return 1;
|
|
/* END ANNECY MT } */
|
|
|
|
/*
|
|
* Special process after a failure.
|
|
* If we are in a special mode, we must test the end of the mode.
|
|
*/
|
|
if(!(_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_ConstraintMoveVisFailure))
|
|
return 1;
|
|
|
|
/*
|
|
* If current camera wanted position is outside the circle (center = last failed origin, ray =
|
|
* first shifting), we force last failed wanted to be NULL to tell that we can move now.
|
|
* There's a little epsilon on the ray not to be too short.
|
|
*/
|
|
MTH3D_M_vSubVector
|
|
(
|
|
&stTempVector,
|
|
_p_stWanted,
|
|
&_p_stStruct->hCineinfo->stLastFailedOrigin
|
|
);
|
|
xNorm = MTH3D_M_xNormVector(&stTempVector);
|
|
|
|
MTH3D_M_vSubVector
|
|
(
|
|
&stTempVector1,
|
|
&_p_stStruct->hCineinfo->stLastFailedWanted,
|
|
&_p_stStruct->hCineinfo->stLastFailedOrigin
|
|
);
|
|
xNorm1 = MTH3D_M_xNormVector(&stTempVector1);
|
|
/* if(MTH_M_bGreater(xNorm1, MTH_M_xFloatToReal(5.0f)))*/
|
|
/* xNorm1 = MTH_M_xFloatToReal(5.0f);*/
|
|
|
|
if(MTH_M_bLessEqual(xNorm, MTH_M_xAdd(xNorm1, 0.5)))
|
|
return 0;
|
|
|
|
/*
|
|
* We can reset vector.
|
|
*/
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
*=====================================================================================================
|
|
* To restore the normal state.
|
|
*=====================================================================================================
|
|
*/
|
|
void CAM_fn_vRestoreNormalState(CAM_tdstUpdateCamera *_p_stStruct)
|
|
{
|
|
/* Return to normal state */
|
|
_p_stStruct->hCineinfo->eState = CAM_e_State_GoToOptimal;
|
|
|
|
/* Restore visibility cineinfo structure to current one to restore parameters of ideal position */
|
|
CAM_fn_vSetCineinfoCurrentFromVisibility(_p_stStruct->hCineinfo);
|
|
CAM_fn_vSetCineinfoWorkFromVisibility(_p_stStruct->hCineinfo);
|
|
|
|
/*
|
|
* No shift until ideal pos is reached.
|
|
*/
|
|
_p_stStruct->hCineinfo->ucPerIAFlags |= C_PerIAFlags_NoShift;
|
|
_p_stStruct->hCineinfo->ucPerIAFlags &= ~C_PerIAFlags_ConstraintMoveVisFailure;
|
|
|
|
/*
|
|
* Compute position for this new position.
|
|
*/
|
|
CAM_fn_vComputeMovePosWithDynTheta(_p_stStruct);
|
|
}
|
|
|
|
/*
|
|
*=====================================================================================================
|
|
* Try to find a better position than current one.
|
|
*=====================================================================================================
|
|
*/
|
|
void CAM_fn_vCheckForABetterPos(CAM_tdstUpdateCamera *_p_stStruct)
|
|
{
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
MTH3D_tdstVector stComputeVector;
|
|
char cRes;
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
/*
|
|
* One more trame in this new ideal position. If wCounter1 is too small, don't search a better one.
|
|
* Else we try to find a better position. We try to find a better position if camera doesn't move
|
|
* for a too long time too (wCounter4).
|
|
*--------------------------------------------------------------------------------------------------
|
|
*/
|
|
/* ANNECY MT - 03/08/99 { */
|
|
/* _p_stStruct->hCineinfo->wCounter1++; */
|
|
_p_stStruct->hCineinfo->xCounter1 = MTH_M_xAdd(_p_stStruct->hCineinfo->xCounter1,MTH_M_xFloatToReal(g_stEngineStructure.stEngineTimer.ulUsefulDeltaTime));
|
|
/* if((_p_stStruct->hCineinfo->wCounter1 >= CAM_C_xTickFindBetterPos) && (!(CONSTANT_NOBETTERPOS)) && _p_stStruct->hCineinfo->bCanDoBestPos) */
|
|
if(MTH_M_bGreaterEqual(_p_stStruct->hCineinfo->xCounter1 , CAM_C_xTickTimeFindBetterPos) && (!(CONSTANT_NOBETTERPOS)) && _p_stStruct->hCineinfo->bCanDoBestPos)
|
|
{
|
|
/* _p_stStruct->hCineinfo->wCounter1 = 0; */
|
|
_p_stStruct->hCineinfo->xCounter1 = MTH_C_ZERO;
|
|
/* END ANNECY MT } */
|
|
|
|
/*
|
|
* Test for a better position.
|
|
*/
|
|
cRes = CAM_fn_cFindNewGoodIdealPos(_p_stStruct, &stComputeVector, C_mode_MUSTGO|C_mode_MUSTSEE|C_mode_MORE_CORRECT);
|
|
if(cRes)
|
|
{
|
|
if(cRes == 1)
|
|
{
|
|
CAM_fn_vRestoreNormalState(_p_stStruct);
|
|
}
|
|
else
|
|
{
|
|
CAM_fn_vMakeAsNewIdealPosition(_p_stStruct, &stComputeVector);
|
|
if(_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_ConstraintMoveVisFailure)
|
|
cJustBetterPos = 1;
|
|
else
|
|
cJustBetterPos = 0;
|
|
_p_stStruct->hCineinfo->ucPerIAFlags &= ~C_PerIAFlags_ConstraintMoveVisFailure;
|
|
}
|
|
_p_stStruct->hCineinfo->bCanDoBestPos = FALSE;
|
|
}
|
|
}
|
|
}
|