reman3/Rayman_X/cpa/tempgrp/AI/AIGame/CAM_Base.c

1774 lines
61 KiB
C

/*
**************************************************************************************************
* General functions for camera AI.
**************************************************************************************************
*/
#define D_CineInfo_StructureDefine
#include "AIUseCPA.h"
#include "CAM_Base.h"
#include "CAM_Tool.h"
#include "CAM_Vis.h"
#include "Gam.h"
#include "safe.h"
#include "specif/aitools.h"
/*
* FLAGS THAT DEPEND ON ACTUAL WORK.
* That flags can change the compute of moving vectors.
* Determin if we must take a special axis.
*/
char cRefAxisIsAlreadyComputed;
char cNoDynChangeTheta;
/* Set when we find a better position, and we just became from a failure visibility */
char cJustBetterPos = 0;
extern char cCanTestStatic;
/*
**************************************************************************************************
**************************************************************************************************
COMPUTE REFERENCE POSITION
**************************************************************************************************
**************************************************************************************************
*/
/*
*=================================================================================================
* Compute reference camera axis to compute position.
*=================================================================================================
*/
void CAM_fn_vComputeRefAxis(CAM_tdstUpdateCamera *_p_stStruct, MTH3D_tdstVector *_p_stRefAxis)
{
/*
* Determin if reference axis has already been computed.
*/
if(cRefAxisIsAlreadyComputed)
{
MTH3D_tdstVector stVectorNull;
MTH3D_M_vNullVector(&stVectorNull);
/* Blindage ! */
/* if(MTH3D_M_bIsNullVector(&_p_stStruct->hCineinfo->stForceRefAxisY))*/
if (CAM_fn_bEqualVectorWithEpsilon(&_p_stStruct->hCineinfo->stForceRefAxisY, &stVectorNull,MTH_M_xFloatToReal(0.0001f)))
{
MTH3D_M_vSetVectorElements(&_p_stStruct->hCineinfo->stForceRefAxisY, MTH_C_ZERO, -MTH_C_ONE, MTH_C_ZERO);
MTH3D_M_vCopyVector(_p_stRefAxis, &_p_stStruct->hCineinfo->stForceRefAxisY);
}
else
{
MTH3D_M_vNormalizeVector(_p_stRefAxis, &_p_stStruct->hCineinfo->stForceRefAxisY);
}
/* Blindage ! */
/* if(MTH3D_M_bIsNullVector(&_p_stStruct->hCineinfo->stForceRefAxisZ))*/
if (CAM_fn_bEqualVectorWithEpsilon(&_p_stStruct->hCineinfo->stForceRefAxisZ, &stVectorNull,MTH_M_xFloatToReal(0.0001f)))
{
MTH3D_M_vSetVectorElements(&_p_stStruct->hCineinfo->stForceRefAxisZ, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE);
}
else
{
MTH3D_M_vNormalizeVector(&_p_stStruct->stCptPos.stRefAxisZ, &_p_stStruct->hCineinfo->stForceRefAxisZ);
}
}
/*
* Apex mode if a second superobject is defined.
* Reference axis is the axis between the two persos.
*/
else if(_p_stStruct->hCineinfoWork->hSecondSuperObjectTargeted)
{
MTH3D_M_vSubVector(_p_stRefAxis, &_p_stStruct->stSecondTargetedPersoPos, &_p_stStruct->stTargetedPersoPos);
MTH3D_M_vNormalizeVector(_p_stRefAxis, _p_stRefAxis);
MTH3D_M_vSetVectorElements(&_p_stStruct->stCptPos.stRefAxisZ, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE);
}
/*
* Else reference axis is perso sight axis.
*/
else
{
CAM_fn_vGetPersoSightAxis(_p_stStruct, _p_stRefAxis, &_p_stStruct->stCptPos.stRefAxisZ);
MTH3D_M_vSetVectorElements(&_p_stStruct->stCptPos.stRefAxisZ, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE);
MTH3D_M_vNegVector(_p_stRefAxis, _p_stRefAxis);
}
}
/*
*=================================================================================================
* Compute the targeted perso position.
* This is the position of perso return by meca (average or linear) + the stShiftPos.
*=================================================================================================
*/
void CAM_fn_vComputeTargetedPersoPos
(
CAM_tdstUpdateCamera *_p_stStruct,
HIE_tdxHandleToSuperObject _hPerso,
MTH3D_tdstVector *_p_stTargetedPersoPos,
MTH3D_tdstVector *_p_stTargetedPersoRealPos
)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH3D_tdstVector stTempVector;
unsigned char ucChannel;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
if(_hPerso == NULL)
{
MTH3D_M_vNullVector(_p_stTargetedPersoPos);
MTH3D_M_vNullVector(_p_stTargetedPersoRealPos);
return;
}
/* Get eventual channel number for that perso */
ucChannel = CAM_fn_cCineInfoGetChannel(_p_stStruct->hCineinfoWork);
if(ucChannel != 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);
}
/* Get real targeted perso position */
POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectGlobalMatrix(_hPerso), _p_stTargetedPersoRealPos);
/*
* Compute perso position that will serve to compute following camera position.
* In some case, the position is the real one.
* In other cases, position is the average one computed by meca.
*/
if
(
(_p_stStruct->hCineinfo->ucVolIAFlags & C_VolIAFlags_InitJustCopiedInCurrent) /* It's the first trame */
|| (_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoAverageMoveTgtPerso) /* We want real pos of perso */
|| ((ucChannel == C_ucUnknownChannel) && (!M_GetMSHandle(_hPerso, Dynam))) /* Perso has no meca */
|| (ucChannel != C_ucUnknownChannel) /* We want a channel of perso */
)
{
MTH3D_M_vCopyVector(_p_stTargetedPersoPos, _p_stTargetedPersoRealPos);
}
else
{
CAM_fn_vAveragePosition(_p_stStruct->hCineinfo, CAM_C_xAverageForComputePos, _p_stTargetedPersoPos);
}
/*
* Compute shift pos. We rotate it depending on perso rotation matrix.
*/
MTH3D_M_vCopyVector(&stTempVector, &_p_stStruct->hCineinfoWork->stShiftPos);
POS_fn_vRotateVector(&stTempVector, HIE_fn_hGetSuperObjectGlobalMatrix(_hPerso), &stTempVector);
/*
* Add shift pos to the 2 computed vectors.
*/
MTH3D_M_vAddVector
(
_p_stTargetedPersoPos,
_p_stTargetedPersoPos,
&stTempVector
);
MTH3D_M_vAddVector
(
_p_stTargetedPersoRealPos,
_p_stTargetedPersoRealPos,
&stTempVector
);
}
/*
*=================================================================================================
* Compute the reference position to compute target and camera position.
*=================================================================================================
*/
void CAM_fn_vComputeReferencePoint(CAM_tdstUpdateCamera *_p_stStruct)
{
/*
* If there are 2 persos, force camera to take real position instead of
* average cause of a wonderful optim (average in camera and not in meca).
*/
if(_p_stStruct->hCineinfoWork->hSecondSuperObjectTargeted)
_p_stStruct->hCineinfoWork->uwIAFlags |= C_IAFlags_NoAverageMoveTgtPerso;
/*
* Position of first perso;
*/
CAM_fn_vComputeTargetedPersoPos
(
_p_stStruct,
_p_stStruct->hCineinfoWork->hSuperObjectTargeted,
&_p_stStruct->stTargetedPersoPos,
&_p_stStruct->stTargetedPersoRealPos
);
/*
* Position of second perso. If yes, we took the middle of the axis between the
* two persos.
*/
if(_p_stStruct->hCineinfoWork->hSecondSuperObjectTargeted)
{
CAM_fn_vComputeTargetedPersoPos
(
_p_stStruct,
_p_stStruct->hCineinfoWork->hSecondSuperObjectTargeted,
&_p_stStruct->stSecondTargetedPersoPos,
&_p_stStruct->stSecondTargetedPersoRealPos
);
MTH3D_M_vLinearInterpolVector
(
&_p_stStruct->stTargetedPersoPos,
&_p_stStruct->stTargetedPersoPos,
&_p_stStruct->stSecondTargetedPersoPos,
MTH_M_xFloatToReal(_p_stStruct->hCineinfo->xApexRatio)
);
MTH3D_M_vLinearInterpolVector
(
&_p_stStruct->stTargetedPersoRealPos,
&_p_stStruct->stTargetedPersoRealPos,
&_p_stStruct->stSecondTargetedPersoRealPos,
MTH_M_xFloatToReal(_p_stStruct->hCineinfo->xApexRatio)
);
}
}
/*
**************************************************************************************************
**************************************************************************************************
COMPUTE TARGET
**************************************************************************************************
**************************************************************************************************
*/
/*
*=================================================================================================
* To be sure that targeted perso is visible.
*=================================================================================================
*/
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void CAM_fn_vDynChangeTarget(CAM_tdstUpdateCamera *_p_stStruct, MTH3D_tdstVector *_p_stTempVector)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH_tdxReal xFocal = MTH_M_xMul(_p_stStruct->hCineinfoWork->xFocal, MTH_C_Inv2);
MTH_tdxReal xAngle, xNorm;
MTH3D_tdstVector stTempVector, stTempVector1;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
* If no dynamic target request or first trame, don't process.
*/
if
(
(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoDynamicTarget)
|| (_p_stStruct->hCineinfo->ucVolIAFlags & C_VolIAFlags_InitJustCopiedInCurrent)
)
return;
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stTargetedPersoPos, &_p_stStruct->stCurrentCameraPos);
MTH3D_M_vAddVector(&stTempVector, &stTempVector, _p_stTempVector);
MTH3D_M_vSubVector(&stTempVector1, &_p_stStruct->stTargetedPersoRealPos, &_p_stStruct->stCurrentCameraPos);
xAngle = CAM_fn_xComputeRotation(&stTempVector, &stTempVector1, NULL);
/* Add an epsilon to demi-focal angle */
xFocal = MTH_M_xSub(xFocal, CAM_C_xEpsilonDynTgtFocalAngle);
if(MTH_M_bLess(xAngle , xFocal))
return;
xNorm = MTH_M_xDiv(MTH3D_M_xNormVector(&stTempVector), MTH_M_xCos(xFocal));
xNorm = MTH_M_xMul(MTH_M_xSin(xFocal), xNorm);
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stTargetedPersoRealPos, &_p_stStruct->stTargetedPersoPos);
MTH3D_M_vAddVector(&stTempVector, &stTempVector, _p_stTempVector);
MTH3D_M_vNormalizeVector(&stTempVector, &stTempVector);
/* MTH3D_M_vMulScalarVector(&stTempVector, xNorm, &stTempVector);*/
/* MTH3D_M_vCopyVector(_p_stTempVector, &stTempVector);*/
MTH3D_M_vMulScalarVector(_p_stTempVector, xNorm, &stTempVector);
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
/*
*=================================================================================================
* Compute the target depending on shift and persos.
*=================================================================================================
*/
void CAM_fn_vComputeTarget(CAM_tdstUpdateCamera *_p_stStruct)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH3D_tdstVector stTempLook;
HIE_tdxHandleToSuperObject h_Perso;
unsigned char ucChannel;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
* If target vertex was already computed, we copy it without additional process.
*-------------------------------------------------------------------------------
*/
if(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_TargetIsAlreadyComputed)
{
MTH3D_M_vCopyVector(&_p_stStruct->stCptPos.stTarget, &_p_stStruct->hCineinfo->stForceTarget);
}
/*
* No handle to target, and no forced target : strange...
*--------------------------------------------------------
*/
else if (_p_stStruct->hCineinfoWork->hSuperObjectTargeted == NULL)
{
MTH3D_M_vNullVector(&_p_stStruct->stCptPos.stTarget);
}
/*
* For 2 persos, the shift target must be in the new camera axis (axis between the 2 persos).
* Don't care of stShiftTarget.
*--------------------------------------------------------------------------------------------
*/
else if(_p_stStruct->hCineinfoWork->hSecondSuperObjectTargeted)
{
MTH3D_M_vCopyVector(&_p_stStruct->stCptPos.stTarget, &_p_stStruct->stTargetedPersoPos);
}
/*
* Else we compute target depending on targeted perso position.
*--------------------------------------------------------------
*/
else
{
/*
* Get targeted perso
*/
h_Perso = _p_stStruct->hCineinfoWork->hSuperObjectTargeted;
if ((ucChannel = CAM_fn_cCineInfoGetChannel(_p_stStruct->hCineinfoWork)) != C_ucUnknownChannel)
{
/* FBF blindage acces modules {*/
#ifdef ACTIVE_EDITOR
fn_vCheckModuleAccess(h_Perso,TRUE, &ucChannel);
#endif
/* } fin blindage acces modules */
h_Perso = fn_hGetSuperObjectInChannel(fn_h3dDataGetChannelSOList(M_GetMSHandle(h_Perso, 3dData)), (short) ucChannel);
}
/*
* Compute additional target vertex.
*/
MTH3D_M_vCopyVector(&stTempLook, &_p_stStruct->hCineinfoWork->stShiftTarget);
POS_fn_vRotateVector(&stTempLook, HIE_fn_hGetSuperObjectGlobalMatrix(h_Perso), &stTempLook);
MTH3D_M_vAddVector(&_p_stStruct->stCptPos.stTarget, &_p_stStruct->stTargetedPersoPos, &stTempLook);
/*
* A little change. We change the look vertex to be as max as possible from perso, so for the gameplay,
* this will permit to see as possible what the perso can see.
*/
/* CAM_fn_vDynChangeTarget(_p_stStruct, &stTempLook);*/
/*
* Compute resultant look position and update field.
*/
MTH3D_M_vAddVector(&_p_stStruct->stCptPos.stTarget, &_p_stStruct->stTargetedPersoPos, &stTempLook);
}
}
/*
**************************************************************************************************
**************************************************************************************************
COMPUTE MOVE VECTOR
**************************************************************************************************
**************************************************************************************************
*/
/*
*=================================================================================================
* Description : bound angle
* _p_xAngleToBound -> angle to bound (current real angle)
* _p_xCutAngle -> To receive cut angle.
* _xAngle -> angle ideal
* _xTolerance -> tolerance
*=================================================================================================
*/
void CAM_fn_vBoundAngleWithTolerance
(
CAM_tdstUpdateCamera *_p_stStruct,
MTH_tdxReal *_p_xAngleToBound,
MTH_tdxReal *_p_xCutAngle,
MTH_tdxReal *_p_xDeltaAngle,
MTH_tdxReal _xRequestAngle,
MTH_tdxReal _xTolerance
)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH_tdxReal xAngleMin;
MTH_tdxReal xAngleMax;
MTH_tdxReal xDelta;
MTH_tdxReal xNewAngle;
BOOL bInTolerance;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
* If tolerance is greater equal than Pi, current angle is correct. Don't need to bound.
*/
if (MTH_M_bGreaterEqual(_xTolerance, MTH_C_Pi))
{
*_p_xCutAngle = *_p_xAngleToBound;
return;
}
/*
* If tolerance.
*/
xNewAngle = _xRequestAngle;
if (MTH_M_bGreater(_xTolerance, MTH_C_ZERO))
{
/*
* Compute angle min and angle max.
*/
_xTolerance = MTH_M_xAdd(_xTolerance, MTH_M_xFloatToReal(0.0001f));
xAngleMin = MTH_M_xSub(_xRequestAngle, _xTolerance);
if (MTH_M_bLessZero(xAngleMin))
xAngleMin = MTH_M_xAdd(xAngleMin, MTH_C_2Pi);
xAngleMax = MTH_M_xAdd(_xRequestAngle, _xTolerance);
if (MTH_M_bGreater(xAngleMax, MTH_C_2Pi))
xAngleMax = MTH_M_xSub(xAngleMax, MTH_C_2Pi);
/*
* Determin if current angle is between angle min and max.
*/
if (MTH_M_bGreater(xAngleMax, xAngleMin))
bInTolerance = MTH_M_bInRangeEqual(*_p_xAngleToBound, xAngleMin, xAngleMax);
else
bInTolerance = !MTH_M_bInRange(*_p_xAngleToBound, xAngleMax, xAngleMin);
/*
* If current angle is not between that 2 values, we must bound it.
*/
if (!bInTolerance)
{
xDelta = MTH_M_xSub(*_p_xAngleToBound, _xRequestAngle);
xDelta = CAM_fn_xSetAngleInIntervalPiPi(xDelta);
/*
* We set wanted angle to angle min or max depending on the sens.
*/
if (MTH_M_bGreater(xDelta, MTH_C_ZERO))
xNewAngle = xAngleMax;
else
xNewAngle = xAngleMin;
}
else
xNewAngle = *_p_xAngleToBound;
}
/*
* Cut big angle in smaller one if necessary.
*/
xDelta = MTH_M_xSub(xNewAngle, *_p_xAngleToBound);
xDelta = CAM_fn_xSetAngleInIntervalPiPi(xDelta);
*_p_xDeltaAngle = xDelta;
if(MTH_M_bGreaterEqual(MTH_M_xAbs(xDelta), CAM_C_xBaseCutAngle))
{
if (MTH_M_bGreaterZero(xDelta))
*_p_xCutAngle = MTH_M_xAdd(*_p_xAngleToBound, CAM_C_xBaseCutAngle);
else
*_p_xCutAngle = MTH_M_xSub(*_p_xAngleToBound, CAM_C_xBaseCutAngle);
*_p_xCutAngle = CAM_fn_xSetAngleInInterval02Pi(*_p_xCutAngle);
}
else
*_p_xCutAngle = xNewAngle;
/*
* Set new bounded angle.
*/
*_p_xAngleToBound = xNewAngle;
}
/*
*=================================================================================================
Description : compute ideal angles that depend of parameters and old camera position
_p_stStruct -> camera data
_p_stCameraAxis -> new camera axis (without rotation)
_p_stCamTargetAxis -> old camera position to new target axis
_p_xHorAngle -> horizontal angle
_p_xVerAngle -> vertical angle
*=================================================================================================
*/
void CAM_fn_vComputeCameraAxisAngles
(
CAM_tdstUpdateCamera *_p_stStruct,
MTH3D_tdstVector *_p_stCameraAxis,
MTH3D_tdstVector *_p_stCamTargetAxis,
MTH_tdxReal *_p_xHorAngle,
MTH_tdxReal *_p_xVerAngle
)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH_tdxReal xTemp, xShiftAlpha, xShiftTheta;
MTH_tdxReal xAngleTheta;
MS_tdxHandleToInternalCineinfo hCineInfoWork;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
hCineInfoWork = _p_stStruct->hCineinfoWork;
/*
* compute angle between old direction and new dir
*/
CAM_fn_vComputeAnglesBetweenTwoVectors
(
hCineInfoWork,
_p_stCameraAxis,
_p_stCamTargetAxis,
_p_xHorAngle,
_p_xVerAngle,
&_p_stStruct->stCptPos.stRefAxisZ
);
/*
* If no shift flag is set, no tolerance for angles.
*/
if
(
(_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_NoShift)
|| (_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoShiftUntilPosReached)
)
{
xShiftAlpha = MTH_C_ZERO;
xShiftTheta = MTH_C_ZERO;
}
else
{
xShiftAlpha = _p_stStruct->hCineinfoWork->xAngleShiftAlpha;
xShiftTheta = _p_stStruct->hCineinfoWork->xAngleShiftTheta;
}
/*
* Tolerance on horizontal angle
*/
_p_stStruct->cHasCutAlpha = 0;
CAM_fn_vBoundAngleWithTolerance
(
_p_stStruct,
_p_xHorAngle,
&_p_stStruct->xAngleAlphaCut,
&_p_stStruct->xAngleDeltaAlphaCut,
_p_stStruct->hCineinfoWork->xAngleAlpha,
xShiftAlpha
);
if(!(MTH_M_bEqual(*_p_xHorAngle, _p_stStruct->xAngleAlphaCut)))
_p_stStruct->cHasCutAlpha = 1;
/*
* Tolerance on vertical angle
*/
if(_p_stStruct->hCineinfo->eState == CAM_e_State_GoToComputedOptimal)
xAngleTheta = _p_stStruct->hCineinfoCurrent->xAngleTheta;
else
xAngleTheta = _p_stStruct->hCineinfoWork->xAngleTheta;
CAM_fn_vBoundAngleWithTolerance
(
_p_stStruct,
_p_xVerAngle,
&xTemp,
&xTemp,
xAngleTheta,
xShiftTheta
);
}
/*
*=================================================================================================
* Rotate camera axis with two angles (one in horizontal plane, the other in vertical plane)
* _p_stCameraAxis -> axis (result axis is set in this parameter)
* _xHorAngle -> rotation in horizontal plane (xOy)
* _xVerAngle -> rotation in vertical plane (zOy)
*=================================================================================================
*/
void CAM_fn_vRotateCameraAxis
(
MTH3D_tdstVector *_p_stCameraAxis,
MTH_tdxReal _xHorAngle,
MTH_tdxReal _xVerAngle,
MTH3D_tdstVector *_p_stRefAxisZ
)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH_tdstRotation stRotation;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
* Rotate axis around Z axis.
*/
stRotation.m_xAngle = _xHorAngle;
MTH3D_M_vCopyVector(&stRotation.m_stAxis, _p_stRefAxisZ);
MTH_p_stRotationMulVector(&stRotation, _p_stCameraAxis, _p_stCameraAxis);
/*
* Compute x Axis, and rotate axis around x axis.
*/
MTH3D_M_vCrossProductVectorWithoutBuffer(&stRotation.m_stAxis, _p_stCameraAxis, _p_stRefAxisZ);
MTH3D_M_vNormalizeVector(&stRotation.m_stAxis, &stRotation.m_stAxis);
stRotation.m_xAngle = _xVerAngle;
MTH_p_stRotationMulVector(&stRotation, _p_stCameraAxis, _p_stCameraAxis);
}
/*
*=================================================================================================
* Compute real camera wanted position.
*=================================================================================================
*/
void CAM_fn_vComputeRealWantedPos(CAM_tdstUpdateCamera *_p_stStruct)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
CAM_tdstUpdateCamera stTempStruct;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
* A temporary structure.
*/
memcpy(&stTempStruct, _p_stStruct, sizeof(CAM_tdstUpdateCamera));
/*
* Real wanted position for normal state is the same that current wanted position.
* We must assure that there's no shifting vertex to retreive the ideal position, so we
* get current working structure (we copy it in visibility one that is not used).
*/
if(_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_VisibilityCopied)
{
memcpy(&gst_Ideal, _p_stStruct->hCineinfoVisibility, sizeof(struct tdstInternalStructurCineinfo_));
/* gst_Ideal.xAngleTheta = _p_stStruct->hCineinfoWork->xAngleTheta;*/
gst_Ideal.xDistMin = _p_stStruct->hCineinfoWork->xDistMin;
gst_Ideal.xDistMax = _p_stStruct->hCineinfoWork->xDistMax;
}
else
memcpy(&gst_Ideal, _p_stStruct->hCineinfoWork, sizeof(struct tdstInternalStructurCineinfo_));
/*
* Compute position. Force to have no shift to compute the real wanted position only
* depending on alpha and theta (and not shift values).
*/
gst_Ideal.uwIAFlags |= C_IAFlags_NoShiftUntilPosReached;
stTempStruct.hCineinfoWork = &gst_Ideal;
CAM_fn_vComputeMovePosWithDynTheta(&stTempStruct);
MTH3D_M_vCopyVector(&_p_stStruct->stRealWantedCameraPos, &stTempStruct.stWantedCameraPos);
}
/*
*=================================================================================================
* Change theta depending of current targeted perso move.
* Return 0 if theta is not changed, and 1 else.
*=================================================================================================
*/
char CAM_fn_cDynChangeTheta(CAM_tdstUpdateCamera *_p_stStruct, MTH3D_tdstVector *_p_stTestedPos)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH3D_tdstVector stMove, stRef, stSightAxis;
MTH3D_tdstVector stNormal;
MTH_tdxReal xAngle, xThetaAngle;
MTH_tdxReal xCos;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
* Get the normal of the face the targeted perso is walking on.
*/
if(!CAM_fn_bPersoOnFace(_p_stStruct->hCineinfoWork->hSuperObjectTargeted, &stNormal))
return 0;
/*
* Compute projection of perso sight axis on face.
*/
CAM_fn_vComputeRefAxis(_p_stStruct, &stSightAxis);
CAM_fn_vComputeProjection(&stMove, &stSightAxis, &stNormal);
MTH3D_M_vNormalizeVector(&stMove, &stMove);
/*
* Compute requested theta angle.
*/
MTH3D_M_vSetVectorElements(&stRef, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE);
xAngle = CAM_fn_xComputeRotation(&stRef, &stMove, NULL);
xAngle = MTH_M_xSub(xAngle, MTH_C_PiBy2);
MTH3D_M_vSubVector(&stRef, &_p_stStruct->stTargetedPersoPos, _p_stTestedPos);
MTH3D_M_vNormalizeVector(&stRef, &stRef);
xCos = MTH3D_M_xDotProductVector(&stRef, &stMove);
xAngle = MTH_M_xMul(xAngle, xCos);
/*
* Compute normal theta angle for tested position.
*/
if(_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_VisibilityCopied)
xThetaAngle = _p_stStruct->hCineinfoVisibility->xAngleTheta;
else
/* ANNECY MT - 09/07/99 { */
/*xThetaAngle = _p_stStruct->hCineinfoCurrent->xAngleTheta;*/
xThetaAngle = _p_stStruct->hCineinfoWork->xAngleTheta;
/* END ANNECY MT } */
/*
* Compute additional theta angle.
* Epsilon is current theta angle.
*
* - If actual and requested theta are opposite, we will add xAngle to current theta.
* - Else we compute the difference between the two angles.
* - Cause of current theta, new angle can be the same as wanted one.
*/
if(MTH_M_bLess(MTH_M_xMul(xThetaAngle, xAngle), MTH_C_ZERO))
{
xAngle = xAngle;
}
else if
(
MTH_M_bLessEqual
(
MTH_M_xAbs(xThetaAngle),
MTH_M_xAbs(xAngle)
)
)
{
xAngle = MTH_M_xSub(xAngle, xThetaAngle);
}
else
{
xAngle = MTH_C_ZERO;
return 0;
}
/*
* Add angle to current theta.
*/
_p_stStruct->hCineinfoWork->xAngleTheta = MTH_M_xAdd(xThetaAngle, xAngle);
return 1;
}
/*
*=================================================================================================
* Description : Take care of camera's altitude
*=================================================================================================
*/
void CAM_fn_vTakeCareOfCameraAltitude(MS_tdxHandleToCineinfo _hCineinfo, MTH3D_tdstVector *_p_stNewCameraPosition)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH_tdxReal xZCamera;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
xZCamera = _p_stNewCameraPosition->xZ;
if (MTH_M_bGreater(xZCamera, _hCineinfo->hWork->xZMax))
_p_stNewCameraPosition->xZ = _hCineinfo->hWork->xZMax;
if (MTH_M_bLess(xZCamera, _hCineinfo->hWork->xZMin))
_p_stNewCameraPosition->xZ = _hCineinfo->hWork->xZMin;
}
/*
*=================================================================================================
* Compute move vector of camera.
*=================================================================================================
*/
void CAM_fn_vComputeMovePos(CAM_tdstUpdateCamera *_p_stStruct)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH3D_tdstVector stDir;
MTH3D_tdstVector stCamTargetVector;
MTH_tdxReal xNorm;
MTH_tdxReal xDistMin;
MTH_tdxReal xDistMax;
MTH_tdxReal xAlphaAngle, xThetaAngle;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
* Test if we have force camera position.
*/
if(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_PositionIsAlreadyComputed)
{
if(cRefAxisIsAlreadyComputed)
{
MTH3D_M_vNormalizeVector(&_p_stStruct->stCptPos.stRefAxisZ, &_p_stStruct->hCineinfo->stForceRefAxisZ);
}
else
{
MTH3D_M_vSetVectorElements(&_p_stStruct->stCptPos.stRefAxisZ, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE);
}
/* no Dynamic Theta change when we have force camera position */
cNoDynChangeTheta = 1;
/* Wanted position and move */
MTH3D_M_vCopyVector(&_p_stStruct->stWantedCameraPos, &_p_stStruct->hCineinfo->stForcePosition);
MTH3D_M_vSubVector(&_p_stStruct->stCptPos.stMovePos, &_p_stStruct->stWantedCameraPos, &_p_stStruct->stCurrentCameraPos);
}
/*
* Test if the camera has a target.
*/
else if(!_p_stStruct->hCineinfoWork->hSuperObjectTargeted)
{
if(cRefAxisIsAlreadyComputed)
{
MTH3D_M_vNormalizeVector(&_p_stStruct->stCptPos.stRefAxisZ, &_p_stStruct->hCineinfo->stForceRefAxisZ);
}
else
{
MTH3D_M_vSetVectorElements(&_p_stStruct->stCptPos.stRefAxisZ, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE);
}
/* Wanted position and move */
CAM_fn_vComputeRefAxis(_p_stStruct, &stDir);
MTH3D_M_vCopyVector(&_p_stStruct->stWantedCameraPos, &_p_stStruct->stCurrentCameraPos);
MTH3D_M_vNullVector(&_p_stStruct->stCptPos.stMovePos);
}
/*
* Else normal computing.
*/
else
{
/* Compute vector between old camera and new target */
MTH3D_M_vSubVector(&stCamTargetVector, &_p_stStruct->stCurrentCameraPos, &_p_stStruct->stTargetedPersoPos);
if
(
(stCamTargetVector.xX == _p_stStruct->stCptPos.stRefAxisZ.xX)
&& (stCamTargetVector.xY == _p_stStruct->stCptPos.stRefAxisZ.xY)
)
stCamTargetVector.xX += 0.5;
/* Compute new axis (super object direction or vector direction in cineinfo */
CAM_fn_vComputeRefAxis(_p_stStruct, &stDir);
/* Look if old axis is in ideal angle */
CAM_fn_vComputeCameraAxisAngles(_p_stStruct, &stDir, &stCamTargetVector, &xAlphaAngle, &xThetaAngle);
/* Rotate camera system with alpha and Theta angles */
CAM_fn_vRotateCameraAxis(&stDir, xAlphaAngle, xThetaAngle, &_p_stStruct->stCptPos.stRefAxisZ);
/* Compute actual distance (between old camera and new target) */
/*xNorm = MTH3D_M_xNormVector(&stCamTargetVector);*/
xNorm = MTH3D_M_xSqrVector(&stCamTargetVector);
/* Compute ideal distance */
xDistMin = _p_stStruct->hCineinfoWork->xDistMin;
xDistMax = _p_stStruct->hCineinfoWork->xDistMax;
/* Test norm */
if (MTH_M_bLess( xNorm, MTH_M_xSqr(xDistMin)))
xNorm = xDistMin;
else if (MTH_M_bGreater(xNorm, MTH_M_xSqr(xDistMax)))
xNorm = xDistMax;
else
xNorm = MTH_M_xSqrt(xNorm);
if (MTH_M_bLessEqual(xNorm, MTH_M_xFloatToReal(0.01f)))
xNorm = MTH_M_xFloatToReal(0.01f);
/*
* Compute new wanted camera position
*/
MTH3D_M_vMulScalarVector(&stDir, xNorm, &stDir);
MTH3D_M_vAddVector(&_p_stStruct->stWantedCameraPos, &_p_stStruct->stTargetedPersoPos, &stDir);
CAM_fn_vTakeCareOfCameraAltitude(_p_stStruct->hCineinfo, &_p_stStruct->stWantedCameraPos);
MTH3D_M_vSubVector(&_p_stStruct->stCptPos.stMovePos, &_p_stStruct->stWantedCameraPos, &_p_stStruct->stCurrentCameraPos);
}
}
/*
*=================================================================================================
* Compute move vector of camera with dynamic theta.
*=================================================================================================
*/
void CAM_fn_vComputeMovePosWithDynTheta(CAM_tdstUpdateCamera *_p_stStruct)
{
CAM_fn_vComputeMovePos(_p_stStruct);
if
(
(!((_p_stStruct)->hCineinfo->ucVolIAFlags & C_VolIAFlags_InitJustCopiedInCurrent))
&& ((_p_stStruct)->hCineinfoWork->hSuperObjectTargeted)
&& (!cNoDynChangeTheta)
)
{
if(CAM_fn_cDynChangeTheta(_p_stStruct, &_p_stStruct->stWantedCameraPos))
CAM_fn_vComputeMovePos(_p_stStruct);
}
}
/*
**************************************************************************************************
**************************************************************************************************
SPEED
**************************************************************************************************
**************************************************************************************************
*/
/*
*=================================================================================================
* Compute the speed and accel of the camera.
*=================================================================================================
*/
void CAM_fn_vComputeSpeed(CAM_tdstUpdateCamera *_p_stStruct)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH3D_tdstVector stTempVector, stTempVector1, stMoveTgt;
MTH_tdxReal xNorm, xAngle, xDot, xNorm2;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
* If no shift is set, this is a vis failure. We use dynamic speed with inertia
* of current cineinfo.
*/
/*
if
(
(_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_NoShift)
&& (_p_stStruct->hCineinfo->eState == CAM_e_State_GoToComputedOptimal)
)
{
_p_stStruct->hCineinfoWork->uwIAFlags |= C_IAFlags_NoDynSpeed;
_p_stStruct->hCineinfoWork->xLinearIncreaseSpeed = _p_stStruct->hCineinfoCurrent->xLinearIncreaseSpeed;
_p_stStruct->hCineinfoWork->xLinearDecreaseSpeed = _p_stStruct->hCineinfoCurrent->xLinearDecreaseSpeed;
_p_stStruct->hCineinfoWork->xAngularIncreaseSpeed = _p_stStruct->hCineinfoCurrent->xAngularIncreaseSpeed;
_p_stStruct->hCineinfoWork->xAngularDecreaseSpeed = _p_stStruct->hCineinfoCurrent->xAngularDecreaseSpeed;
_p_stStruct->hCineinfoWork->xTargetIncreaseSpeed = _p_stStruct->hCineinfoCurrent->xTargetIncreaseSpeed;
_p_stStruct->hCineinfoWork->xTargetDecreaseSpeed = _p_stStruct->hCineinfoCurrent->xTargetDecreaseSpeed;
}
*/
/*
* Speeds are the one of IA.
*/
if(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoDynSpeed)
{
_p_stStruct->stCptPos.xLinearSpeed = _p_stStruct->hCineinfoWork->xLinearSpeed;
_p_stStruct->stCptPos.xAngularSpeed = _p_stStruct->hCineinfoWork->xAngularSpeed;
_p_stStruct->stCptPos.xTargetSpeed = _p_stStruct->hCineinfoWork->xTargetSpeed;
return;
}
/*
* Linear speed.
* Angular speed.
*/
if
(
(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_PositionIsAlreadyComputed)
|| (_p_stStruct->hCineinfoWork->hSuperObjectTargeted == NULL)
)
{
_p_stStruct->stCptPos.xLinearSpeed = _p_stStruct->hCineinfoWork->xLinearSpeed;
_p_stStruct->stCptPos.xAngularSpeed = _p_stStruct->hCineinfoWork->xAngularSpeed;
}
else
{
/* LINEAR */
xNorm = MTH_C_ZERO;
if(!(_p_stStruct->hCineinfoWork->uwDNMFlags & DNM_CAM_C_NoLinearParsing))
{
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stWantedCameraPos, &_p_stStruct->stCurrentCameraPos);
xNorm = MTH3D_M_xNormVector(&stTempVector);
xNorm = MTH_M_xMul(xNorm, CAM_C_xDynSpeed_LinearFactNorm);
if(MTH_M_bGreater(xNorm, CAM_C_xDynSpeed_LinearMax))
xNorm = CAM_C_xDynSpeed_LinearMax;
CAM_fn_bPersoIsMoving(_p_stStruct, &stTempVector);
xNorm2 = MTH3D_M_xNormVector(&stTempVector);
if(MTH_M_bLess(xNorm, MTH_M_xMul(xNorm2, CAM_C_xDynSpeed_LinearMulPerso)))
xNorm = MTH_M_xMul(xNorm2, CAM_C_xDynSpeed_LinearMulPerso);
}
_p_stStruct->stCptPos.xLinearSpeed = xNorm;
/* ANGULAR */
if(!(_p_stStruct->hCineinfoWork->uwDNMFlags & DNM_CAM_C_NoAngularParsing))
{
xNorm = MTH_C_ZERO;
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stTargetedPersoPos, &_p_stStruct->stCurrentCameraPos);
if(!MTH3D_M_bIsNullVector(&stTempVector))
{
if (!MTH3D_M_bIsNullVector(&stTempVector))
MTH3D_M_vNormalizeVector(&stTempVector, &stTempVector);
MTH3D_M_vSubVector(&stTempVector1, &_p_stStruct->stTargetedPersoPos, &_p_stStruct->stWantedCameraPos);
if (!MTH3D_M_bIsNullVector(&stTempVector1))
MTH3D_M_vNormalizeVector(&stTempVector1, &stTempVector1);
xNorm = CAM_fn_xComputeRotation(&stTempVector, &stTempVector1, NULL);
}
xNorm = MTH_M_xMul(xNorm, CAM_C_xDynSpeed_AngularFactNorm);
if(MTH_M_bGreater(xNorm, CAM_C_xDynSpeed_AngularMax))
xNorm = CAM_C_xDynSpeed_AngularMax;
CAM_fn_bPersoIsTurning(_p_stStruct->hCineinfoWork->hSuperObjectTargeted, &xAngle);
if(MTH_M_bLess(xNorm, MTH_M_xMul(xAngle, CAM_C_xDynSpeed_AngularMulPerso)))
xNorm = xAngle;
/* Decrease speed depending on distance to target (regardless of ideal distance) */
xAngle = _p_stStruct->hCineinfoWork->xDistMin;
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stTargetedPersoPos, &_p_stStruct->stCurrentCameraPos);
xAngle = MTH_M_xSub(xAngle, MTH3D_M_xNormVector(&stTempVector));
if(MTH_M_bGreater(xAngle, MTH_C_ONE))
xNorm = MTH_M_xDiv(xNorm, xAngle);
else if(MTH_M_bLess(xAngle, MTH_M_xNeg(MTH_C_ONE)))
xNorm = MTH_M_xMul(xNorm, MTH_M_xAbs(xAngle));
}
_p_stStruct->stCptPos.xAngularSpeed = xNorm;
}
/*
* Target speed.
*/
if
(
(_p_stStruct->hCineinfo->ucPerIAFlags & C_IAFlags_TargetIsAlreadyComputed)
|| (_p_stStruct->hCineinfoWork->hSuperObjectTargeted == NULL)
)
{
_p_stStruct->stCptPos.xTargetSpeed = _p_stStruct->hCineinfoWork->xTargetSpeed;
}
else
{
xNorm = MTH_C_ZERO;
MTH3D_M_vNullVector(&stMoveTgt);
if(!(_p_stStruct->hCineinfoWork->uwDNMFlags & DNM_CAM_C_NoTargetParsing))
{
MTH3D_M_vCopyVector(&stTempVector, DNM_M_p_stCPDGetTarget(fn_p_stDynamGetParsingDatas(M_GetMSHandle(_p_stStruct->hSuperObjCamera, Dynam))));
MTH3D_M_vSubVector
(
&stTempVector,
&_p_stStruct->stCptPos.stTarget,
&stTempVector
);
xNorm = MTH3D_M_xNormVector(&stTempVector);
MTH3D_M_vCopyVector(&stMoveTgt, &stTempVector);
}
xNorm = MTH_M_xMul(xNorm, CAM_C_xDynSpeed_TargetFactNorm);
if(MTH_M_bGreater(xNorm, CAM_C_xDynSpeed_TargetMax))
xNorm = CAM_C_xDynSpeed_TargetMax;
/* Norm must be greater than current perso speed */
CAM_fn_bPersoIsMoving(_p_stStruct, &stTempVector);
if(MTH_M_bLess(xNorm, MTH_M_xMul(MTH3D_M_xNormVector(&stTempVector), CAM_C_xDynSpeed_TargetMulPerso)))
xNorm = MTH_M_xMul(MTH3D_M_xNormVector(&stTempVector), CAM_C_xDynSpeed_TargetMulPerso);
_p_stStruct->stCptPos.xTargetSpeed = xNorm;
/*
* Modifs inertie.
*/
if((!MTH3D_M_bIsNullVector(&stMoveTgt)) && (!MTH3D_M_bIsNullVector(DNM_M_p_stReportGetLastTgtMove(_p_stStruct->p_stReport))))
{
xDot = MTH3D_M_xDotProductVector(&stMoveTgt, DNM_M_p_stReportGetLastTgtMove(_p_stStruct->p_stReport));
if(MTH_M_bLess(xDot, -0.9f))
{
_p_stStruct->hCineinfoWork->xTargetDecreaseSpeed = 40;
_p_stStruct->hCineinfoWork->xTargetIncreaseSpeed = 40;
}
}
}
}
/*
**************************************************************************************************
**************************************************************************************************
MOVE CONSTRAINT
**************************************************************************************************
**************************************************************************************************
*/
/*
*=================================================================================================
* Determin if it's not better to not move.
* This function is called to avoid camera to move on the same side where the visiblity failed a
* short time after the failure.
*=================================================================================================
*/
void CAM_fn_vConstraintMoveAfterVisFailure(CAM_tdstUpdateCamera *_p_stStruct)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH3D_tdstVector stTempVector, stTempVector1;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
* If perso is moving (relative to its father), projection of current moving camera pos to axe
* (lastfailed wanted - lastfailed origin).
*/
if((_p_stStruct->cTgtPersoIsMovingRelative) && (!(CONSTANT_NOVISPROJ)))
{
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stWantedCameraPos, &_p_stStruct->hCineinfo->stLastFailedWanted);
MTH3D_M_vSubVector(&stTempVector1, &_p_stStruct->stTargetedPersoPos, &_p_stStruct->hCineinfo->stLastFailedWanted);
if((!MTH3D_M_bIsNullVector(&stTempVector)) && (!MTH3D_M_bIsNullVector(&stTempVector1)))
{
MTH3D_M_vNormalizeVector(&stTempVector1, &stTempVector1);
MTH3D_M_vMulScalarVector(&stTempVector, MTH3D_M_xDotProductVector(&stTempVector, &stTempVector1), &stTempVector1);
MTH3D_M_vAddVector(&stTempVector, &stTempVector, &_p_stStruct->hCineinfo->stLastFailedWanted);
}
else
{
MTH3D_M_vCopyVector(&stTempVector, &_p_stStruct->hCineinfo->stLastFailedWanted);
}
}
/*
* Previous wanted position became the new ideal one (so camera will go to the position computed just
* after the failure).
*/
else
{
MTH3D_M_vCopyVector(&stTempVector, &_p_stStruct->hCineinfo->stLastFailedWanted);
}
/*
* stTempVector is the position we want to go now. We compute movepos and we set Cineinfo current
* to be at this new position.
*/
MTH3D_M_vSubVector(&_p_stStruct->stCptPos.stMovePos, &stTempVector, &_p_stStruct->stCurrentCameraPos);
MTH3D_M_vCopyVector(&_p_stStruct->stWantedCameraPos, &stTempVector);
CAM_fn_vComputeCineinfoCurrentForAPosition(_p_stStruct, &stTempVector);
MTH3D_M_vCopyVector(&_p_stStruct->hCineinfo->stLastFailedWanted, &_p_stStruct->stWantedCameraPos);
}
/*
*=================================================================================================
* Test a position with an angle.
*=================================================================================================
*/
char CAM_fn_cConstraintMoveCutTestAngle(CAM_tdstUpdateCamera *_p_stStruct, MTH_tdxReal _xAngle)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
struct tdstInternalStructurCineinfo_ stTemp;
CAM_tdstUpdateCamera stStruct;
char cMode;
MTH3D_tdstVector stTempVector, stTempVector1;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
* A temporary structure just for our compute.
*/
memcpy(&stTemp, _p_stStruct->hCineinfoWork, sizeof(struct tdstInternalStructurCineinfo_));
stTemp.xAngleAlpha = _xAngle;
CAM_fn_vInitCameraStructure(_p_stStruct->hSuperObjCamera, &stStruct);
stStruct.hCineinfoWork = &stTemp;
/*
* Compute move and wanted position to take care of cut angles.
*/
CAM_fn_vComputeReferencePoint(&stStruct);
CAM_fn_vComputeMovePosWithDynTheta(&stStruct);
/*
* If cJustBetterPos is set, we must not go to the sens of the last visibility failure.
*/
if(cJustBetterPos)
{
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->hCineinfo->stLastFailedOrigin, &_p_stStruct->stCurrentCameraPos);
MTH3D_M_vSubVector(&stTempVector1, &_p_stStruct->hCineinfo->stLastFailedOrigin, &stStruct.stWantedCameraPos);
if(MTH_M_bGreater(MTH3D_M_xNormVector(&stTempVector), MTH3D_M_xNormVector(&stTempVector1)))
return 0;
}
/*
* Test if position is correct. If not, requested move is not change.
*/
cMode = 0;
if
(
(_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_NoShift)
&& (_p_stStruct->hCineinfo->eState == CAM_e_State_GoToComputedOptimal)
)
{
cMode = C_mode_MUSTGO|C_mode_MUSTSEE;
if(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoVisibility)
cMode &= ~C_mode_MUSTSEE;
}
if
(
CAM_fn_cIsWantedPosIncorrect
(
&stStruct,
&stStruct.stWantedCameraPos,
cMode
)
)
return 0;
/*
* Else we change the position to take care of the cutted angle.
*/
MTH3D_M_vCopyVector(&_p_stStruct->stWantedCameraPos, &stStruct.stWantedCameraPos);
MTH3D_M_vCopyVector(&_p_stStruct->stCptPos.stMovePos, &stStruct.stCptPos.stMovePos);
return 1;
}
/*
*=================================================================================================
* Function do inverse cut angle (other sens).
*=================================================================================================
*/
MTH_tdxReal CAM_fn_xOppositeAngle(CAM_tdstUpdateCamera *_p_stStruct)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH_tdxReal xNewAngle;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
xNewAngle = MTH_M_xMul(CAM_C_xBaseCutAngle, MTH_M_xFloatToReal(2.0f));
if(MTH_M_bGreater(_p_stStruct->xAngleDeltaAlphaCut, MTH_C_ZERO))
xNewAngle = MTH_M_xNeg(xNewAngle);
xNewAngle = MTH_M_xAdd(_p_stStruct->xAngleAlphaCut, xNewAngle);
xNewAngle = CAM_fn_xSetAngleInInterval02Pi(xNewAngle);
return xNewAngle;
}
/*
*=================================================================================================
* Camera will go to near from targeted perso. Try to go elsewhere.
*=================================================================================================
*/
void CAM_fn_vConstraintMoveCutAngles(CAM_tdstUpdateCamera *_p_stStruct)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH_tdxReal xNewAngle;
char cWantedSens;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
* If -2, the last sens is not a sens, and in fact we don't want to cut.
*/
if(_p_stStruct->hCineinfo->cLastCutAngleSens == -2)
return;
if(DNM_M_bReportCollision(_p_stStruct->p_stReport) && (!(CONSTANT_CUT_COL)))
{
_p_stStruct->hCineinfo->cLastCutAngleSens = -2;
return;
}
if
(
(MTH_M_bLess(MTH_M_xMul(_p_stStruct->hCineinfo->xLastDeltaCut, _p_stStruct->xAngleDeltaAlphaCut), MTH_C_ZERO))
&& (MTH_M_bLess(MTH_M_xAbs(_p_stStruct->xAngleDeltaAlphaCut), MTH_M_xSub(MTH_C_Pi, CAM_C_xBaseCutAngle)))
)
{
_p_stStruct->hCineinfo->cLastCutAngleSens = 0;
}
/*
* Save current delta.
*/
if(_p_stStruct->hCineinfo->cLastCutAngleSens == 0)
_p_stStruct->hCineinfo->xLastDeltaCut = _p_stStruct->xAngleDeltaAlphaCut;
/*
* There's a problem to know in which sens the cut angle will work.
* We force cut angle to go in sens defined by _p_stStruct->hCineinfo->cLastCutAngleSens.
* If it is equal to 0, we can test in the normal sens, and in opposite one if we want
* to go to a position at the opposite of current one.
*/
xNewAngle = _p_stStruct->xAngleAlphaCut;
if((_p_stStruct->hCineinfo->cLastCutAngleSens == -1) && (MTH_M_bGreater(_p_stStruct->xAngleDeltaAlphaCut, MTH_C_ZERO)))
xNewAngle = CAM_fn_xOppositeAngle(_p_stStruct);
if((_p_stStruct->hCineinfo->cLastCutAngleSens == 1) && (MTH_M_bLess(_p_stStruct->xAngleDeltaAlphaCut, MTH_C_ZERO)))
xNewAngle = CAM_fn_xOppositeAngle(_p_stStruct);
if(CAM_fn_cConstraintMoveCutTestAngle(_p_stStruct, xNewAngle))
{
cWantedSens = _p_stStruct->hCineinfo->cLastCutAngleSens;
if(cWantedSens == 0)
{
/* Force next cut angle to work in the same sens than this one */
if(MTH_M_bGreater(_p_stStruct->xAngleDeltaAlphaCut, MTH_C_ZERO))
_p_stStruct->hCineinfo->cLastCutAngleSens = 1;
else
_p_stStruct->hCineinfo->cLastCutAngleSens = -1;
}
return;
}
if(_p_stStruct->hCineinfo->cLastCutAngleSens == 0)
{
if(MTH_M_bGreaterEqual(MTH_M_xAbs(_p_stStruct->xAngleDeltaAlphaCut), MTH_M_xSub(MTH_C_Pi, CAM_C_xBaseCutAngle)))
{
xNewAngle = CAM_fn_xOppositeAngle(_p_stStruct);
if(CAM_fn_cConstraintMoveCutTestAngle(_p_stStruct, xNewAngle))
{
/* Force next cut angle to work in the same sens than this one */
if(MTH_M_bGreater(_p_stStruct->xAngleDeltaAlphaCut, MTH_C_ZERO))
_p_stStruct->hCineinfo->cLastCutAngleSens = -1;
else
_p_stStruct->hCineinfo->cLastCutAngleSens = 1;
return;
}
}
}
/* To say that we don't want to cut angle anymore */
_p_stStruct->hCineinfo->cLastCutAngleSens = -2;
}
/*
*=================================================================================================
* Is it better not to move ?
*=================================================================================================
*/
void CAM_fn_vConstraintNoMove(CAM_tdstUpdateCamera *_p_stStruct, MTH3D_tdstVector *_p_stWanted)
{
#if 0
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH3D_tdstVector stTempVector;
MTH_tdxReal xCurPound, xWantPound;
char cMode;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH3D_M_vSubVector(&stTempVector, &_p_stStruct->stCurrentCameraPos, &_p_stStruct->stTargetedPersoPos);
xCurPound = CAM_fnx_ComputePosPound(_p_stStruct, &stTempVector);
MTH3D_M_vSubVector(&stTempVector, _p_stWanted, &_p_stStruct->stTargetedPersoPos);
xWantPound = CAM_fnx_ComputePosPound(_p_stStruct, &stTempVector);
if(MTH_M_bLess(xCurPound, xWantPound))
{
cMode = C_mode_MUSTSEE;
if(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoVisibility)
cMode &= ~C_mode_MUSTSEE;
if(!CAM_fn_cIsWantedPosIncorrect(_p_stStruct, &_p_stStruct->stCurrentCameraPos, cMode))
{
MTH3D_M_vCopyVector(&_p_stStruct->stWantedCameraPos, &_p_stStruct->stCurrentCameraPos);
MTH3D_M_vNullVector(&_p_stStruct->stCptPos.stMovePos);
CAM_fn_vComputeCineinfoCurrentForAPosition(_p_stStruct, &_p_stStruct->stCurrentCameraPos);
}
}
#endif
}
/*
*=================================================================================================
* If camera has no moved, and we want to go to the same position than previous one, force
* move pos to be NULL.
*=================================================================================================
*/
void CAM_fn_vConstraintMove(CAM_tdstUpdateCamera *_p_stStruct)
{
/*
* No constraint the first trame, and if we have force the position.
*/
if
(
(_p_stStruct->hCineinfo->ucVolIAFlags & C_VolIAFlags_InitJustCopiedInCurrent)
|| (_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_PositionIsAlreadyComputed)
|| (_p_stStruct->hCineinfoWork->hSuperObjectTargeted == NULL)
)
return;
/*
* Determin if we can reset last failed wanted.
*/
if(CAM_fn_cCanResetConstraintMoveVisFailure(_p_stStruct, &_p_stStruct->stWantedCameraPos))
{
_p_stStruct->hCineinfo->ucPerIAFlags &= ~C_PerIAFlags_ConstraintMoveVisFailure;
}
/*
* Constraint cause of a special mode.
*/
if(_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_ConstraintMoveVisFailure)
{
CAM_fn_vConstraintMoveAfterVisFailure(_p_stStruct);
return;
}
/*
* If we have cut angle, we try to go to the position defined by the cutted angles.
* If we don't want to cut angle, we reset the last sens of cutting.
*/
if
(
(_p_stStruct->cHasCutAlpha)
&& (!(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoParseCutAngle))
)
{
CAM_fn_vConstraintMoveCutAngles(_p_stStruct);
}
else
{
_p_stStruct->hCineinfo->cLastCutAngleSens = 0;
}
/*
* Force camera to stay in place if it is not moved
*/
if(_p_stStruct->hCineinfo->eState == CAM_e_State_GoToComputedOptimal)
{
CAM_fn_vConstraintNoMove(_p_stStruct, &_p_stStruct->stWantedCameraPos);
}
}
/*
*=================================================================================================
* Take care of targeted perso father.
*=================================================================================================
*/
void CAM_fn_vTakeCareOfFather(CAM_tdstUpdateCamera *_p_stStruct)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* MS_tdxHandleToDynam h_Dynam;*/
/* DNM_tdstDynamics *p_stDynamics;*/
HIE_tdxHandleToSuperObject hFather;
/* POS_tdstCompletePosition stMatrix;*/
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
hFather = CAM_fn_hGetFather(_p_stStruct->hCineinfoWork->hSuperObjectTargeted);
/* if(hFather == NULL)*/
/* return;*/
/* h_Dynam = M_GetMSHandle(hFather, Dynam);*/
/* if(h_Dynam == NULL)*/
/* return;*/
/* p_stDynamics = fn_p_stDynamGetDynamics(h_Dynam); */
/* if(p_stDynamics == NULL)*/
/* return;*/
/* POS_fn_vInvertMatrix(&stMatrix, DNM_M_p_stDynamicsGetPrevPreviousMatrix(p_stDynamics));*/
/* POS_fn_vMulMatrixMatrix(&stMatrix, DNM_M_p_stDynamicsGetPreviousMatrix(p_stDynamics), &stMatrix);*/
/* POS_fn_vMulMatrixVertex(&_p_stStruct->hCineinfo->stLastFailedWanted, &stMatrix, &_p_stStruct->hCineinfo->stLastFailedWanted);*/
/* POS_fn_vMulMatrixVertex(&_p_stStruct->hCineinfo->stLastFailedOrigin, &stMatrix, &_p_stStruct->hCineinfo->stLastFailedOrigin);*/
}
/*
**************************************************************************************************
**************************************************************************************************
GENERAL MANAGMENT
**************************************************************************************************
**************************************************************************************************
*/
/*
*=================================================================================================
* Main camera function.
*=================================================================================================
*/
void CAM_fn_vUpdateGeneralCamera(CAM_tdstUpdateCamera *_p_stStruct)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
MTH3D_tdstVector stMoveVector;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
recom: /* C'est ignoble, mais j'assume */
cCanTestStatic = 1;
/*
**********************************************************************************************
**********************************************************************************************
*/
/*
* Take care of father to change last computed positions.
*/
CAM_fn_vTakeCareOfFather(_p_stStruct);
/*
**********************************************************************************************
**********************************************************************************************
*/
/*
* Test if camera is moving. wCounter4 is increased each time camera is not moving, and
* reset to 0 else.
*/
MTH3D_M_vCopyVector(&stMoveVector, DNM_M_p_stReportGetLastMove(_p_stStruct->p_stReport));
if(MTH_M_bLess(MTH3D_M_xNormVector(&stMoveVector), CAM_C_xMinLinearSpeedCamera))
{
_p_stStruct->hCineinfo->ucVolIAFlags |= C_VolIAFlags_CameraNotMove;
/*
* We don't increase wCounter4 if it's greater than CAM_C_xTickFindBetterPosIfNoMove.
*/
/* ANNECY MT - 03/08/99 { */
/*
if(_p_stStruct->hCineinfo->wCounter4 < CAM_C_xTickFindBetterPosIfNoMove)
{
_p_stStruct->hCineinfo->wCounter4++;
}
*/
if(MTH_M_bLess(_p_stStruct->hCineinfo->xCounter4,CAM_C_xTickTimeFindBetterPosIfNoMove))
{
_p_stStruct->hCineinfo->xCounter4 = MTH_M_xAdd(_p_stStruct->hCineinfo->xCounter4,MTH_M_xFloatToReal(g_stEngineStructure.stEngineTimer.ulUsefulDeltaTime));
}
}
else
{
/*_p_stStruct->hCineinfo->wCounter4 = 0; */
_p_stStruct->hCineinfo->xCounter4 = MTH_C_ZERO;
}
/* END ANNECY MT } */
/*
* Special case in flying mode. Force some values.
*/
if (g_ucIsEdInGhostMode)
{
CAM_fn_vInitCompleteCineinfo(_p_stStruct->hCineinfo);
memcpy(_p_stStruct->hCineinfo->hWork, _p_stStruct->hCineinfo->hCurrent, sizeof(struct tdstInternalStructurCineinfo_));
_p_stStruct->hCineinfoWork->xDistMin = MTH_M_xFloatToReal(2.0f);
_p_stStruct->hCineinfoWork->xDistMax = MTH_M_xFloatToReal(2.0f);
_p_stStruct->hCineinfoWork->xAngleAlpha = MTH_C_ZERO;
_p_stStruct->hCineinfoWork->xAngleShiftAlpha = MTH_C_ZERO;
_p_stStruct->hCineinfoWork->xAngleTheta = MTH_C_ZERO;
_p_stStruct->hCineinfoWork->xAngleShiftTheta = MTH_C_ZERO;
_p_stStruct->hCineinfoWork->uwDNMFlags = DNM_CAM_C_NoLinearParsing|DNM_CAM_C_NoAngularParsing|DNM_CAM_C_NoTargetParsing|DNM_CAM_C_NoObstacle;
_p_stStruct->hCineinfoWork->uwIAFlags = C_IAFlags_NoVisibility|C_IAFlags_NoAverageMoveTgtPerso;
_p_stStruct->hCineinfo->ucPerIAFlags = 0;
_p_stStruct->hCineinfo->ucVolIAFlags = 0;
_p_stStruct->hCineinfo->eState = CAM_e_TempState_GhostMode;
}
/*
* Camera for cinematic scenary.
*/
if
(
(_p_stStruct->hCineinfoWork->hSuperObjectTargeted)
&& (_p_stStruct->hCineinfoWork->hSecondSuperObjectTargeted)
)
{
_p_stStruct->hCineinfo->ucPerIAFlags &= ~C_PerIAFlags_ConstraintMoveVisFailure;
_p_stStruct->hCineinfoWork->uwIAFlags |= C_IAFlags_NoVisibility;
_p_stStruct->hCineinfo->eState = CAM_e_TempState_ApexMode;
}
/*
**********************************************************************************************
* General.
**********************************************************************************************
*/
/*
* Every moving compute must take care of current axis requested. Even if make a position
* compute with a cineinfo without that flag, we must in fact compute the position with that
* flag (it determins the actual reference axis to compute all the positions).
* This is a global variable, so the computerefaxis will don't care of cineinfowork defined
* in the structure passed to it (look at the function...).
*
* The same for dyntheta.
*/
cRefAxisIsAlreadyComputed = _p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_RefAxisIsAlreadyComputed ? 1 : 0;
cNoDynChangeTheta = _p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoDynChangeTheta ? 1 : 0;
/*
* - Compute position of targeted perso
* - Compute target
* - Compute the real IA wanted position.
*/
CAM_fn_vComputeReferencePoint(_p_stStruct);
CAM_fn_vComputeTarget(_p_stStruct);
CAM_fn_vComputeRealWantedPos(_p_stStruct);
/*
* Compute camera move.
*/
CAM_fn_vComputeMovePos(_p_stStruct);
if
(
(!((_p_stStruct)->hCineinfo->ucVolIAFlags & C_VolIAFlags_InitJustCopiedInCurrent))
&& ((_p_stStruct)->hCineinfoWork->hSuperObjectTargeted)
&& (!cNoDynChangeTheta)
&& (!(_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_ConstraintMoveVisFailure))
&& (!(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_PositionIsAlreadyComputed))
)
{
if(CAM_fn_cDynChangeTheta(_p_stStruct, &_p_stStruct->stWantedCameraPos))
CAM_fn_vComputeMovePos(_p_stStruct);
}
/*
* Test if we can restore initial shift alpha and theta.
* When camera is to current wanted camera pos, we can restore.
*/
if
(
(_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_NoShift)
|| (_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_NoShiftUntilPosReached)
)
{
if
(
(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_TargetIsAlreadyComputed)
|| (_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_PositionIsAlreadyComputed)
|| (_p_stStruct->hCineinfo->ucVolIAFlags & C_VolIAFlags_InitJustCopiedInCurrent)
|| CAM_fn_bEqualVectorWithEpsilon
(
&_p_stStruct->stCurrentCameraPos,
&_p_stStruct->stWantedCameraPos,
CAM_C_xEpsilonForEqualVectors
)
)
{
_p_stStruct->hCineinfoCurrent->uwIAFlags &= ~C_IAFlags_NoShiftUntilPosReached;
_p_stStruct->hCineinfoWork->uwIAFlags &= ~C_IAFlags_NoShiftUntilPosReached;
_p_stStruct->hCineinfo->ucPerIAFlags &= ~C_PerIAFlags_NoShift;
_p_stStruct->hCineinfo->cLastCutAngleSens = 0;
}
}
/*
* If current is the same as wanted, force normal state.
*/
if
(
(CONSTANT_NORMALIFJOIN)
&& (_p_stStruct->hCineinfo->eState == CAM_e_State_GoToComputedOptimal)
&& (_p_stStruct->cTgtPersoIsMovingRelative)
)
{
if
(
CAM_fn_bEqualVectorWithEpsilon
(
&_p_stStruct->stCurrentCameraPos,
&_p_stStruct->stWantedCameraPos,
CAM_C_xEpsilonForEqualVectors
)
)
{
if (_p_stStruct->hCineinfo->ucPerIAFlags & C_PerIAFlags_VisibilityCopied)
CAM_fn_vSetCineinfoCurrentFromVisibility(_p_stStruct->hCineinfo);
_p_stStruct->hCineinfo->ucPerIAFlags &= ~C_PerIAFlags_ConstraintMoveVisFailure;
_p_stStruct->hCineinfo->ucVolIAFlags &= ~C_VolIAFlags_CurrentAlreadyCopiedInWork;
_p_stStruct->hCineinfo->eState = CAM_e_State_GoToOptimal;
goto recom;
}
}
/*
**********************************************************************************************
* Process the states.
**********************************************************************************************
*/
/*
* Some functions can change the current state to be in failure
*--------------------------------------------------------------
*/
switch(_p_stStruct->hCineinfo->eState)
{
/*
* - If target is not seen.
* - If camera distance is too near from target.
* - If collision is oppsition to current move.
*/
case CAM_e_State_GoToOptimal:
case CAM_e_State_GoToComputedOptimal:
CAM_fn_vTestBadVisibility(_p_stStruct);
CAM_fn_vTestBadDistance(_p_stStruct);
CAM_fn_vTestOppositeCollision(_p_stStruct);
break;
default:
break;
}
/*
* Process of each state.
*-----------------------
*/
switch(_p_stStruct->hCineinfo->eState)
{
/*
* We want to go to the optimal position defined in the MS with all the
* camera parameters.
*=========================================================================================
*/
case CAM_e_State_GoToOptimal:
CAM_fn_vConstraintMove(_p_stStruct);
break;
case CAM_e_State_GoToComputedOptimal:
CAM_fn_vCheckForABetterPos(_p_stStruct);
CAM_fn_vConstraintMove(_p_stStruct);
break;
/*
* Camera failure with visibility.
*=========================================================================================
*/
case CAM_e_State_FailureVisibility:
CAM_fn_vComputeFailureVisibility(_p_stStruct);
break;
/*
* Apex mode.
*=========================================================================================
*/
case CAM_e_TempState_ApexMode:
_p_stStruct->hCineinfo->eState = CAM_e_State_GoToOptimal;
break;
/*
* Ghost mode.
*=========================================================================================
*/
case CAM_e_TempState_GhostMode:
_p_stStruct->hCineinfo->eState = CAM_e_State_GoToOptimal;
break;
/* XB 05/05/99 */
default:
break;
/* End XB 05/05/99 */
}
/*
* Some update at the end.
*-------------------------
*/
/* Compute speed of camera */
CAM_fn_vComputeSpeed(_p_stStruct);
/* Reset values for visibility */
if
(
(_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_TargetIsAlreadyComputed)
|| (_p_stStruct->hCineinfoWork->uwIAFlags & C_IAFlags_PositionIsAlreadyComputed)
|| (_p_stStruct->hCineinfo->ucVolIAFlags & C_VolIAFlags_InitJustCopiedInCurrent)
|| (_p_stStruct->hCineinfo->eState == CAM_e_State_GoToOptimal)
)
{
MTH3D_M_vNullVector(&_p_stStruct->hCineinfo->stLastFailedOrigin);
MTH3D_M_vNullVector(&_p_stStruct->hCineinfo->stLastFailedWanted);
/* 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 } */
_p_stStruct->hCineinfo->ucPerIAFlags &= ~C_PerIAFlags_ConstraintMoveVisFailure;
}
/* Valid for one trame only */
cJustBetterPos = 0;
}