/*
 *=======================================================================================
 * Name        : MecBase.c
 * Author      : J Thénoz               Date : 01/05/98
 * Description : Mechanic functions for Base model
 *=======================================================================================
 */
 
/*FB030898*/
#define HIE_FRIEND
/*END FB*/
#include "cpa_expt.h"
#include "ACP_Base.h"
 
#include "MEC/MECInc.h"
#include "MEC/DnmDynam.h"
#include "MEC/ParsData.h"
#include "MEC/DNMSurSt.h"
#include "MEC/mbase.h"
#include "Extheade.h"
#include "COL.h"
#include "MEC/MecDef.h"
#include "MEC/MECOpt.h"
#include "MEC/MECBhv.h"
#include "MEC/MECCol.h"
#include "MEC/MECPfm.h"
#include "MEC/MECTools.h"
 
#include "PCS.h" /* Physical Collide Set */
#include "SCT.h" /* SeCTor*/
#include "FIL.h" /* SeCTor*/
#include "PRT.h" /* PaRTicules*/
#include "GAM.h" /* GAMe*/


/* global */
MTH_tdxReal MEC_g_xClimbSpeedLimit = MTH_M_xDoubleToReal(0.7);

MTH_tdxReal MEC_g_xBaseCoeff = C_xDNM_BASE_COEF;
MTH_tdxReal MEC_g_xWalkCoeff = C_xDNM_WALK_COEF;
 

extern POS_tdstCompletePosition * POS_g_p_stIdentityMatrix;
extern long g_lCallCounter;
extern ACP_tdxBool g_bHighSpeed;


 

/* internal functions */
long MEC_fn_lComputeCall ( struct DNM_stDynamics *p_stDynamic, HIE_tdxHandleToSuperObject hSupObj, MTH_tdxReal xDT, MTH_tdxReal xCoef )
{
	long lNbFrame, lCall;
	POS_tdxHandleToPosition hPreviousMatrix, hCurrentMatrix;
	MTH3D_tdstVector *p_stPreviousPosition, *p_stCurrentPosition;
	MTH3D_tdstVector stVector;

	hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
	hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
	p_stPreviousPosition = POS_fn_p_stGetTranslationVector ( hPreviousMatrix );
	p_stCurrentPosition = POS_fn_p_stGetTranslationVector ( hCurrentMatrix );

	MTH3D_M_vSubVector ( &stVector, p_stCurrentPosition, p_stPreviousPosition );
	
	
	if ((fn_ulStandardGameGetCustomBitsSO(hSupObj) & C_ulDNM_RAYMAN_CUSTOM_BIT) == C_ulDNM_RAYMAN_CUSTOM_BIT)
		lCall = MTH_M_xRealToLong (MTH_M_xAdd( MTH_M_xMul(MTH_M_xDiv(MTH3D_M_xNormVector(&stVector),C_ulDNM_RAYMAN_ZDM_RADIUS),xCoef) ,MTH_C_ONE));
	else
	{
		lNbFrame = MTH_M_xRealToLong (MTH_M_xAdd(MTH_M_xDiv (xDT,M_xGetFrameLength(g_stEngineStructure.stEngineTimer)),MTH_C_Inv2));
		lCall = 1;
		if (lNbFrame>4 && MTH_M_bGreater(MTH3D_M_xNormVector(&stVector),MTH_C_Inv2) )
			lCall = 2;
	}

	return lCall;
}


void MEC_fn_vBaseManager ( struct DNM_stDynamics *p_stDynamic, HIE_tdxHandleToSuperObject hSupObj, MTH_tdxReal xDT )
{
	long lCall, lCounter;
	
	if ( DNM_M_bDynamicsIsDontUseNewMechanic(p_stDynamic) || MTH_M_bEqualZero(MEC_g_xBaseCoeff) )
		MEC_fn_vBaseObstacleManagement ( p_stDynamic, hSupObj, xDT );
	else
	{
		lCall = MEC_fn_lComputeCall ( p_stDynamic, hSupObj, xDT, MEC_g_xBaseCoeff );
		
		MEC_fn_vSlowMode (p_stDynamic,lCall);
		MEC_fn_vBaseObstacleManagement ( p_stDynamic, hSupObj, xDT );
		for (lCounter=1; lCounter<lCall; lCounter++)
		{
			MEC_fn_vRepeatMove (p_stDynamic);
			MEC_fn_vBaseObstacleManagement ( p_stDynamic, hSupObj, xDT );
		}
		MEC_fn_vNormalMode (p_stDynamic,lCall);
	} 
}



void MEC_fn_vWalkManager ( struct DNM_stDynamics *p_stDynamic, HIE_tdxHandleToSuperObject hSupObj, MTH_tdxReal xDT )
{
	long lCall, lCounter;

	if ( DNM_M_bDynamicsIsDontUseNewMechanic(p_stDynamic) || MTH_M_bEqualZero(MEC_g_xWalkCoeff) )
		MEC_fn_vGroundObstacleManagement ( p_stDynamic, hSupObj, xDT );
	else
	{
		lCall = MEC_fn_lComputeCall ( p_stDynamic, hSupObj, xDT, MEC_g_xWalkCoeff );

		MEC_fn_vSlowMode (p_stDynamic,lCall);
		MEC_fn_vGroundObstacleManagement ( p_stDynamic, hSupObj, xDT );
		for (lCounter=1; lCounter<lCall; lCounter++)
		{
			g_lCallCounter = 0;
			MEC_fn_vRepeatMove (p_stDynamic);
			MEC_fn_vGroundObstacleManagement ( p_stDynamic, hSupObj, xDT );
		}
		MEC_fn_vNormalMode (p_stDynamic,lCall);
	}
}



/* Dynamic function*/
struct DNM_stDynamics *MEC_p_stDynamicsBaseMechanics
(
	struct DNM_stDynamics *p_stDynamic,
    HIE_tdxHandleToSuperObject hSupObj,
    struct DNM_stParsingDatas *p_stParsingDatas,
    DNM_tdxHandleToMecIdentityCard h_MecIdCard,
    MTH_tdxReal xDT
)
{
	/* variable declaration */
	DNM_tdstMecBaseIdCard* pstBaseMecIdCard;
	GEO_tdxHandleToMatrix hGlobalMatrix;
	POS_tdxHandleToPosition hCurrentMatrix; 
	POS_tdxHandleToPosition hPreviousMatrix;
	POS_tdxHandleToPosition hPrevPreviousMatrix;
	POS_tdxHandleToPosition hAbsolutePreviousMatrix;
	POS_tdxHandleToPosition hPreviousReferenceMatrix;
	POS_tdxHandleToPosition hInvPreviousReferenceMatrix;
	POS_tdxHandleToPosition hPrevPreviousReferenceMatrix;
	POS_tdxHandleToPosition hRefMatrix;
	POS_tdxHandleToPosition hInvRefMatrix;
 
 
	POS_tdstCompletePosition stPreviousReferenceMatrix, stInvPreviousReferenceMatrix, stPrevPreviousReferenceMatrix, stInvMatrix, stRefMatrix;
	MTH3D_tdstVector *p_stCurrentTranslation, *p_stAbsolutePreviousTranslation;
	MTH3D_tdstVector stSpeed;
	MTH3D_tdstVector stStablePreviousPosition;
	MTH3D_tdstVector *p_stPreviousX, *p_stPreviousY, *p_stPreviousZ;
	/* XB 05/05/99 */
	/* MTH_tdxReal xDotProd; */
	/* End XB 05/05/99 */
	DNM_tdstReport* p_stReport=NULL;
	ACP_tdxBool bNeedToCollide;
	ACP_tdxBool bPlatform=FALSE;
	ACP_tdxBool bPlatformChange=FALSE;
	ACP_tdxBool bImposeRotation;
	MTH3D_tdstVector stI, stJ, stK;
	long lNbFrame, lFrame;
 
	MTH_tdstMove stMove; 
	MTH3D_tdstVector stVector; 
	MTH3D_tdstVector stMatrixTranslation;
/* XB 05/05/99 */
	/* MTH_tdxReal xSlide = MTH_C_ZERO; */
/* End XB 05/05/99 */
	DNM_tdstMecObstacle* p_stObstacle;
 
	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic) && DNM_M_bDynamicsIsCollisionReport(p_stDynamic)) 
		MTH_M_MoveSetNull(&stMove); //AR9903	
 
	if (DNM_M_bDynamicsIsCollisionReport(p_stDynamic))
	{
		p_stReport = DNM_M_p_stDynamicsGetReport (p_stDynamic);
 
		if ( DNM_M_ulReportGetSurfaceState (p_stReport) & C_WOT_ulForceMobile )
			DNM_M_ulReportSetSurfaceState (p_stReport,C_WOT_ulMobile);	
		else
			DNM_M_ulReportSetSurfaceState (p_stReport,C_WOT_ulNoObstacle);
	}
 
 
	DNM_M_vDynamicsSetExec ( p_stDynamic, TRUE );
	DNM_M_vDynamicsSetActorMove (p_stDynamic,FALSE);

	/* exit optimization */
	if ( !fn_bGetCharacterForceCollisionWhenNotMoving(hSupObj) && MEC_fn_bNoMove(p_stDynamic) && !DNM_M_bDynamicsIsInit(p_stDynamic) && !DNM_M_bDynamicsIsChangeScale(p_stDynamic) )
	{
		return p_stDynamic; 
	}
 
	/* variable definition */
	pstBaseMecIdCard = (DNM_tdstMecBaseIdCard*)h_MecIdCard;
	hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
	hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
	
	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic))
	{
		hPrevPreviousMatrix = DNM_M_p_stDynamicsGetPrevPreviousMatrix (p_stDynamic);
		hAbsolutePreviousMatrix = DNM_M_p_stDynamicsGetAbsolutePreviousMatrix (p_stDynamic);
	}
 
	POS_fn_vCopyMatrix(&stPreviousReferenceMatrix, (POS_tdstCompletePosition *) POS_g_p_stIdentityMatrix);
	hPreviousReferenceMatrix = &stPreviousReferenceMatrix;
 
	POS_fn_vCopyMatrix(&stPrevPreviousReferenceMatrix, (POS_tdstCompletePosition *) POS_g_p_stIdentityMatrix);
	hPrevPreviousReferenceMatrix = &stPrevPreviousReferenceMatrix;
 
	hGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix (hSupObj);
	POS_fn_vCopyMatrix(&stRefMatrix, (POS_tdstCompletePosition *) POS_g_p_stIdentityMatrix);
 
	hRefMatrix = &stRefMatrix;
 
	hInvRefMatrix = (POS_tdxHandleToPosition)&stInvMatrix;
	DNM_M_vDynamicsSetComputeInvertMatrix (p_stDynamic,TRUE);

 
	/* clear global report */
	DNM_M_ulReportSetSurfaceState ( &g_stReport, 0 );
	g_lCallCounter = 0;
	g_bHighSpeed = FALSE;
 
  	if ( DNM_M_bDynamicsIsInit(p_stDynamic))
	{
		POS_fn_vCopyMatrix ( hCurrentMatrix, hGlobalMatrix );
		POS_fn_vCopyMatrix ( hPreviousMatrix, hGlobalMatrix );
		
		if (DNM_M_bDynamicsIsComplexSize(p_stDynamic))
		{
			POS_fn_vCopyMatrix ( hPrevPreviousMatrix, hGlobalMatrix );
			POS_fn_vCopyMatrix ( hAbsolutePreviousMatrix, hGlobalMatrix );
		}
 
		if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic)) MEC_fn_vRegisterCollisionTranslation ( p_stDynamic, hCurrentMatrix );
 
		if (!DNM_M_bDynamicsIsChangeScale(p_stDynamic))
		{
			POS_fn_vGetScaleMatrix (hGlobalMatrix, &stI, &stJ, &stK);
			DNM_M_vDynamicsSetScale (p_stDynamic, MTH3D_M_xGetXofVector(&stI), MTH3D_M_xGetYofVector(&stJ), MTH3D_M_xGetZofVector(&stK) );
		}
		MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed ( p_stDynamic ) );
 
		DNM_M_vDynamicsSetInit (p_stDynamic,FALSE);
	}
 
	if ( DNM_M_bDynamicsIsMechanicChange (p_stDynamic) && DNM_M_bDynamicsIsComplexSize(p_stDynamic))
		MEC_fn_vCancelTilt (p_stDynamic);
 
	POS_fn_vCopyMatrix ( hRefMatrix ,  hPreviousMatrix );
	if (DNM_M_bDynamicsIsImposeRotation(p_stDynamic)) 
		MTH3D_M_vCopyMatrix ( &(hRefMatrix->stRotationMatrix), DNM_M_p_stDynamicsGetImposeRotationMatrix(p_stDynamic) );
	
 
	/* init collision counter */
	if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic))
	{
		if ( DNM_M_cDynamicsGetCollideCounter(p_stDynamic) <= 0 )
			DNM_M_vDynamicsSetCollideCounter ( p_stDynamic, fn_ucCollSetGetCollComputeFrequencySO(hSupObj) );
	}
 
	/* shoot mechanic */
	if (DNM_M_bDynamicsIsShoot (p_stDynamic))
	{
		bImposeRotation = DNM_M_bDynamicsIsImposeRotation(p_stDynamic);
 
		/* shoot mechanic */
		MTH3D_M_vMulScalarVector ( &stVector, xDT, DNM_M_pDynamicsGetPreviousSpeed ( p_stDynamic ) );
		MEC_fn_vSetInitialFrameTranslation ( p_stDynamic, &stVector );
 
		POS_fn_vCopyMatrix ( hPreviousReferenceMatrix, hPreviousMatrix );
 
		/* Impose speed ? */
		if (DNM_M_bDynamicsIsImposeSpeed(p_stDynamic))
		{
			MEC_fn_vImposeSpeed (p_stDynamic,xDT,hRefMatrix,hInvRefMatrix);
			DNM_M_vDynamicsSetImposeSpeedX ( p_stDynamic, FALSE );
			DNM_M_vDynamicsSetImposeSpeedY ( p_stDynamic, FALSE );
			DNM_M_vDynamicsSetImposeSpeedZ ( p_stDynamic, FALSE );
		}
 
		/* Impose rotation ? */
		if ( bImposeRotation )
		{	
			MEC_fn_vImposeRotation (p_stDynamic);
			DNM_M_vDynamicsSetImposeRotation ( p_stDynamic, FALSE );
		}
 
		if (DNM_M_bDynamicsIsCollide(p_stDynamic))
		{
			if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic))
			{
				DNM_M_vDynamicsDecCollideCounter (p_stDynamic);
		
				if ( DNM_M_cDynamicsGetCollideCounter (p_stDynamic)==0  )
				{
//					MEC_fn_vBaseObstacleManagement ( p_stDynamic, hSupObj, xDT );
					MEC_fn_vBaseManager ( p_stDynamic, hSupObj, xDT );
					if (fn_ucCollSetGetCollComputeFrequencySO(hSupObj)>1) MEC_fn_vRegisterCollisionTranslation (p_stDynamic,hCurrentMatrix);
				}
			}
//			else MEC_fn_vBaseObstacleManagement ( p_stDynamic, hSupObj, xDT );
			else MEC_fn_vBaseManager ( p_stDynamic, hSupObj, xDT );
		}
 
		MEC_fn_vComputeSpeed ( p_stDynamic, xDT );
 
		/* adjust matrix to get scale */
		MEC_fn_vCorrectMatrix ( p_stDynamic, hCurrentMatrix );
 
		
		if(!MEC_fn_bIsEqualMatrix (hGlobalMatrix,hCurrentMatrix))
		{
			POS_fn_vCopyMatrix ( hGlobalMatrix, hCurrentMatrix );
			HIE_fn_vComputeNewRelativeMatrix (hSupObj);
		}
				
		/* platform and pushed objects update */
		if ( fn_bStandardGameIsAPlatform(hSupObj) )
		{
			if(!MEC_fn_bIsEqualMatrix (hPreviousMatrix,hCurrentMatrix))
			{
				HIE_fn_vRefreshHierarchy (hSupObj);
		
				/* invert matrix only if usefull */
				if (bImposeRotation)
				{
					hInvPreviousReferenceMatrix = (POS_tdxHandleToPosition)&stInvPreviousReferenceMatrix;
					POS_fn_vInvertMatrix (hInvPreviousReferenceMatrix,hPreviousReferenceMatrix);
				}
				else
				{
					MEC_fn_vInvertMatrix (p_stDynamic,hInvRefMatrix,hRefMatrix);
					hInvPreviousReferenceMatrix = hInvRefMatrix;
				}
 
				MEC_fn_vUpdatePlatform (p_stDynamic,hSupObj, hPreviousReferenceMatrix, hInvPreviousReferenceMatrix);
			}
		}
		else if ( (fn_ulStandardGameGetCustomBitsSO(hSupObj) & C_ulDNM_COMPUTE_CHANNEL) && !MEC_fn_bIsEqualMatrix (hPreviousMatrix,hCurrentMatrix))
		{
			HIE_fn_vRefreshHierarchy (hSupObj);
		}
 
		MEC_fn_vInitMatrix (p_stDynamic);
		MEC_fn_vFillCollisionReport (p_stDynamic);
 
		return p_stDynamic;
	}
		
	/* number of frame */
	lNbFrame = MTH_M_xRealToLong (MTH_M_xAdd(MTH_M_xDiv (xDT,M_xGetFrameLength(g_stEngineStructure.stEngineTimer)),MTH_C_Inv2));
 
	/* stable position */
	POS_fn_vGetTranslationVector ( hPreviousMatrix, &stStablePreviousPosition );
 
	/* copy previous reference */
	POS_fn_vCopyMatrix ( hPreviousReferenceMatrix, hPreviousMatrix );
	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic)) POS_fn_vCopyMatrix ( hPrevPreviousReferenceMatrix, hPrevPreviousMatrix );
 
	/* reset platform crash */
	DNM_M_bDynamicsSetPlatformCrash (p_stDynamic,FALSE);
	DNM_M_bDynamicsSetCanFall (p_stDynamic,FALSE);
 
	if ( DNM_M_bDynamicsIsScale(p_stDynamic) && MEC_fn_bIsScale(p_stDynamic)  )
		MEC_fn_vAdjustScaleData (p_stDynamic,hRefMatrix,hInvRefMatrix);
 
	MTH3D_M_vMulScalarVector ( DNM_M_p_stDynamicsGetSpeedAnim(p_stDynamic), M_xGetFrameLength(g_stEngineStructure.stEngineTimer), DNM_M_p_stDynamicsGetSpeedAnim(p_stDynamic) );
	POS_fn_vRotateVector ( DNM_M_p_stDynamicsGetSpeedAnim(p_stDynamic), hCurrentMatrix, DNM_M_p_stDynamicsGetSpeedAnim(p_stDynamic) );
	
	/* init frame */
	MTH3D_M_vDivScalarVector (DNM_M_pDynamicsGetAddTranslation(p_stDynamic),DNM_M_pDynamicsGetAddTranslation(p_stDynamic), MTH_M_xDoubleToReal(lNbFrame));
 
	/* translate matrix on */
	MEC_fn_vTranslateMatrixOn (p_stDynamic,&stMatrixTranslation);
 
	for (lFrame=0; lFrame<lNbFrame; lFrame++)
	{
		if (DNM_M_bDynamicsIsAnimation(p_stDynamic)) MEC_fn_vSetInitialFrameTranslation (p_stDynamic,DNM_M_p_stDynamicsGetSpeedAnim(p_stDynamic));
		
		/* Propose speed */
		if (DNM_M_bDynamicsIsProposeSpeed(p_stDynamic)) MEC_fn_vProposeSpeed (p_stDynamic,M_xGetFrameLength(g_stEngineStructure.stEngineTimer),hRefMatrix,hInvRefMatrix);
 
		/* stream priority 0 */
		if ( DNM_M_bDynamicsIsStream(p_stDynamic) )
		{
			if ( DNM_M_xDynamicsGetStreamPriority(p_stDynamic)==0 )
				MEC_fn_vAddStream (p_stDynamic,M_xGetFrameLength(g_stEngineStructure.stEngineTimer),TRUE);
		}
	
			/* inertia */
		MEC_fn_vInertia (p_stDynamic,M_xGetFrameLength(g_stEngineStructure.stEngineTimer),hRefMatrix,hInvRefMatrix);
 
		/* Gravity */
		if ( DNM_M_bDynamicsIsGravity(p_stDynamic) ) MEC_fn_vGravitySpeed (p_stDynamic,M_xGetFrameLength(g_stEngineStructure.stEngineTimer));
 
		/* Impose speed ? */
		if (DNM_M_bDynamicsIsImposeSpeed(p_stDynamic)) MEC_fn_vImposeSpeed (p_stDynamic,M_xGetFrameLength(g_stEngineStructure.stEngineTimer),hRefMatrix,hInvRefMatrix);
 
		/* Add speed ? */
		if(DNM_M_bDynamicsIsAddSpeed(p_stDynamic)) MEC_fn_vAddSpeed (p_stDynamic,M_xGetFrameLength(g_stEngineStructure.stEngineTimer),hRefMatrix,hInvRefMatrix);
 
		if ( DNM_M_bDynamicsIsImposeRotation(p_stDynamic) )
		{
			/* Impose rotation */
			MEC_fn_vImposeRotation (p_stDynamic);
 
			/* Add translation due to impose rotation */
			MEC_fn_vAdditionnalTranslation (p_stDynamic);
		}
		else if (DNM_M_bDynamicsIsImposeTranslation(p_stDynamic)) MEC_fn_vAdditionnalTranslation (p_stDynamic);
 
		/* stream priority 1 */
		if (DNM_M_bDynamicsIsStream(p_stDynamic))
		{
			if ( DNM_M_xDynamicsGetStreamPriority(p_stDynamic)==1 )
				MEC_fn_vAddStream (p_stDynamic,M_xGetFrameLength(g_stEngineStructure.stEngineTimer),FALSE);
		}
 
		/* Speed limit */
		if (DNM_M_bDynamicsIsSpeedLimit(p_stDynamic)) MEC_fn_vSpeedLimit ( p_stDynamic, M_xGetFrameLength(g_stEngineStructure.stEngineTimer), hRefMatrix, hInvRefMatrix );
 
		MEC_fn_vComputeSpeed (p_stDynamic,M_xGetFrameLength(g_stEngineStructure.stEngineTimer));
 
		/* report additionnnal vector */
		if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic)) MEC_fn_vComputeInertiaTranslation ( p_stDynamic, M_xGetFrameLength(g_stEngineStructure.stEngineTimer) );
 
		/* current -> previous */
		if (DNM_M_bDynamicsIsComplexSize(p_stDynamic)) POS_fn_vCopyMatrix ( hPrevPreviousMatrix, hPreviousMatrix );
		POS_fn_vCopyMatrix ( hPreviousMatrix, hCurrentMatrix );
 
		/* optimisation */
		if ( MTH3D_M_bIsNullVector (DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic)) ) lFrame=lNbFrame;
	}
	
	/* restore values */
	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic)) POS_fn_vCopyMatrix ( hPrevPreviousMatrix, hPrevPreviousReferenceMatrix );
	POS_fn_vCopyMatrix ( hPreviousMatrix, hPreviousReferenceMatrix );
 
	/* translate matrix off */
	MEC_fn_vTranslateMatrixOff (p_stDynamic,&stMatrixTranslation);
 
	/* adjust speed */
	MEC_fn_vAdjustSpeed (p_stDynamic, xDT);
 
	/* Tilt */
	if (DNM_M_bDynamicsIsTilt(p_stDynamic)) MEC_fn_vAddTiltSpeed (p_stDynamic,xDT);
 
	/* need to collide ? */
	bNeedToCollide = MEC_fn_bDynamicsNeedCollide(p_stDynamic);
	
	/* platform ? */
	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic)) bPlatform = MEC_fn_bIsPlatform(p_stDynamic);
	
	DNM_M_vDynamicsSetNoGravity (p_stDynamic,FALSE);
 
	if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic))
	{
	
		/* dec collision counter */
		DNM_M_vDynamicsDecCollideCounter (p_stDynamic);
	
		/* Obstacle part */
		if (DNM_M_cDynamicsGetCollideCounter (p_stDynamic)==0)
		{
			if ( bNeedToCollide || bPlatform || fn_bGetCharacterForceCollisionWhenNotMoving(hSupObj) )
			{
				if (DNM_M_bDynamicsIsGi (p_stDynamic)) MEC_fn_vGiObstacleManagement ( p_stDynamic, hSupObj, xDT );
				else if (DNM_M_bDynamicsIsClimb (p_stDynamic))
				{
					MEC_fn_vClimbObstacleManagement ( p_stDynamic, hSupObj, xDT );
					/* if actor moves just a little, actor don't move at all.*/
					if (MTH_M_bLess ( MTH3D_M_xNormVector(DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic)), MEC_g_xClimbSpeedLimit ))
					{
						MTH3D_M_vCopyVector ( POS_fn_p_stGetTranslationVector(hCurrentMatrix), POS_fn_p_stGetTranslationVector(hPreviousMatrix) );
						MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
					}
				}
//				else if (DNM_M_bDynamicsIsOnGround (p_stDynamic)) MEC_fn_vGroundObstacleManagement ( p_stDynamic, hSupObj, xDT );
				else if (DNM_M_bDynamicsIsOnGround (p_stDynamic)) MEC_fn_vWalkManager ( p_stDynamic, hSupObj, xDT );
				else if (DNM_M_bDynamicsIsSpider (p_stDynamic)) MEC_fn_vSpiderObstacleManagement ( p_stDynamic, hSupObj, xDT );
//				else if (DNM_M_bDynamicsIsCollide(p_stDynamic)) MEC_fn_vBaseObstacleManagement ( p_stDynamic, hSupObj, xDT );
				else if (DNM_M_bDynamicsIsCollide(p_stDynamic)) MEC_fn_vBaseManager ( p_stDynamic, hSupObj, xDT );

			
			
			}
/*			else*/
/*			{*/
				/* collide only with other actors */
/*				if (fn_bGetCharacterForceCollisionWhenNotMoving(hSupObj))*/
/*				{*/
/*					ACP_tdxBool bCollisionState;*/
/*					bCollisionState = fn_bGetCharacterNoCollisionWithMap (hSupObj);*/
/*					fn_vSetCharacterNoCollisionWithMap (hSupObj,TRUE);*/
/*					if (MEC_fn_bInCollision(p_stDynamic,hSupObj) && !bCollisionState)*/
/*					{*/
/*						fn_vSetCharacterNoCollisionWithMap (hSupObj,bCollisionState);*/
	
/*						if (DNM_M_bDynamicsIsGi (p_stDynamic)) MEC_fn_vGiObstacleManagement ( p_stDynamic, hSupObj, xDT );*/
/*						else if (DNM_M_bDynamicsIsClimb (p_stDynamic)) MEC_fn_vClimbObstacleManagement ( p_stDynamic, hSupObj, xDT );*/
/*						else if ((p_stDynamic)) MEC_fn_vGroundObstacleManagement ( p_stDynamic, hSupObj, xDT, FALSE );*/
/*						else if (DNM_M_bDynamicsIsCollide(p_stDynamic)) MEC_fn_vBaseObstacleManagement ( p_stDynamic, hSupObj, xDT );*/
/*					}*/
/*					else*/
/*					{*/
/*						fn_vSetCharacterNoCollisionWithMap (hSupObj,bCollisionState);*/
/*						DNM_M_ulReportSetSurfaceState ( p_stReport, DNM_M_ulReportGetPrevSurfaceState (p_stReport) );*/
/*					}*/
/*				}*/
/*			}*/
/*			bCollide = TRUE;*/
 
			/* register collision */
			if (fn_ucCollSetGetCollComputeFrequencySO(hSupObj)>1) MEC_fn_vRegisterCollisionTranslation (p_stDynamic,hCurrentMatrix);
		}
		else
		{
			if (DNM_M_bDynamicsIsOnGround (p_stDynamic)) MEC_fn_vGroundGuess (p_stDynamic,xDT);
		
			if (DNM_M_bDynamicsIsCollisionReport(p_stDynamic))
				/* current collision state = previous one */
				DNM_M_ulReportSetSurfaceState ( p_stReport, DNM_M_ulReportGetPrevSurfaceState (p_stReport) );
		}
	}
	else	/* no advanced mechanic so collide every frame */
	{
		if ( bNeedToCollide || fn_bGetCharacterForceCollisionWhenNotMoving(hSupObj) )
		{
			if (DNM_M_bDynamicsIsGi (p_stDynamic)) MEC_fn_vGiObstacleManagement ( p_stDynamic, hSupObj, xDT );
			else if (DNM_M_bDynamicsIsClimb (p_stDynamic))
			{
				MEC_fn_vClimbObstacleManagement ( p_stDynamic, hSupObj, xDT );
				/* if actor moves just a little, actor don't move at all.*/
				if (MTH_M_bLess ( MTH3D_M_xNormVector(DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic)), MEC_g_xClimbSpeedLimit ))
				{
					MTH3D_M_vCopyVector ( POS_fn_p_stGetTranslationVector(hCurrentMatrix), POS_fn_p_stGetTranslationVector(hPreviousMatrix) );
					MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
				}
			}
//			else if (DNM_M_bDynamicsIsOnGround (p_stDynamic)) MEC_fn_vGroundObstacleManagement ( p_stDynamic, hSupObj, xDT );
			else if (DNM_M_bDynamicsIsOnGround (p_stDynamic)) MEC_fn_vWalkManager ( p_stDynamic, hSupObj, xDT );
			else if (DNM_M_bDynamicsIsSpider (p_stDynamic)) MEC_fn_vSpiderObstacleManagement ( p_stDynamic, hSupObj, xDT );
//			else if (DNM_M_bDynamicsIsCollide(p_stDynamic)) MEC_fn_vBaseObstacleManagement ( p_stDynamic, hSupObj, xDT );
			else if (DNM_M_bDynamicsIsCollide(p_stDynamic)) MEC_fn_vBaseManager ( p_stDynamic, hSupObj, xDT );

		}
	}
 
	/* check position limit */
	MEC_fn_vPositionLimit ( p_stDynamic, &stStablePreviousPosition );
 
	/* Platform Management */
	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic)) bPlatformChange = MEC_fn_vBasePlatformManagement ( p_stDynamic, hSupObj );
	
	/* correct scale */
	MEC_fn_vCorrectMatrix ( p_stDynamic, hCurrentMatrix );
 
	/* speed */
	p_stCurrentTranslation = POS_fn_p_stGetTranslationVector (hCurrentMatrix);
	/* XB 05/05/99 : move the following line 7 lines after */
	/* p_stAbsolutePreviousTranslation = POS_fn_p_stGetTranslationVector (hAbsolutePreviousMatrix); */
	/* End XB 05/05/99 */
 
	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic) && DNM_M_bDynamicsIsCollisionReport(p_stDynamic)) 
	{
	/* XB 05/05/99 */
		p_stAbsolutePreviousTranslation = POS_fn_p_stGetTranslationVector (hAbsolutePreviousMatrix);
	/* End XB 05/05/99 */
		/* absolute speed */
 
		MTH3D_M_vSubVector (&stSpeed,p_stCurrentTranslation,p_stAbsolutePreviousTranslation);
		MTH3D_M_vDivScalarVector (&stSpeed, &stSpeed, xDT);
 
		/* Update Dynamic Report speed linear -> to keep speed variable in IA */ 
		/* to CB's camera */
		POS_fn_vGetRotationVector ( hAbsolutePreviousMatrix, &p_stPreviousX, &p_stPreviousY, &p_stPreviousZ );

	/* XB 05/05/99 : unused !!!! */
		/* check |xDotProd|<=1 */
	/*	xDotProd = MTH_M_xMin ( MTH_M_xMax ( xDotProd, MTH_C_MinusONE ), MTH_C_ONE ); */
	/* End XB 05/05/99 */

		/* keep Y of hAbsolutePreviousMatrix in &stMove */
		/* will be used to update real angular position if required by camera */
		MTH_M_MoveSetAngularPosition ( &stMove, MTH_C_ONE, p_stPreviousY );

		MTH_M_MoveSetLinear ( &stMove, &stSpeed );
		DNM_M_ReportSetAbsoluteCurrSpeed ( DNM_M_p_stDynamicsGetReport (p_stDynamic), &stMove );
	}
 
 
	/* Update Gli position */
	if(!MEC_fn_bIsEqualMatrix (hGlobalMatrix,hCurrentMatrix) || bPlatformChange)
	{
		POS_fn_vCopyMatrix ( hGlobalMatrix, hCurrentMatrix );
		HIE_fn_vComputeNewRelativeMatrix (hSupObj);
		DNM_M_vDynamicsSetActorMove (p_stDynamic,TRUE);
	}
 
	/* platform and pushed objects update */
	if ( fn_bStandardGameIsAPlatform(hSupObj) )
	{
		if(!MEC_fn_bIsEqualMatrix (hPreviousMatrix,hCurrentMatrix))
		{
			HIE_fn_vRefreshHierarchy (hSupObj);
		
			/* invert matrix only if usefull */
			if (DNM_M_bDynamicsIsImposeRotation(p_stDynamic))
			{
				hInvPreviousReferenceMatrix = (POS_tdxHandleToPosition)&stInvPreviousReferenceMatrix;
				POS_fn_vInvertMatrix (hInvPreviousReferenceMatrix,hPreviousReferenceMatrix);
			}
			else
			{
				MEC_fn_vInvertMatrix (p_stDynamic,hInvRefMatrix,hRefMatrix);
				hInvPreviousReferenceMatrix = hInvRefMatrix;
			}
 
			MEC_fn_vUpdatePlatform (p_stDynamic,hSupObj, hPreviousReferenceMatrix, hInvPreviousReferenceMatrix);
		}
	}
	else if ( (fn_ulStandardGameGetCustomBitsSO(hSupObj) & C_ulDNM_COMPUTE_CHANNEL) && !MEC_fn_bIsEqualMatrix (hPreviousMatrix,hCurrentMatrix))
	{
		HIE_fn_vRefreshHierarchy (hSupObj);
	}
 
 
	/* Update Matrix */
	MEC_fn_vInitMatrix (p_stDynamic);
	
	/* Update Dynamic Report position linear -> to keep position varaiable in IA */
	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic) && DNM_M_bDynamicsIsCollisionReport(p_stDynamic))
	{
		MTH3D_M_vCopyVector ( &stVector, p_stCurrentTranslation );
		MTH_M_MoveSetAngularToNull ( &stMove );
		MTH_M_MoveSetLinear ( &stMove, &stVector );
		DNM_M_ReportSetAbsoluteCurrPosition (DNM_M_p_stDynamicsGetReport (p_stDynamic),&stMove);
	}
 
	MEC_fn_vFillCollisionReport (p_stDynamic);
 
	/* Update report state */
	if (DNM_M_bDynamicsIsCollisionReport(p_stDynamic)) DNM_M_ulReportSetPrevSurfaceState ( p_stReport, DNM_M_ulReportGetSurfaceState (p_stReport) );
 
	/* update Nb Frame */
	DNM_M_vDynamicsSetNbFrame ( p_stDynamic, (unsigned char)lNbFrame );
 
	/* End */
	
	MTH3D_M_vNullVector ( DNM_M_pDynamicsGetImposeSpeed (p_stDynamic) );
	MTH3D_M_vNullVector ( DNM_M_pDynamicsGetProposeSpeed (p_stDynamic) );
	MTH3D_M_vNullVector ( DNM_M_p_stDynamicsGetSpeedAnim(p_stDynamic) );
	MTH3D_M_vNullVector ( DNM_M_pDynamicsGetAddTranslation(p_stDynamic) );
	DNM_M_bDynamicsSetAbsoluteImposeSpeed ( p_stDynamic, FALSE );
	DNM_M_bDynamicsSetAbsoluteProposeSpeed ( p_stDynamic, FALSE );
	DNM_M_bDynamicsSetAbsoluteAddSpeed ( p_stDynamic, FALSE );
	DNM_M_vDynamicsSetImposeSpeedX ( p_stDynamic, FALSE );
	DNM_M_vDynamicsSetImposeSpeedY ( p_stDynamic, FALSE );
	DNM_M_vDynamicsSetImposeSpeedZ ( p_stDynamic, FALSE );
	DNM_M_vDynamicsSetProposeSpeedX ( p_stDynamic, FALSE );
	DNM_M_vDynamicsSetProposeSpeedY ( p_stDynamic, FALSE );
	DNM_M_vDynamicsSetProposeSpeedZ ( p_stDynamic, FALSE );
	DNM_M_vDynamicsSetAddSpeedX ( p_stDynamic, FALSE );
	DNM_M_vDynamicsSetAddSpeedY ( p_stDynamic, FALSE );
	DNM_M_vDynamicsSetAddSpeedZ ( p_stDynamic, FALSE );
	DNM_M_vDynamicsSetImposeRotation ( p_stDynamic, FALSE );
	DNM_M_vDynamicsSetImposeTranslation ( p_stDynamic, FALSE );
	DNM_M_bDynamicsSetMechanicChange( p_stDynamic,FALSE);
	DNM_M_vDynamicsSetChangeScale( p_stDynamic, FALSE );
 
 
	/* reset coeff */
	MEC_g_xBaseCoeff = C_xDNM_BASE_COEF;
	MEC_g_xWalkCoeff = C_xDNM_WALK_COEF;

	if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic))
	{
		p_stObstacle = DNM_M_p_stReportGetObstacle (&g_stReport);
		if ( p_stObstacle && ((DNM_M_ulReportGetSurfaceState(&g_stReport))!=C_WOT_ulNoObstacle) )
			DNM_M_vDynamicsSetPreviousSlide(p_stDynamic,MEC_fn_xGetSlide (p_stDynamic,p_stObstacle));	
		else
			DNM_M_vDynamicsSetPreviousSlide(p_stDynamic,MTH_C_ZERO);
	}

	p_stObstacle = DNM_M_p_stReportGetGround(&g_stReport);
	if 
	( 
		p_stObstacle 
	&&	((DNM_M_ulReportGetSurfaceState(&g_stReport)&C_WOT_ulGround)==C_WOT_ulGround) 
	&&	MTH_M_bDifferent(MEC_fn_xGetSlide (p_stDynamic,p_stObstacle),MTH_C_ZERO)
	)
		DNM_M_vDynamicsSetSlidingGround(p_stDynamic,TRUE);
	else
		DNM_M_vDynamicsSetSlidingGround(p_stDynamic,FALSE);

	
	if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic))
	{
		MTH3D_M_vNullVector ( DNM_M_pDynamicsGetAddSpeed (p_stDynamic) );
		MTH3D_M_vNullVector ( DNM_M_pDynamicsGetStreamSpeed (p_stDynamic) );
	}
 
	return p_stDynamic;
}
 
 
/* Impose rotation matrix */
void MEC_vImposeRotationMatrix 
(
	struct DNM_stDynamics *p_stDynamic,
	POS_tdxHandleToPosition hRotationMatrix 
)
{
	POS_tdxHandleToPosition hCurrentMatrix;
	MTH3D_tdstVector *p_stCurrentTranslation, *p_stMatrixTranslation;
	MTH3D_tdstVector stMove;
 
	if (DNM_M_bDynamicsIsInit(p_stDynamic)) return;
 
	hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
 
	/* impose rotation */
	DNM_M_vDynamicsSetImposeRotation (p_stDynamic,TRUE);
	DNM_M_vDynamicsSetImposeRotationMatrix (p_stDynamic,&(hRotationMatrix->stRotationMatrix));
 
	/* translation without rotation */
	p_stCurrentTranslation = POS_fn_p_stGetTranslationVector ( hCurrentMatrix );
	p_stMatrixTranslation = POS_fn_p_stGetTranslationVector ( hRotationMatrix );
	
	MTH3D_M_vSubVector (&stMove,p_stMatrixTranslation,p_stCurrentTranslation);
	DNM_M_vDynamicsSetAddTranslation (p_stDynamic,&stMove);
 
	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic)) MEC_fn_vCancelTilt (p_stDynamic);
}
 
void MEC_vImposeRotationVector 
(
	struct DNM_stDynamics *p_stDynamic,
	MTH3D_tdstVector *p_stX, 
	MTH3D_tdstVector *p_stY, 
	MTH3D_tdstVector *p_stZ 
)
{
	MTH3D_tdstMatrix* p_stImposeRotationMatrix;
 
	if (DNM_M_bDynamicsIsInit(p_stDynamic)) return;
 
	p_stImposeRotationMatrix = DNM_M_p_stDynamicsGetImposeRotationMatrix (p_stDynamic);
	MTH3D_M_vSetVectorsInMatrix( p_stImposeRotationMatrix, p_stX, p_stY, p_stZ);
 
	/* impose rotation */
	DNM_M_vDynamicsSetImposeRotation (p_stDynamic,TRUE);
}
 
 
/* Impose relative rotation */
void MEC_vImposeRelativeRotation
(
	struct DNM_stDynamics *p_stDynamic,
	MTH3D_tdstMatrix *p_stRotationMatrix
)
{
	MTH3D_tdstVector *p_stI, *p_stJ, *p_stK;
	MTH3D_tdstMatrix stMatrix;
	POS_tdxHandleToPosition hCurrentMatrix;
 
	if (DNM_M_bDynamicsIsInit(p_stDynamic)) return;
	hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
	POS_fn_vGetRotationVector ( hCurrentMatrix, &p_stI, &p_stJ, &p_stK );
	MTH3D_M_vSetVectorsInMatrix ( &stMatrix, p_stI, p_stJ, p_stK );
	MTH3D_M_vMulMatrixMatrix ( &stMatrix, &stMatrix, p_stRotationMatrix );
	MTH3D_M_vGetVectorsInMatrix ( p_stI, p_stJ, p_stK, &stMatrix );
	MEC_fn_vUpdateMatrix (p_stDynamic,hCurrentMatrix);
 
	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic)) MEC_fn_vCancelTilt (p_stDynamic);
}
 
 
/* Impose absolute translation */
void MEC_vImposeTranslation
(
	struct DNM_stDynamics *p_stDynamic,
	MTH3D_tdstVector* p_stVector 
)
{
	MTH3D_tdstVector stVector;
	MTH3D_tdstVector* p_stCurrentTranslation;
	POS_tdxHandleToPosition hCurrentMatrix;
	
	if (DNM_M_bDynamicsIsInit(p_stDynamic)) return;
	DNM_M_vDynamicsSetImposeTranslation ( p_stDynamic, TRUE );
	hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
	p_stCurrentTranslation = POS_fn_p_stGetTranslationVector (hCurrentMatrix);
	MTH3D_M_vSubVector ( &stVector, p_stVector, p_stCurrentTranslation );
	DNM_M_vDynamicsSetAddTranslation (p_stDynamic,&stVector);
	MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
}
 
 
/* Init translation */
void MEC_vInitTranslation
(
	struct DNM_stDynamics *p_stDynamic,
	HIE_tdxHandleToSuperObject hSupObj,
	MTH3D_tdstVector* p_stVector 
)
{
	POS_tdxHandleToPosition hCurrentMatrix, hPreviousMatrix, hAbsolutePreviousMatrix, hPrevPreviousMatrix, hGlobalMatrix;
 
	if (DNM_M_bDynamicsIsInit(p_stDynamic))
	{
		hGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix (hSupObj);	
		POS_fn_vSetTranslationVector (hGlobalMatrix,p_stVector);
	}
	else
	{
		/*--- Base ---*/
		hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
		hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
		hGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix (hSupObj);	
		
		POS_fn_vSetTranslationVector (hCurrentMatrix,p_stVector);
		POS_fn_vSetTranslationVector (hPreviousMatrix,p_stVector);
		POS_fn_vCopyMatrix ( hGlobalMatrix, hCurrentMatrix );
		
		
		/*--- Complex ---*/
		if (DNM_M_bDynamicsIsComplexSize(p_stDynamic))
		{
			hAbsolutePreviousMatrix = DNM_M_p_stDynamicsGetAbsolutePreviousMatrix (p_stDynamic);
			hPrevPreviousMatrix = DNM_M_p_stDynamicsGetPrevPreviousMatrix (p_stDynamic);
 
			POS_fn_vSetTranslationVector (hAbsolutePreviousMatrix,p_stVector);
			POS_fn_vSetTranslationVector (hPrevPreviousMatrix,p_stVector);
		}
	}
 
	HIE_fn_vComputeNewRelativeMatrix (hSupObj);
 
	/* reset data */
	/*--- Base ---*/
	MTH3D_M_vNullVector (DNM_M_pDynamicsGetPreviousSpeed (p_stDynamic));
	MTH3D_M_vNullVector (DNM_M_pDynamicsGetAddTranslation(p_stDynamic));
 
	/*--- Advanced ---*/
	if (DNM_M_bDynamicsIsAdvancedSize(p_stDynamic))
	{
		MTH3D_M_vNullVector (DNM_M_pDynamicsGetInertiaTranslation(p_stDynamic));
	}
}
 
 
void MEC_fn_vImposeActorMatrix
(
	HIE_tdxHandleToSuperObject hSupObj
)
{
	POS_tdxHandleToPosition hCurrentMatrix, hPreviousMatrix, hAbsolutePreviousMatrix, hPrevPreviousMatrix, hGlobalMatrix;
	struct DNM_stDynamics *p_stDynamic;
 
	p_stDynamic = fn_p_stDynamGetDynamicsSO (hSupObj);
	if (!p_stDynamic) return;
 
	hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
	hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);
	hGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix (hSupObj);
 
	POS_fn_vCopyMatrix ( hCurrentMatrix, hGlobalMatrix );
	POS_fn_vCopyMatrix ( hPreviousMatrix, hGlobalMatrix );
	MTH3D_M_vNullVector ( DNM_M_pDynamicsGetPreviousSpeed(p_stDynamic) );
	DNM_M_vDynamicsSetActorMove (p_stDynamic,TRUE);

	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic))
	{
		hAbsolutePreviousMatrix = DNM_M_p_stDynamicsGetAbsolutePreviousMatrix (p_stDynamic);
		hPrevPreviousMatrix = DNM_M_p_stDynamicsGetPrevPreviousMatrix (p_stDynamic);
 
		POS_fn_vCopyMatrix ( hAbsolutePreviousMatrix, hGlobalMatrix );
		POS_fn_vCopyMatrix ( hPrevPreviousMatrix, hGlobalMatrix );
	}
}
 
 
 
void MEC_vTurnAroundZAxis 
( 	
	struct DNM_stDynamics *p_stDynamic,
	MTH_tdxReal xAngle
)
{
	POS_tdxHandleToPosition hCurrentMatrix;
	MTH3D_tdstVector stVectorZ;
	MTH3D_tdstVector stMove;
 
	if (DNM_M_bDynamicsIsInit(p_stDynamic)) return;
	if (MTH_M_bIsNull(xAngle)) return;
 
	hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
 
	if (DNM_M_bDynamicsIsTilt(p_stDynamic))
	{
		MTH3D_tdstVector stI, stJ, stK;
		MTH_tdxReal xCos, xSin;
 
		POS_tdxHandleToPosition hMatrix;
		POS_tdstCompletePosition stMatrix;
		hMatrix = &stMatrix;
 
		xCos = MTH_M_xCos ( xAngle );
		xSin = MTH_M_xSin ( xAngle );
 
/*FB030898*/
		/*POS_fn_vGetTranslationVector ( hCurrentMatrix, &stMove );*/
		MTH3D_M_vCopyVector(&stMove, &(hCurrentMatrix->stTranslationVector) );
/*END FB*/
 
/*FB030898*/
		/*POS_fn_vSetIdentityMatrix ( hMatrix );*/
		POS_fn_vCopyMatrix(hMatrix, (POS_tdstCompletePosition *) POS_g_p_stIdentityMatrix);
/*END FB*/
		MTH3D_M_vSetVectorElements ( &stI, xCos, xSin, MTH_C_ZERO );
		MTH3D_M_vSetVectorElements ( &stJ, MTH_M_xNeg(xSin), xCos, MTH_C_ZERO );
		MTH3D_M_vSetBaseKVector ( &stK );
 
		POS_fn_vSetRotationMatrix ( hMatrix, &stI, &stJ, &stK );
		POS_fn_vMulMatrixMatrix ( hCurrentMatrix, hMatrix, hCurrentMatrix );
 
/*FB030898*/
		/*POS_fn_vSetTranslationVector ( hCurrentMatrix, &stMove );*/
		MTH3D_M_vCopyVector( &(hCurrentMatrix->stTranslationVector), &stMove );
/*END FB*/
		return;
	}
/*FB030898*/
	/*POS_fn_vGetTranslationVector ( hCurrentMatrix, &stMove );*/
	MTH3D_M_vCopyVector(&stMove, &(hCurrentMatrix->stTranslationVector) );
/*END FB*/
	MTH3D_M_vSetVectorElements ( &stVectorZ, MTH_C_ZERO, MTH_C_ZERO, MTH_C_MinusONE );
	POS_fn_vRotatePositionAroundAxis (hCurrentMatrix, &stVectorZ, xAngle);
/*FB030898*/
	/*POS_fn_vSetTranslationVector ( hCurrentMatrix, &stMove );*/
	MTH3D_M_vCopyVector( &(hCurrentMatrix->stTranslationVector), &stMove );
/*END FB*/
}
 
void MEC_vTurnAbsolute
( 	
	struct DNM_stDynamics *p_stDynamic,
	MTH3D_tdstVector* p_stVector 
)
{
	POS_tdxHandleToPosition hCurrentMatrix;
	MTH3D_tdstVector *p_stI, *p_stJ, *p_stK;
	
	if (DNM_M_bDynamicsIsInit(p_stDynamic)) return;
	if (MTH3D_M_bIsNullVector(p_stVector)) return;
 
	hCurrentMatrix = DNM_M_p_stDynamicsGetCurrentMatrix (p_stDynamic);
 
	POS_fn_vGetRotationVector (hCurrentMatrix,&p_stI,&p_stJ,&p_stK);
 
	MTH3D_M_vNormalizeVector ( p_stJ,p_stVector);
	MTH3D_M_vNegVector ( p_stJ, p_stJ );
	MTH3D_M_vCrossProductVector (p_stI,p_stJ,p_stK);
	MTH3D_M_vCrossProductVector (p_stJ,p_stK,p_stI);
	MEC_fn_vUpdateMatrix ( p_stDynamic, hCurrentMatrix );
	if (DNM_M_bDynamicsIsComplexSize(p_stDynamic)) MEC_fn_vCancelTilt (p_stDynamic);
}
 

void DNM_fn_vSetHangingLimit 
(
	struct DNM_stDynamics *p_stDynamic,
	MTH_tdxReal xValue
)
{
	if (MEC_fn_bIsPlatform(p_stDynamic))
		DNM_M_vDynamicsSetHangingLimit (p_stDynamic,MTH_M_xSub ( xValue, MTH3D_M_xGetZofVector(POS_fn_p_stGetTranslationVector(HIE_fn_hGetSuperObjectGlobalMatrix(DNM_M_hDynamicsGetPlatformSO(p_stDynamic)))) ) );
	else
		DNM_M_vDynamicsSetHangingLimit (p_stDynamic,xValue);
}


/* Update speed for camera */
void MEC_fn_vUpdateSpeed (HIE_tdxHandleToSuperObject hSupObj)
{
	MS_tdxHandleToDynam h_Dynam;
	struct DNM_stDynamics *p_stDynamic;
	MTH3D_tdstVector *p_stSpeed;
	POS_tdxHandleToPosition hPreviousMatrix; 
	MTH3D_tdstVector *p_stCurrentX, *p_stCurrentY, *p_stCurrentZ;
	MTH3D_tdstVector stPreviousY;
	MTH3D_tdstVector stAxis;
	MTH3D_tdstVector  stCrossProduct;
	MTH_tdstMove* p_stMove; 
	MTH_tdxReal xDotProd, xAngle;

	h_Dynam = M_GetMSHandle(hSupObj,Dynam);
	if (!h_Dynam) return;
	p_stDynamic = fn_p_stDynamGetDynamics(h_Dynam);
	if ( !DNM_M_bDynamicsIsComplexSize(p_stDynamic) || !DNM_M_bDynamicsIsCollisionReport(p_stDynamic) ) return; 

	p_stSpeed = DNM_M_pDynamicsGetPreviousSpeed (p_stDynamic);
	hPreviousMatrix = DNM_M_p_stDynamicsGetPreviousMatrix (p_stDynamic);

	/* Update Dynamic Report speed linear -> to keep speed variable in IA */ 
	/* to CB's camera */

	POS_fn_vGetRotationVector ( hPreviousMatrix, &p_stCurrentX, &p_stCurrentY, &p_stCurrentZ );

	p_stMove = DNM_M_p_stReportGetAbsoluteCurrSpeed ( DNM_M_p_stDynamicsGetReport (p_stDynamic) );
	MTH3D_M_vCopyVector (&stPreviousY,MTH_M_p_stRotationGetAxis(MTH_M_p_stMoveGetAngular(p_stMove)));	

	xDotProd = MTH3D_M_xDotProductVector (&stPreviousY,p_stCurrentY);
	MTH3D_M_vCrossProductVectorWithoutBuffer (&stCrossProduct, &stPreviousY, p_stCurrentY);

	/* check |xDotProd|<=1 */
	xDotProd = MTH_M_xMin ( MTH_M_xMax ( xDotProd, MTH_C_MinusONE ), MTH_C_ONE );

	if (MTH_M_bGreater(MTH3D_M_xGetZofVector(&stCrossProduct),MTH_C_ZERO)) xAngle = MTH_M_xACos (xDotProd);
	else xAngle = MTH_M_xNeg (MTH_M_xACos(xDotProd));

	MTH3D_M_vSetBaseKVector (&stAxis);
	MTH_M_MoveSetAngularPosition ( p_stMove, xAngle, &stAxis );
}



 
	
