/*ANNECY CB Attention, tout a été modifié dans ce fichier !!!*/
 
#include "ACP_base.h"
#include "GMT.h"
#include "GEO.h"
#include "GLI.h"
#include "PCS.h"
#include "COL.h"
#include "lst.h"
#include "PO.h"
 
#include "FIL.h"
#include "snd.h"
#include "gld.h"
#include "mec.h"
#ifdef USE_IPT_DX5
#include "IPT_DX5.h" /* InPuT (absolutely before GAM.h)*/
#else /* USE_IPT_WIN */
#include "IPT.h" /* InPuT (absolutely before GAM.h)*/
#endif /* USE_IPT_WIN */
#include "sct.h"
#ifndef D_THROW_PRT
#include "PRT.h"
#endif /* D_THROW_PRT */
#include "gam.h"
#include "tmr.h"
/*XB980821*/
#ifndef D_THROW_IPO
#include "IPO.h"
#endif /* D_THROW_IPO */
/*End XB*/
#undef extern
 
#include "SPO/HieConst.h"
#include "LST.h"
#include "SPO/HieSpObj.h"
#include "SPO/HieHand.h"
#include "SPO/HieDef.h"
#include "SPO/HieMacro.h"
#include "SPO/HieMtStk.h"
#include "SPO/HieExt.h"
#include "SPO/HiePick.h"
/*HP 180698*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
MTH_tdxReal				VoidReal;
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
ACP_tdxHandleOfObject	GeoHandle;
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
#ifndef D_THROW_VISUAL_SET
#define M_hGetFirstLodOfVisualSetFromPo(Po)		(GLI_vGetVisualSetLOD(PO_fn_hGetVisualSet(Po), 0, &VoidReal, &GeoHandle), GeoHandle)
#define M_hGetRepositionZoneFromPo(Po)			(GLI_vGetVisualSetLOD(PO_fn_hGetVisualSet(Po), 0, &VoidReal, &GeoHandle), GeoHandle)
#else
#define M_hGetFirstLodOfVisualSetFromPo(Po)		PO_fn_hGetGeometricObject(Po)
#define M_hGetRepositionZoneFromPo(Po)			PO_fn_hGetGeometricObject(Po)
#endif /* D_THROW_VISUAL_SET */
 
extern BOOL fn_bIsEditorsActive(void);
 
extern unsigned long fn_ulStandardGameGetCustomBitsSO (HIE_tdxHandleToSuperObject hSupObj);
 
extern ACP_tdxHandleOfObject fn_hMakeOneObjectFromManyZdx (unsigned char _ucZoneType, HIE_tdxHandleToSuperObject _hCharacter);
 
 
unsigned long g_ulSpoMask = 0;
/*
 *=================================================================================================
 *=================================================================================================
 */
#ifdef ACTIVE_EDITOR
/* active editor only*/
static ACP_tdxBool fn_bIsBoundingVolumeIntersect
(
	GEO_tdxHandleToMatrix			_p_stCurrentMatrix,
	MTH3D_tdstVector		*		_p_stVertexA,
	MTH3D_tdstVector		*		_p_stVectAB,
	GEO_tdxHandleToBoundingSphere	_hBoundingSphere
)
{
	MTH3D_tdstVector	stGlobalSphereCenter;
	MTH_tdxReal			xScaledRadius;
 
	MTH3D_M_vMulMatrixVector(&stGlobalSphereCenter, &_p_stCurrentMatrix->stRotationMatrix, GEO_fn_pGetCenterPointOfBoundingSphere(_hBoundingSphere));
	MTH3D_M_vAddVector(&stGlobalSphereCenter, &_p_stCurrentMatrix->stTranslationVector, &stGlobalSphereCenter);
 
	xScaledRadius = GEO_fn_xGetRadiusOfBoundingSphere(_hBoundingSphere) * POS_fn_xGetMaxScale(_p_stCurrentMatrix);
 
	return INT_fn_bDetectIntersectSemiAxeWithSphere (_p_stVertexA, _p_stVectAB, &stGlobalSphereCenter, xScaledRadius);
}
#endif
 
/* used*/
ACP_tdxBool fn_bDetectIntersectSegmentWithBoundingSphere
(
	GEO_tdxHandleToMatrix			_p_stCurrentMatrix,
	MTH3D_tdstVector		*		_p_stVertexA,
	MTH3D_tdstVector		*		_p_stVectAB,
	GEO_tdxHandleToBoundingSphere	_hBoundingSphere
)
{
 
	MTH3D_tdstVector	stGlobalSphereCenter;
	MTH_tdxReal			xScaledRadius;
 
	MTH3D_M_vMulMatrixVector(&stGlobalSphereCenter, &_p_stCurrentMatrix->stRotationMatrix, GEO_fn_pGetCenterPointOfBoundingSphere(_hBoundingSphere));
	MTH3D_M_vAddVector(&stGlobalSphereCenter, &_p_stCurrentMatrix->stTranslationVector, &stGlobalSphereCenter);
 
	xScaledRadius = GEO_fn_xGetRadiusOfBoundingSphere(_hBoundingSphere) * POS_fn_xGetMaxScale(_p_stCurrentMatrix);
 
	return INT_fn_bDetectIntersectSegmentWithSphere (_p_stVertexA, _p_stVectAB, &stGlobalSphereCenter, xScaledRadius);
}
 
 
/*
 *=================================================================================================
 *=================================================================================================
 */
 
#ifdef ACTIVE_EDITOR
/* active editor only*/
static ACP_tdxIndex fn_xIntersectSemiAxeWithRepositioningSuperObject
(
	GLI_tdeModePicking			xModePicking,
    MTH3D_tdstVector			*p_stVertexA,
    MTH3D_tdstVector			*p_stVertexB,
    MTH3D_tdstVector			*p_stVectAB,
    HIE_tdxHandleToSuperObject	_hSprObj,
    HIE_tdstPickInfo			*p_stPickInfo ,
    ACP_tdxIndex				*p_xNbPickInfo
	)
{
	static GEO_tdxHandleToBoundingSphere	hBoundingSphere;
	static GEO_tdxHandleToParallelBox		hParallelBox;
	static ACP_tdxHandleOfObject			hSentObject;
	static MTH3D_tdstVector					stMinPoint;
	static MTH3D_tdstVector					stMaxPoint;
	static ACP_tdxBool						bBoxBoundingVolume,bIntersect;
	ACP_tdxIndex							i;
	static long								lType,lCustomBits;
	HIE_tdxHandleToSuperObject				hChild;
	static MTH3D_tdstVector					stVertexALocal, stVectAB;
	static POS_tdstCompletePosition			stInvMatrix;
	static GLI_tdstPickedObject				stPickedObject;
 
 
	/* eliminate every object that must be ignored...*/
	if (HIE_fn_SO_bIsNotPickable( _hSprObj ))
	{
		return *p_xNbPickInfo;
	}
	
	lType=HIE_fn_ulGetSuperObjectType(_hSprObj);
	
	/* we test if the character is rayman (has the custombit 32)*/
	/* we also ignore the character if he can't be hit by ray tracing.*/
    /* we also ignore inactive characters*/
    if (lType==HIE_C_ulActor)
    {
		lCustomBits = fn_ulStandardGameGetCustomBitsSO(_hSprObj);
        if ( !(lCustomBits & GAM_C_CustBitRayHit) ||  /* not hit by ray tracing*/
             !(fn_bf1StandardGameGetIsActive(M_GetMSHandle(_hSprObj,StandardGame))) ||  /* inactive*/
			 (lCustomBits & (1<<31)) )  /* Rayman*/
        {
            return *p_xNbPickInfo;
        }
    }
	
	/* ok, now we can pick*/
	hBoundingSphere = NULL;
	hParallelBox = NULL;
	hSentObject = NULL;
 
	HIE_fn_vPushMatrix (_hSprObj);
	
	/* do we have a bounding sphere or a bounding box ??*/
	bBoxBoundingVolume = HIE_fn_SO_bHasABoxBoundingVolume(_hSprObj);
	
	if(bBoxBoundingVolume)
	{
		/* this is a BOX !! */
		hParallelBox = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
		if (hParallelBox)
		{
			/* the box realy exists, compute its 2 points in world coordinates*/
			MTH3D_tdstVector	*p_stMinPoint;
			MTH3D_tdstVector	*p_stMaxPoint;
			MTH3D_tdstVector	stTranslation;
			
			p_stMinPoint = GEO_fn_pGetMinPointOfParallelBox(hParallelBox);
			p_stMaxPoint = GEO_fn_pGetMaxPointOfParallelBox(hParallelBox);
			stTranslation = (HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj))->stTranslationVector;
			
			MTH3D_M_vAddVector(&stMinPoint, p_stMinPoint , &stTranslation);
			MTH3D_M_vAddVector(&stMaxPoint, p_stMaxPoint , &stTranslation);
		}
	}
	else
	{
		/* this is a SPHERE, get it*/
		hBoundingSphere = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
	}
 
	/* test intersection*/
	if (!hBoundingSphere && !hParallelBox)
	{
		/* if there are no bounding volume at all (no box nor sphere) --> go further*/
		bIntersect = TRUE;
	}
	else if (!bBoxBoundingVolume)
	{
		/* if there is a BV Sphere, seek an intersect between the sphere and the axe*/
		bIntersect = fn_bIsBoundingVolumeIntersect(HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj), p_stVertexA, p_stVectAB, hBoundingSphere);
	}
	else 
	{
		/*if there is a BV Box, seek an intersect between the box and the axe */
		bIntersect = INT_fn_bDetectIntersectSemiAxeWithBox(p_stVertexA, p_stVertexB, p_stVectAB, &stMinPoint, &stMaxPoint);
	}
 
	if(bIntersect)
	{
		if( lType & (HIE_C_ulEDT_Geometric | HIE_C_ulMirror))
		{
			hSentObject = (ACP_tdxHandleOfObject)HIE_fn_hGetSuperObjectObject(_hSprObj);
		} 
		else if( lType & (HIE_C_ulPO | HIE_C_ulPO_Mirror))
		{
			PCS_tdxHandleToPhysicalCollSet hCollSet = PO_fn_hGetCollideSet((PO_tdxHandleToPhysicalObject) HIE_fn_hGetSuperObjectObject (_hSprObj)); /*AR9809*/
			hSentObject = hCollSet ? PCS_fn_hGetZdrGeoObjOfPhysicalCollSet (hCollSet) : NULL;
		}
#ifndef D_THROW_IPO
		else if( lType & (HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
		{
			PCS_tdxHandleToPhysicalCollSet hCollSet = PO_fn_hGetCollideSet (IPO_fn_hGetPhysicalObject
				((IPO_tdxHandleToInstanciatedPhysicalObject) HIE_fn_hGetSuperObjectObject (_hSprObj)));
			hSentObject = hCollSet ? PCS_fn_hGetZdrGeoObjOfPhysicalCollSet (hCollSet) : NULL;
		}
#endif
		else if( lType == HIE_C_ulActor )
		{
			hSentObject=fn_hMakeOneObjectFromManyZdx(C_ucTypeZdr, _hSprObj);
		}
 
		/* intersection test*/
        if (hSentObject)
		{
			/* convertion local coordinate system*/
			POS_fn_vInvertMatrix(&stInvMatrix, g_p_stCurrentMatrix);
 
			MTH3D_M_vMulMatrixVectorWithoutBuffer(&stVectAB, &(stInvMatrix.stTransformMatrix), p_stVectAB);
			MTH3D_M_vAddVector(&stVectAB, &(stInvMatrix.stTranslationVector), &stVectAB);
			
			MTH3D_M_vMulMatrixVectorWithoutBuffer(&stVertexALocal, &(stInvMatrix.stTransformMatrix), p_stVertexA);
			MTH3D_M_vAddVector(&stVertexALocal, &(stInvMatrix.stTranslationVector), &stVertexALocal);
			
			if (PIC_bIntersectSemiAxeWithGeometricObject (xModePicking,&stVertexALocal,&stVectAB,hSentObject,&stPickedObject))
			{
				ACP_tdxIndex    i;
				
				i=(*p_xNbPickInfo)-1;
				while( (i >= 0) && (stPickedObject.aDEF_stDataOfElement[0].xDistance
					< p_stPickInfo[i].stPickedObject.aDEF_stDataOfElement[0].xDistance) )
				{
					if ( i < (HIE_C_DepthPickingObjects-1) )
						p_stPickInfo[i+1] = p_stPickInfo[i];
					i--;
				}
				
				if ( i < (HIE_C_DepthPickingObjects-1) )
				{
					p_stPickInfo[i+1].stPickedObject = stPickedObject;
					p_stPickInfo[i+1].hSprObject = _hSprObj;
					p_stPickInfo[i+1].hGeoObject=hSentObject;
					if ( (*p_xNbPickInfo) < HIE_C_DepthPickingObjects )
						(*p_xNbPickInfo)++;
				}
			}
		}
	}
			
	if (bIntersect || HIE_fn_SO_bCheckChildren(_hSprObj))
	{
		/* node examination*/
		HIE_M_ForEachChildOf(_hSprObj, hChild, i)
		{
			/* recurence*/
			fn_xIntersectSemiAxeWithRepositioningSuperObject(xModePicking,
				p_stVertexA,
				p_stVertexB,
				p_stVectAB,
				hChild,
				p_stPickInfo,
				p_xNbPickInfo);
		}
	}
	HIE_fn_vPopMatrix ();
	return *p_xNbPickInfo;
}
#endif /* ACTIVE_EDITOR*/
 
/*
 *=================================================================================================
 *=================================================================================================
 */
#ifdef ACTIVE_EDITOR
 /* active editor only*/
ACP_tdxIndex fn_xIntersectSemiAxeWithVisualSuperObject
(
	GLI_tdeModePicking			xModePicking,
    MTH3D_tdstVector			*p_stVertexA,
    MTH3D_tdstVector			*p_stVertexB,
    MTH3D_tdstVector			*p_stVectAB,
    HIE_tdxHandleToSuperObject	_hSprObj,
    HIE_tdstPickInfo			*p_stPickInfo ,
    ACP_tdxIndex				*p_xNbPickInfo
)
{
	ACP_tdxHandleOfObject			hSentObject = NULL;
	ACP_tdxIndex					i;
	HIE_tdxHandleToSuperObject	hChild;
	long							lType;
 
	HIE_fn_vPushMatrix(_hSprObj);
 
	lType=HIE_fn_ulGetSuperObjectType(_hSprObj);
 
	{
		if (
			HIE_fn_SO_bIsNotPickable( _hSprObj )
#ifdef ACTIVE_EDITOR
			&& !fn_bIsEditorsActive()
#endif
			)
		{
			HIE_fn_vPopMatrix ();
			return *p_xNbPickInfo;
		}
 
		if( lType & (HIE_C_ulEDT_Geometric | HIE_C_ulPO | HIE_C_ulIPO | HIE_C_ulMirror| HIE_C_ulPO_Mirror | HIE_C_ulIPO_Mirror))
		{
			MTH3D_tdstVector stVertexALocal, stVertexBLocal, stVectAB;
			POS_tdstCompletePosition stInvMatrix;
			GLI_tdstPickedObject stPickedObject;
 
			/* convertion loacal coordinate system*/
 
			POS_fn_vInvertMatrix(&stInvMatrix, g_p_stCurrentMatrix);/*!!!*/
 
			POS_fn_vMulMatrixVertex(&stVertexALocal, &stInvMatrix, p_stVertexA);
			POS_fn_vMulMatrixVertex(&stVertexBLocal, &stInvMatrix, p_stVertexB);
			MTH3D_M_vSubVector(&stVectAB, &stVertexBLocal, &stVertexALocal);
 
			if(lType & (HIE_C_ulEDT_Geometric | HIE_C_ulMirror))
				hSentObject=(ACP_tdxHandleOfObject)HIE_fn_hGetSuperObjectObject(_hSprObj);
 
			if(lType & (HIE_C_ulPO | HIE_C_ulPO_Mirror))
				hSentObject=M_hGetFirstLodOfVisualSetFromPo((PO_tdxHandleToPhysicalObject)HIE_fn_hGetSuperObjectObject(_hSprObj));
/*XB980821*/
#ifndef D_THROW_IPO
			if(lType & (HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
				hSentObject=M_hGetFirstLodOfVisualSetFromPo(IPO_fn_hGetPhysicalObject((IPO_tdxHandleToInstanciatedPhysicalObject)HIE_fn_hGetSuperObjectObject(_hSprObj)));
#endif /* D_THROW_IPO */
/*End XB*/
 
			/* intersection test*/
			if( PIC_bIntersectSemiAxeWithGeometricObject(xModePicking,
				&stVertexALocal,
				/*                                                   &stVertexBLocal,*/
				&stVectAB,
				hSentObject,
				&stPickedObject) )
			{ /* l'objet est sous la souris*/
				ACP_tdxIndex i;
 
				i=(*p_xNbPickInfo)-1;
				while( (i >= 0) && (stPickedObject.aDEF_stDataOfElement[0].xDistance
					< p_stPickInfo[i].stPickedObject.aDEF_stDataOfElement[0].xDistance) )
				{
					if ( i < (HIE_C_DepthPickingObjects-1) )
						p_stPickInfo[i+1] = p_stPickInfo[i];
					i--;
				}
 
				if ( i < (HIE_C_DepthPickingObjects-1) )
				{
					p_stPickInfo[i+1].stPickedObject = stPickedObject;
					p_stPickInfo[i+1].hSprObject = _hSprObj;
					p_stPickInfo[i+1].hGeoObject=hSentObject;
					if ( (*p_xNbPickInfo) < HIE_C_DepthPickingObjects )
						(*p_xNbPickInfo)++;
				}
			}
		}
 
		/* node examination*/
		HIE_M_ForEachChildOf(_hSprObj, hChild, i)
		{
			/* recurence*/
			fn_xIntersectSemiAxeWithVisualSuperObject(xModePicking,
				p_stVertexA,
				p_stVertexB,
				p_stVectAB,
				hChild,
				p_stPickInfo,
				p_xNbPickInfo);
		}
	}
	HIE_fn_vPopMatrix ();
	return *p_xNbPickInfo;
}
#endif /* ACTIVE_EDITOR*/
/*
 *=================================================================================================
 *=================================================================================================
 */
#ifdef ACTIVE_EDITOR
/* active editor only*/
ACP_tdxIndex HIE_xIsSuperObjectPick
(
	GLI_tdeModePicking			xModePicking,
    GLD_tdhDevice				hDev,
	GLD_tdhViewport				hVp,
    GLI_tdst2DVertex			*p_stSouris2D,
	HIE_tdxHandleToSuperObject	hSprObj,
    HIE_tdstPickInfo			*p_stPickInfo
)
{
	MTH3D_tdstVector stSouris3D, stVertex12, stCameraPos;
	ACP_tdxIndex xNbPickInfo=0;
 
	/* calcul des positions 3d de la camera et de la souris dans le repere global*/
	PIC_vGetPosCamAndMouse(hDev, hVp, p_stSouris2D, &stSouris3D, &stCameraPos);
	MTH3D_M_vSubVector(&stVertex12, &stSouris3D, &stCameraPos);
 
	return fn_xIntersectSemiAxeWithVisualSuperObject
	(
		xModePicking,
		&stCameraPos,
		&stSouris3D,
		&stVertex12,
		hSprObj,
		p_stPickInfo,
		&xNbPickInfo
	);
}
#endif
/*
 *=================================================================================================
 *=================================================================================================
 */
#ifdef ACTIVE_EDITOR
/* active editor only*/
ACP_tdxIndex HIE_bIntersectSemiAxeWithSuperObject
(
	GLI_tdeModePicking			xModePicking,
    MTH3D_tdstVector			*p_stVertexA,
	MTH3D_tdstVector			*p_stVertexB,
	MTH3D_tdstVector			*p_stVectAB,
	HIE_tdxHandleToSuperObject	hSprObj,
    HIE_tdstPickInfo			*p_stPickInfo
)
{
	ACP_tdxIndex	xNbPickInfo = 0;
	ACP_tdxIndex	iRet;
 
	HIE_fn_bLoadIdentity();
 
	iRet = fn_xIntersectSemiAxeWithRepositioningSuperObject
	(
		xModePicking,
		p_stVertexA,
		p_stVertexB,
		p_stVectAB,
		hSprObj,
		p_stPickInfo,
		&xNbPickInfo
	);
 
	HIE_fn_vPopMatrix();
	return iRet;
}
#endif
/*
 *=================================================================================================
 *=================================================================================================
 */
 
/*
 *=================================================================================================
 *=================================================================================================
 */
/* used*/
static ACP_tdxIndex fn_xIntersectSegmentWithRepositioningSuperObject
(
	MTH3D_tdstVector			*p_stVertexA,
	MTH3D_tdstVector			*p_stVectAB,
	HIE_tdxHandleToSuperObject	_hSprObj,
    HIE_tdstPickInfo			*p_stPickInfo ,
    ACP_tdxIndex				*p_xNbPickInfo
)
{
	static GEO_tdxHandleToBoundingSphere	hBoundingSphere;
	static GEO_tdxHandleToParallelBox		hParallelBox;
	static ACP_tdxHandleOfObject			hSentObject;
	static MTH3D_tdstVector					stMinPoint;
	static MTH3D_tdstVector					stMaxPoint;
	static ACP_tdxBool						bBoxBoundingVolume,bIntersect;
	ACP_tdxIndex							i;
/* XB 05/05/99 */
	/* static long								lType,lCustomBits; */
	static long								lType;
/* End XB 05/05/99 */
	HIE_tdxHandleToSuperObject				hChild;
	static MTH3D_tdstVector					stVertexALocal, stVectAB;
	static POS_tdstCompletePosition			stInvMatrix;
	static GLI_tdstPickedObject				stPickedObject;
	register unsigned long					ulSpoFlags;
 
	ulSpoFlags = HIE_M_xGetSuperObjectMember(_hSprObj,ulFlags);
 
	/* eliminate every object that has the No_Collision flag*/
	if (ulSpoFlags & HIE_C_Flag_ulNotPickable)
	{
		return *p_xNbPickInfo;
	}
	
	lType=HIE_fn_ulGetSuperObjectType(_hSprObj);
 
	/* if object is not an actor, check the flags with the given mask...*/
	/* else, check the custom bit */
	if (lType != HIE_C_ulActor)
	{
		if (ulSpoFlags & g_ulSpoMask)
			return *p_xNbPickInfo;
	}
	else
	{
		if (!fn_ulStandardGameGetCustomBitsSO(_hSprObj) & GAM_C_CustBitShadowOnMe)
		{
			return *p_xNbPickInfo;
		}
	}
 
	hBoundingSphere = NULL;
	hParallelBox = NULL;
	hSentObject = NULL;
 
	HIE_fn_vPushMatrix(_hSprObj);
 
	/* do we have a bounding sphere or a bounding box ??*/
	bBoxBoundingVolume = (unsigned char)(ulSpoFlags & HIE_C_Flag_ulTypeOfBoundingVolume);
	
	if(bBoxBoundingVolume)
	{
		/* this is a BOX !! */
		hParallelBox = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
		if (hParallelBox)
		{
			/* the box realy exists, compute its 2 points in world coordinates*/
			MTH3D_tdstVector	*p_stMinPoint;
			MTH3D_tdstVector	*p_stMaxPoint;
			MTH3D_tdstVector	stTranslation;
			
			p_stMinPoint = GEO_fn_pGetMinPointOfParallelBox(hParallelBox);
			p_stMaxPoint = GEO_fn_pGetMaxPointOfParallelBox(hParallelBox);
			stTranslation = (HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj))->stTranslationVector;
			
			MTH3D_M_vAddVector(&stMinPoint, p_stMinPoint , &stTranslation);
			MTH3D_M_vAddVector(&stMaxPoint, p_stMaxPoint , &stTranslation);
		}
	}
	else
	{
		/* this is a SPHERE, get it*/
		hBoundingSphere = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
	}
 
	/* test intersection*/
	if (!hBoundingSphere && !hParallelBox)
	{
		/* if there are no bounding volume at all (no box nor sphere) --> go further*/
		bIntersect = TRUE;
	}
	else if (!bBoxBoundingVolume)
	{
		/* if there is a BV Sphere, seek an intersect between the sphere and the axe*/
		bIntersect = fn_bDetectIntersectSegmentWithBoundingSphere(HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj), p_stVertexA, p_stVectAB, hBoundingSphere);
	}
	else 
	{
		/*if there is a BV Box, seek an intersect between the box and the axe */
		bIntersect = INT_fn_bDetectIntersectSegmentWithBox(p_stVertexA, p_stVectAB, &stMinPoint, &stMaxPoint,NULL);
	}
 
	
	if(bIntersect)
	{
		/* we found an intersection between the segment and the bounding volume --> let's see if we must get down to the faces*/
#ifndef U64	/* no editor objects on u64*/
		if( lType & (HIE_C_ulEDT_Geometric | HIE_C_ulMirror))
		{
			hSentObject = (ACP_tdxHandleOfObject)HIE_fn_hGetSuperObjectObject(_hSprObj);
		} 
		else
#endif		
		if( lType & (HIE_C_ulPO | HIE_C_ulPO_Mirror))
		{
			PCS_tdxHandleToPhysicalCollSet hCollSet = PO_fn_hGetCollideSet((PO_tdxHandleToPhysicalObject) HIE_fn_hGetSuperObjectObject (_hSprObj)); /*AR9809*/
			hSentObject = hCollSet ? PCS_fn_hGetZdrGeoObjOfPhysicalCollSet (hCollSet) : NULL;
		}
#ifndef D_THROW_IPO
		else if( lType & (HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
		{
			PCS_tdxHandleToPhysicalCollSet hCollSet = PO_fn_hGetCollideSet (IPO_fn_hGetPhysicalObject
				((IPO_tdxHandleToInstanciatedPhysicalObject) HIE_fn_hGetSuperObjectObject (_hSprObj)));
			hSentObject = hCollSet ? PCS_fn_hGetZdrGeoObjOfPhysicalCollSet (hCollSet) : NULL;
		}
#endif
		else if( lType == HIE_C_ulActor )
		{
			hSentObject=fn_hMakeOneObjectFromManyZdx(C_ucTypeZdr, _hSprObj);
		}
 
        if (hSentObject)
		{
			/* the detected objetc is relevant, let's see if there is a collision with its faces...*/
			/*Convertion local coordinate system.*/
			if (ulSpoFlags & HIE_C_Flag_ulNoTransformationMatrix)
			{
				/* Only translation, compute A i local*/
				MTH3D_M_vSubVector (&stVertexALocal , p_stVertexA , &_hSprObj->hGlobalMatrix->stTranslationVector);
				/* and nothing for the vector AB...*/
				MTH3D_M_vCopyVector(&stVectAB,p_stVectAB);
			}
			else
			{
				POS_fn_vInvertMatrix(&stInvMatrix,_hSprObj->hGlobalMatrix);
/*				MTH3D_M_vTranspMatrixWithoutBuffer(&stInvMatrix,&_hSprObj->hGlobalMatrix->stRotationMatrix);*/
				
				/* here, stVectAB is used only as a temporary variable and has no meaning...*/
				/* compute A in local coordinates*/
/*				MTH3D_M_vSubVector (&stVectAB , p_stVertexA , &_hSprObj->hGlobalMatrix->stTranslationVector);*/
/*				MTH3D_M_vMulMatrixVectorWithoutBuffer(&stVertexALocal, &stInvMatrix, &stVectAB);*/
				POS_fn_vMulMatrixVertex(&stVertexALocal,&stInvMatrix, p_stVertexA);
 
				/* compute AB in local coordinates*/
				POS_fn_vMulMatrixVector(&stVectAB, &stInvMatrix, p_stVectAB);
 
/*				MTH3D_M_vMulMatrixVectorWithoutBuffer(&stVectAB, &stInvMatrix, p_stVectAB);*/
			}
			
			if (PIC_bIntersectSegmentWithGeometricObject (&stVertexALocal,&stVectAB,hSentObject,&stPickedObject))
			{
				/* yes, we got an intersection !!*/
				/* if it is the first one, then remember it*/
				if (*p_xNbPickInfo == 0)
				{
					/* first one !*/
					p_stPickInfo[0].stPickedObject = stPickedObject;
					p_stPickInfo[0].hSprObject = _hSprObj;
					p_stPickInfo[0].hGeoObject = hSentObject;
					*p_xNbPickInfo = 1;
					/* and reduce the lenght of the segment */
					MTH3D_M_vSubVector(p_stVectAB, &(stPickedObject.aDEF_stDataOfElement[0].stHit),p_stVertexA);
				}
				else
				{
					/* there has already been a collision in this search, so check distance*/
					/* compare this detection with the previous one*/
					if (stPickedObject.aDEF_stDataOfElement[0].xDistance < p_stPickInfo[0].stPickedObject.aDEF_stDataOfElement[0].xDistance)
					{
						/* ok, the new one is nearer*/
						/* lets remember the data*/
						p_stPickInfo[0].stPickedObject = stPickedObject;
						p_stPickInfo[0].hSprObject = _hSprObj;
						p_stPickInfo[0].hGeoObject = hSentObject;
						/* and reduce the lenght of the segment */
						MTH3D_M_vSubVector(p_stVectAB, &(stPickedObject.aDEF_stDataOfElement[0].stHit),p_stVertexA);
					}
				}
			}
		}
	}
	/* keep going on the sons of this SO */
	if (bIntersect || HIE_fn_SO_bCheckChildren(_hSprObj))
	{
		HIE_M_ForEachChildOf(_hSprObj, hChild, i)
		{
			/* recurence*/
			fn_xIntersectSegmentWithRepositioningSuperObject
				(
				p_stVertexA,
				p_stVectAB,
				hChild,
				p_stPickInfo,
				p_xNbPickInfo
				);
		}
	}
	HIE_fn_vPopMatrix ();
	return *p_xNbPickInfo;
}
 
/*
 *=================================================================================================
 *=================================================================================================
 */
/* used*/
ACP_tdxIndex HIE_bIntersectSegmentWithSuperObject
(
    MTH3D_tdstVector			*p_stVertexA,
    MTH3D_tdstVector			*p_stVectAB,
    HIE_tdxHandleToSuperObject	hSprObj,
    HIE_tdstPickInfo			*p_stPickInfo
)
{
	ACP_tdxIndex xNbPickInfo = 0, xReturnValue;
	
	HIE_fn_bLoadIdentity();
	xReturnValue = fn_xIntersectSegmentWithRepositioningSuperObject
	(
		p_stVertexA,
		p_stVectAB,
		hSprObj,
		p_stPickInfo,
		&xNbPickInfo
	);
 
	HIE_fn_bPopMatrix();
 
	return xReturnValue; 
}
 
 
 
 
/*
 *=================================================================================================
 *=================================================================================================
 */
/* used*/
/* compute the intersection between the segment [A, A+AB], and the hSprObj and its descendants*/
ACP_tdxBool HIE_bIntersectSegmentWithFirstSuperObject(MTH3D_tdstVector				*_p_stVertexA,
													  MTH3D_tdstVector				*_p_stVectAB,
													  HIE_tdxHandleToSuperObject	hSprObj,
													  MTH3D_tdstVector				*_p_stHit,
													  MTH3D_tdstVector				*_p_stNormal,
													  HIE_tdxHandleToSuperObject	*_p_hSprObjHit
													 )
{
	HIE_aDEF_stTabOfPickInfo	aDEF_stIntersInfo;
	GEO_tdstGeometricObject		*p_stGeomObj;
	GLI_tdstDataOfElement		*p_stDataOfElement;
	MTH3D_tdstVector			stNormal;
	long                        lType;
 
 
	if( HIE_bIntersectSegmentWithSuperObject(_p_stVertexA,_p_stVectAB,hSprObj,aDEF_stIntersInfo) > 0)
	{
		/* detection !!!*/
		p_stGeomObj = aDEF_stIntersInfo[0].hGeoObject;
		p_stDataOfElement = &(aDEF_stIntersInfo[0].stPickedObject.aDEF_stDataOfElement[0]);
 
		lType = HIE_fn_ulGetSuperObjectType(aDEF_stIntersInfo[0].hSprObject);
 
		if(lType & (HIE_C_ulEDT_Geometric | HIE_C_ulPO | HIE_C_ulMirror | HIE_C_ulPO_Mirror | HIE_C_ulActor | HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
		{
			*_p_hSprObjHit = aDEF_stIntersInfo[0].hSprObject;
		}
		else
		{
			*_p_hSprObjHit = NULL;
		}
 
		MTH3D_M_vCopyVector( _p_stHit, &(p_stDataOfElement->stHit));
 
		if (_p_hSprObjHit && p_stGeomObj->d_xListOfElementsTypes[p_stDataOfElement->xElements] == GEO_C_xElementSpheres)
		{
			MTH3D_tdstVector         stSphereCenter;
			/* Get the sphere element*/
			GEO_tdstElementSpheres * p_stElementSpheres = (GEO_tdstElementSpheres *) p_stGeomObj->d_stListOfElements[p_stDataOfElement->xElements];
			/* The normal is the vector from the center of the sphere to the hit point (in the global axis)*/
			POS_fn_vMulMatrixVertex (& stSphereCenter,
								     HIE_fn_hGetSuperObjectGlobalMatrix(* _p_hSprObjHit),
								     & p_stGeomObj->d_stListOfPoints[p_stElementSpheres->d_stListOfSpheres[p_stDataOfElement->xIndexOfFace].xCenterPoint]);
			MTH3D_M_vSubVector       (_p_stNormal, _p_stHit, & stSphereCenter);
			MTH3D_M_vNormalizeVector (_p_stNormal, _p_stNormal);
		}
		else
		{
			GEO_vGetNormalOfGeometricObjectElement(p_stGeomObj,p_stDataOfElement->xElements,p_stDataOfElement->xIndexOfFace,&stNormal);
			POS_fn_vMulMatrixVector(_p_stNormal, HIE_fn_hGetSuperObjectGlobalMatrix(* _p_hSprObjHit), &stNormal);
			/* don't forget to normalize in case the target had scale... */
			MTH3D_M_vNormalizeVector (_p_stNormal, _p_stNormal);
		}
 
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}
 
 
/*
 ******************************************************************************************************
 ******************************************************************************************************
 ******************************************************************************************************
 ******************************************************************************************************
 */
 
 
/*
 *=================================================================================================
 *	Picking function for camera.
 *=================================================================================================
 */
/* used*/
ACP_tdxBool HIE_bDetectIntersectSegmentWithSuperObject
(
	MTH3D_tdstVector			*p_stVertexA,
    MTH3D_tdstVector			*p_stVectAB,
    HIE_tdxHandleToSuperObject	_hSprObj 
	)
{
	static GEO_tdxHandleToBoundingSphere	hBoundingSphere;
	static GEO_tdxHandleToParallelBox		hParallelBox;
	static MTH3D_tdstVector					stMinPoint;
	static MTH3D_tdstVector					stMaxPoint;
	static MTH3D_tdstVector					*p_stTranslation;
	static ACP_tdxBool						bBoxBoundingVolume,bIntersect;
	static ACP_tdxHandleOfObject			hSentObject;
	ACP_tdxIndex							i;
	HIE_tdxHandleToSuperObject				hChild;
	static long								lType;
/* XB 05/05/99 */
/* 	static MTH3D_tdstVector					stVertexALocal, stVertexBLocal, stVectAB; */
	static MTH3D_tdstVector					stVertexALocal, stVectAB;
/* End XB 05/05/99 */
	static POS_tdstCompletePosition			stInvMatrix;

 
 
	hBoundingSphere = NULL;
	hParallelBox = NULL;
	hSentObject = NULL;
 
	p_stTranslation = &_hSprObj->hGlobalMatrix->stTranslationVector;
	bBoxBoundingVolume = HIE_fn_SO_bHasABoxBoundingVolume(_hSprObj);
	
	if(bBoxBoundingVolume)
	{
		hParallelBox = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
		if (hParallelBox)
		{
			MTH3D_tdstVector	*p_stMinPoint;
			MTH3D_tdstVector	*p_stMaxPoint;
			
			/* get the min and max points in world coordinates*/
			p_stMinPoint = GEO_fn_pGetMinPointOfParallelBox(hParallelBox);
			p_stMaxPoint = GEO_fn_pGetMaxPointOfParallelBox(hParallelBox);
			
			MTH3D_M_vAddVector(&stMinPoint, p_stMinPoint , p_stTranslation);
			MTH3D_M_vAddVector(&stMaxPoint, p_stMaxPoint , p_stTranslation);					 
		}
	}
	else	
	{
		/* get the bounding sphere*/
		hBoundingSphere = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume(_hSprObj);
	}
	
	/* test intersection*/
	if (!hBoundingSphere && !hParallelBox)
	{
		/* if there are no bounding volume at all (no box nor sphere) --> go further*/
		bIntersect = TRUE;
	}
	else if (!bBoxBoundingVolume)
	{
		/* if there is a BV Sphere, seek an intersect between the sphere and the axe*/
		bIntersect = fn_bDetectIntersectSegmentWithBoundingSphere(HIE_fn_hGetSuperObjectGlobalMatrix(_hSprObj), p_stVertexA, p_stVectAB, hBoundingSphere);
	}
	else 
	{
		/*if there is a BV Box, seek an intersect between the box and the axe */
		bIntersect = INT_fn_bDetectIntersectSegmentWithBox(p_stVertexA, p_stVectAB, &stMinPoint, &stMaxPoint,NULL);
	}
 
	
	if(bIntersect)
	{
		lType = HIE_fn_ulGetSuperObjectType(_hSprObj);
			
#ifndef U64	/* no editor objects on u64*/
		if( lType & (HIE_C_ulEDT_Geometric | HIE_C_ulMirror	)) 
		{
			hSentObject = (ACP_tdxHandleOfObject)HIE_fn_hGetSuperObjectObject(_hSprObj);
		}
		else
#endif		
		if( lType & (HIE_C_ulPO | HIE_C_ulPO_Mirror))
		{
			hSentObject = M_hGetRepositionZoneFromPo((PO_tdxHandleToPhysicalObject)HIE_fn_hGetSuperObjectObject(_hSprObj));
		}
#ifndef D_THROW_IPO
		else if( lType & (HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
		{
			hSentObject = M_hGetRepositionZoneFromPo(IPO_fn_hGetPhysicalObject((IPO_tdxHandleToInstanciatedPhysicalObject)HIE_fn_hGetSuperObjectObject(_hSprObj)));
		}
#endif /* D_THROW_IPO */
		else if (lType == HIE_C_ulActor)
		{
			hSentObject = fn_hMakeOneObjectFromManyZdx(C_ucTypeZdr,_hSprObj);
		}
 
		if (hSentObject)
		{
			/*Convertion local coordinate system.*/
			if (HIE_fn_SO_bHasNoTransformationMatrix (_hSprObj))
			{
				/* Only translation, compute A i local*/
				MTH3D_M_vSubVector (&stVertexALocal , p_stVertexA , p_stTranslation);
				/* and nothing for the vector AB...*/
				MTH3D_M_vCopyVector(&stVectAB,p_stVectAB);
			}
			else
			{
				POS_fn_vInvertMatrix(&stInvMatrix,_hSprObj->hGlobalMatrix);
				/* compute A in local coordinates*/
				POS_fn_vMulMatrixVertex(&stVertexALocal,&stInvMatrix, p_stVertexA);
				/* compute AB in local coordinates*/
				POS_fn_vMulMatrixVector(&stVectAB, &stInvMatrix, p_stVectAB);
			}
	
			/*
			*	Intersection test.
			*/
			if( INT_fn_bDetectIntersectSegmentWithFaceOfGeometricObject(&stVertexALocal, &stVectAB, hSentObject))
			{
				return TRUE;
			}
		}
	}

	if (bIntersect || HIE_fn_SO_bCheckChildren(_hSprObj))
	{
		/* keep going on the sons of this SO, only if they are not actors */
		HIE_M_ForEachChildOf(_hSprObj, hChild, i)
		{
			if( (HIE_fn_ulGetSuperObjectType(hChild) != HIE_C_ulActor) &&
				 (HIE_bDetectIntersectSegmentWithSuperObject(p_stVertexA,p_stVectAB,hChild))
			  )
			{
				return TRUE;
			}
		}
	}
	return FALSE;
}
 
/*
 *=================================================================================================
 *=================================================================================================
 */
