/*
 *=======================================================================================
 * Name        : MecTools.c
 * Author      : J Thénoz               Date : 01/05/98
 * Description : Mechanic tools funstions
 *=======================================================================================
 */



#ifndef _MECTOOLS_H_
#define _MECTOOLS_H_

#ifdef __cplusplus
extern "C" {
#endif

/* only to compile inline functions */
#include "Mecdef.h"
#include "col\CollGoCo.h"


/* Dynamics */
#pragma warning (disable : 4706)    // There are some voluntary assignment inside this function
INLINE
ACP_tdxBool MEC_fn_bIsBaseMechanic (struct DNM_stDynamics *p_stDynamic)
{
	register DNM_tdxHandleToMecIdentityCard hIdCard;
	return (ACP_tdxBool)(( ((hIdCard = DNM_M_pDynamicsGetCurrentIdCard (p_stDynamic)) != 0) && hIdCard && (DNM_fn_eIdentityCardGetType(hIdCard)==DNM_eBase)));
}
#pragma warning (default : 4706)

INLINE
MTH_tdxReal MEC_fn_xMinSlope (struct DNM_stDynamics *p_stDynamic)
{
	return MTH_M_xNeg (DNM_M_xDynamicsGetSlopeLimit(p_stDynamic));
}

INLINE
MTH_tdxReal MEC_fn_xMaxSlope (struct DNM_stDynamics *p_stDynamic)
{
	return DNM_M_xDynamicsGetSlopeLimit(p_stDynamic);
}

INLINE
MTH_tdxReal MEC_fn_xGroundLimit (struct DNM_stDynamics *p_stDynamic)
{
	return DNM_M_xDynamicsGetCosSlope (p_stDynamic);
}

INLINE
MTH_tdxReal MEC_fn_xWallLimit (struct DNM_stDynamics *p_stDynamic)
{
	return MTH_M_xNeg ( DNM_M_xDynamicsGetCosSlope (p_stDynamic) );;
}

INLINE
ACP_tdxBool MEC_fn_bIsPlatform (struct DNM_stDynamics *p_stDynamic)
{
	return (ACP_tdxBool)(HIE_fn_bIsSuperObjectValid (DNM_M_hDynamicsGetPlatformSO(p_stDynamic)));
}


INLINE
ACP_tdxBool MEC_fn_bIsScale (struct DNM_stDynamics *p_stDynamic)
{
	return (ACP_tdxBool)(!MTH_M_bEqualWithEpsilon (DNM_M_p_stDynamicsGetScaleX(p_stDynamic), MTH_C_ONE, C_xDNM_MTH_EPSILON)
		|| !MTH_M_bEqualWithEpsilon (DNM_M_p_stDynamicsGetScaleY(p_stDynamic), MTH_C_ONE, C_xDNM_MTH_EPSILON)
		|| !MTH_M_bEqualWithEpsilon (DNM_M_p_stDynamicsGetScaleZ(p_stDynamic), MTH_C_ONE, C_xDNM_MTH_EPSILON));
}


INLINE
void MEC_fn_vComputeSlopeLimit (struct DNM_stDynamics *p_stDynamic)
{
	register MTH_tdxReal xSlopeLimit = MTH_M_xSqrt (MTH_M_xDiv (MTH_C_ONE,MTH_M_xAdd(MTH_C_ONE,MTH_M_xSqr(DNM_M_xDynamicsGetSlopeLimit(p_stDynamic)))));
	DNM_M_vDynamicsSetCosSlope ( p_stDynamic, xSlopeLimit );
}



/* Material */
INLINE
ACP_tdxBool MEC_fn_bTypeOfGameMaterial(GMT_tdxHandleToGameMaterial hGameMat, GMT_tdxMask xTestMask)
{
	register GMT_tdxHandleToCollideMaterial hCollMat;
	return (ACP_tdxBool)( ((hCollMat=hGameMat->hCollideMaterial)!=(GMT_tdxHandleToCollideMaterial)GMT_C_InvalidCollideMaterial) && (hCollMat->xIdentifier&xTestMask)==xTestMask );
}

INLINE
ACP_tdxBool MEC_fn_bTestMaskGameMaterial(GMT_tdxHandleToGameMaterial hGameMat, GMT_tdxMask xTestMask)
{
	register GMT_tdxHandleToCollideMaterial hCollMat;
	return (ACP_tdxBool)( ((hCollMat=hGameMat->hCollideMaterial)!=(GMT_tdxHandleToCollideMaterial)GMT_C_InvalidCollideMaterial) && (hCollMat->xIdentifier&xTestMask)!=MTH_C_ZERO );
}


/* Normal */
ACP_tdxBool MEC_fn_bWallNormal (struct DNM_stDynamics *p_stDynamic, MTH3D_tdstVector* p_stNormal);
ACP_tdxBool MEC_fn_bGroundNormal (struct DNM_stDynamics *p_stDynamic, MTH3D_tdstVector* p_stNormal);

/* Obstacle */
INLINE
ACP_tdxBool MEC_fn_bIsEdge (DNM_tdstMecObstacle *p_stObstacle)
{
	return 	(ACP_tdxBool)((DNM_M_xObstacleGetCollidedEntity(p_stObstacle)==COL_C_xHighEdgeEntity) || (DNM_M_xObstacleGetCollidedEntity(p_stObstacle)==COL_C_xLowEdgeEntity));
}

INLINE
ACP_tdxBool MEC_fn_bIsHighEdge (DNM_tdstMecObstacle *p_stObstacle)
{
	return 	(ACP_tdxBool)(DNM_M_xObstacleGetCollidedEntity(p_stObstacle)==COL_C_xHighEdgeEntity);
}

INLINE
ACP_tdxBool MEC_fn_bIsLowEdge (DNM_tdstMecObstacle *p_stObstacle)
{
	return 	(ACP_tdxBool)(DNM_M_xObstacleGetCollidedEntity(p_stObstacle)==COL_C_xLowEdgeEntity);
}

INLINE
ACP_tdxBool MEC_fn_bIsWater (DNM_tdstMecObstacle *p_stObstacle) 
{
	return 	(ACP_tdxBool)(MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetCollidedMaterial(p_stObstacle),C_xDNM_WATER_TYPE_GAME_MATERIAL)
		&& MEC_fn_bTypeOfGameMaterial (DNM_M_hObstacleGetMyMaterial(p_stObstacle),C_xDNM_WATER_TYPE_GAME_MATERIAL));
}

INLINE
ACP_tdxBool  MEC_fn_bIsCollide (DNM_tdstMecObstacle *p_stObstacle)
{
	return (ACP_tdxBool) MTH_M_bLess ( DNM_M_xObstacleGetRate(p_stObstacle), MTH_C_ZERO );
}

INLINE
ACP_tdxBool MEC_fn_bIsDoubleEdge (DNM_tdstMecObstacle *p_stObstacle)
{
	return (ACP_tdxBool) (( DNM_M_eObstacleGetType(p_stObstacle)&DNM_ObsType_DoubleEdge ) == DNM_ObsType_DoubleEdge);
}


/* this obstacle is a wall ? */
INLINE
ACP_tdxBool MEC_fn_bWallObstacle (struct DNM_stDynamics *p_stDynamic, DNM_tdstMecObstacle *p_stObstacle)
{
	return MEC_fn_bWallNormal (p_stDynamic,DNM_M_p_stObstacleGetNorm (p_stObstacle));
}


/* this obstacle is a ground ? */
INLINE
ACP_tdxBool MEC_fn_bGroundObstacle (struct DNM_stDynamics *p_stDynamic, DNM_tdstMecObstacle *p_stObstacle)
{
	return MEC_fn_bGroundNormal (p_stDynamic,DNM_M_p_stObstacleGetNorm (p_stObstacle));
}

ACP_tdxBool MEC_fn_bCeilObstacle (struct DNM_stDynamics *p_stDynamic, DNM_tdstMecObstacle *p_stObstacle);
ACP_tdxBool MEC_fn_bIsStatic (long lObstacle, DNM_tdstMecObstacle *p_stObstacle);
void MEC_fn_vAddObstacleList (long *p_lObstacle, DNM_tdstMecObstacle *p_stObstacle, long lAddObstacle, DNM_tdstMecObstacle *p_stAddObstacle);
ACP_tdxBool MEC_fn_bCanCrashActor (DNM_tdstMecObstacle* p_stCollideObstacle);

INLINE
void MEC_fn_vInvalidateObstacle ( DNM_tdstMecObstacle *p_stObstacle )
{
	DNM_M_xObstacleSetCollidedEntity ( p_stObstacle, COL_C_xNoEntity );
}

INLINE
ACP_tdxBool MEC_fn_bIsObstacleValid ( DNM_tdstMecObstacle *p_stObstacle )
{
	return (ACP_tdxBool)(DNM_M_xObstacleGetCollidedEntity(p_stObstacle)!=COL_C_xNoEntity);
}

INLINE
ACP_tdxBool MEC_fn_bIsObstacleSphere ( DNM_tdstMecObstacle *p_stObstacle )
{
	return (ACP_tdxBool)(DNM_M_xObstacleGetCollidedEntity(p_stObstacle)==COL_C_xSphereEntity);
}

/* Collision */
BOOL MEC_fn_bDynamicsNeedCollide (struct DNM_stDynamics *p_stDynamic);
MTH_tdxReal MEC_fn_xGetSlide (struct DNM_stDynamics *p_stDynamic,DNM_tdstMecObstacle *p_stObstacle);
MTH_tdxReal MEC_fn_xGetRebound (struct DNM_stDynamics *p_stDynamic,DNM_tdstMecObstacle *p_stObstacle);
void MEC_fn_vComputeCollisionTranslation ( long lObstacle, DNM_tdstMecObstacle *p_stObstacle, MTH3D_tdstVector* p_stMove );
void MEC_fn_vDeleteWallEdge (long lObstacle, DNM_tdstMecObstacle *p_stObstacle, DNM_tdstDynamics *p_stDynamic);
void MEC_fn_vDeleteUnderGroundWall (long lObstacle, DNM_tdstMecObstacle *p_stObstacle, DNM_tdstDynamics *p_stDynamic, DNM_tdstMecObstacle *p_stGroundObstacle);
DNM_tdstMecObstacle* MEC_fn_pSelectGround (struct DNM_stDynamics *p_stDynamic, long lObstacle, DNM_tdstMecObstacle *p_stObstacle,ACP_tdxBool *bFirstGround);
ACP_tdxBool MEC_fn_bDetectStep (struct DNM_stDynamics *p_stDynamic, long lObstacle, DNM_tdstMecObstacle *p_stObstacle, DNM_tdstMecObstacle *p_stGroundObstacle, MTH3D_tdstVector* p_stMoveDirection);


INLINE
void MEC_fn_vGetCollisionTranslation (struct DNM_stDynamics *p_stDynamic, POS_tdxHandleToPosition hMatrix)
{
	POS_fn_vSetTranslationVector ( hMatrix, DNM_M_pDynamicsGetCollisionTranslation(p_stDynamic) );
}

INLINE
void MEC_fn_vRegisterCollisionTranslation (struct DNM_stDynamics *p_stDynamic, POS_tdxHandleToPosition hMatrix)
{
	DNM_M_vDynamicsSetCollisionTranslation ( p_stDynamic, POS_fn_p_stGetTranslationVector ( hMatrix ) );
}

/* Speed*/
void MEC_fn_vComputeSpeed (struct DNM_stDynamics *p_stDynamic, MTH_tdxReal xDT);

/* Matrix */
void MEC_fn_vInitMatrix (DNM_tdstDynamics *p_stDynamic);
void MEC_fn_vCorrectMatrix (struct DNM_stDynamics *p_stDynamic, POS_tdxHandleToPosition hMatrix);
ACP_tdxBool MEC_fn_bIsEqualMatrix (POS_tdxHandleToPosition hMatrix1, POS_tdxHandleToPosition hMatrix2);
ACP_tdxBool MEC_fn_bIsEqualRotationMatrix (POS_tdxHandleToPosition hMatrix1, POS_tdxHandleToPosition hMatrix2);
ACP_tdxBool MEC_fn_bIsEqualTransformMatrix (POS_tdxHandleToPosition hMatrix1, POS_tdxHandleToPosition hMatrix2);
void MEC_fn_vTranslateMatrixOn (struct DNM_stDynamics *p_stDynamic,MTH3D_tdstVector* p_stMatrixTranslation);
void MEC_fn_vTranslateMatrixOff (struct DNM_stDynamics *p_stDynamic,MTH3D_tdstVector* p_stMatrixTranslation);
void MEC_fn_vUpdateMatrix (struct DNM_stDynamics *p_stDynamic,POS_tdxHandleToPosition _hMatrix);

INLINE
void MEC_fn_vInvertMatrix (struct DNM_stDynamics *p_stDynamic,POS_tdxHandleToPosition hInvMatrix, POS_tdxHandleToPosition hMatrix)
{
	if (DNM_M_bDynamicsIsComputeInvertMatrix(p_stDynamic))
	{
		POS_fn_vInvertMatrix ( hInvMatrix, hMatrix );
		DNM_M_vDynamicsSetComputeInvertMatrix ( p_stDynamic, FALSE );
	}
}



/* Adjust */
void MEC_fn_vAdjustStaticVector (struct DNM_stDynamics *p_stDynamic,MTH3D_tdstVector *p_stVector);
void MEC_fn_vAdjustStaticMove (struct DNM_stDynamics *p_stDynamic,MTH3D_tdstVector *p_stMove);
void MEC_fn_vAdjustStaticMatrix (struct DNM_stDynamics *p_stDynamic,POS_tdxHandleToPosition hMatrix);
void MEC_fn_vAdjustScaleVector (struct DNM_stDynamics *p_stDynamic,MTH3D_tdstVector* p_stVector);
void MEC_fn_vAdjustSpeed (struct DNM_stDynamics* p_stDynamic, MTH_tdxReal xDT);

/* Mth */
MTH_tdxReal MEC_fn_vRoundReal (MTH_tdxReal xReal, MTH_tdxReal xEpsilon);
void MEC_fn_vRoundVector (MTH3D_tdstVector* p_stVector, MTH_tdxReal xEpsilon);
INLINE
ACP_tdxBool MEC_fn_bIsNullVector ( MTH3D_tdstVector* p_stVector)
{
	return (ACP_tdxBool)(
		MTH_M_bEqualWithEpsilon ( MTH3D_M_xGetXofVector(p_stVector), MTH_C_ZERO, MTH_M_xDoubleToReal(1e-3) )
	&&	MTH_M_bEqualWithEpsilon ( MTH3D_M_xGetYofVector(p_stVector), MTH_C_ZERO, MTH_M_xDoubleToReal(1e-3) )
	&&	MTH_M_bEqualWithEpsilon ( MTH3D_M_xGetZofVector(p_stVector), MTH_C_ZERO, MTH_M_xDoubleToReal(1e-3) ));

}
MTH_tdxReal MEC_fn_xConvertScale ( MTH_tdxReal xValue );
ACP_tdxBool MEC_fn_bVectorParallel ( MTH3D_tdstVector* p_stVector1, MTH3D_tdstVector* p_stVector2 );
void MEC_fn_vCheckMinVectorNorm ( MTH3D_tdstVector* p_stVector, MTH_tdxReal xLimit );

/* BackFaces */
void MEC_fn_vDeleteBaseBackFace ( long lObstacle, DNM_tdstMecObstacle *p_stObstacle, struct DNM_stDynamics* p_stDynamic );
void MEC_fn_vDeleteOnGroundBackFace ( long lObstacle, DNM_tdstMecObstacle *p_stObstacle, struct DNM_stDynamics* p_stDynamic, MTH3D_tdstVector* p_stVector, DNM_tdstMecObstacle *p_stGroundObstacle );
void MEC_fn_vDeleteGiBackFace ( long lObstacle, DNM_tdstMecObstacle *p_stObstacle, struct DNM_stDynamics* p_stDynamic, MTH3D_tdstVector* p_stVector );
void MEC_fn_vDeleteClimbBackFace ( long lObstacle, DNM_tdstMecObstacle *p_stObstacle, struct DNM_stDynamics* p_stDynamic, MTH3D_tdstVector* p_stVector );
void MEC_fn_vDeleteBaseBackFace ( long lObstacle, DNM_tdstMecObstacle *p_stObstacle, struct DNM_stDynamics* p_stDynamic );

/* Ground Faces */
void  MEC_fn_vDeleteNoCollidedGroundFace ( long lObstacle, DNM_tdstMecObstacle *p_stObstacle, struct DNM_stDynamics* p_stDynamic );

/* Delete Faces for Hanging mechanic */
void MEC_fn_vDeleteHangingObstacle ( long lObstacle, DNM_tdstMecObstacle *p_stObstacle, struct DNM_stDynamics* p_stDynamic );

void MEC_fn_vDeleteObstacleBehind ( long lObstacle, DNM_tdstMecObstacle *a_stObstacle, DNM_tdstMecObstacle *p_stObstacle );

void MEC_fn_vDeleteNullTranslationObstacle ( long lObstacle, DNM_tdstMecObstacle *a_stObstacle );

/* Hierarchy */
HIE_tdxHandleToSuperObject MEC_fn_hGetFatherActor (HIE_tdxHandleToSuperObject hSupObj);

/* Frame */
void MEC_fn_vComputeInitialFrameTranslation ( MTH3D_tdstVector *p_stVector, struct DNM_stDynamics *p_stDynamic, long lFrame);
void MEC_fn_vSetInitialFrameTranslation ( struct DNM_stDynamics *p_stDynamic, MTH3D_tdstVector* p_stVector);

/* Stream */
void MEC_fn_vComputeStream ( MTH3D_tdstVector *p_stStream, struct DNM_stDynamics *p_stDynamic, 	MTH_tdxReal xDT, ACP_tdxBool bSlide);

/* Inertia */
void MEC_fn_vComputeInertiaTranslation ( struct DNM_stDynamics *p_stDynamic, MTH_tdxReal xDT );

/* actor */
ACP_tdxBool MEC_fn_bIsMultiCollision (HIE_tdxHandleToSuperObject hSupObj);
ACP_tdxBool MEC_fn_bMainActor (HIE_tdxHandleToSuperObject hSupObj);


/* optimization */
ACP_tdxBool MEC_fn_bNoMove (struct DNM_stDynamics *p_stDynamic);

/* safe position */
void MEC_fn_vAdjustSafeTranslation (struct DNM_stDynamics *p_stDynamic);
void MEC_fn_vRegisterSafeTranslation (struct DNM_stDynamics *p_stDynamic, POS_tdxHandleToPosition hMatrix);


/* secure mode */
void MEC_fn_vSlowMode (struct DNM_stDynamics *p_stDynamic, long lMode);
void MEC_fn_vNormalMode (struct DNM_stDynamics *p_stDynamic, long lMode);
void MEC_fn_vRepeatMove (struct DNM_stDynamics *p_stDynamic);


#ifdef __cplusplus
}
#endif



#endif //_MECTOOLS_H_


