 
/************************************************************************************************
 *                                                                                              *
 *  Collisio.c                                                                                  *
 *                                                                                              *
 *  High level collision functions                                                              *
 *                                                                                              *
 *                                                                                              *
 ************************************************************************************************/
 
 
#include "ToolsCPA.h"
 
#include "Options/Options.h"
#include "Macros.h"
 
#include "Actions/AllActs.h"
 
#include "structur/objects.h"
#include "STRUCTUR/StdObjSt.h"
#include "Structur/EngMode.h"
#include "Collisio.h"
 
#include "GameEng.h"
#include "ZdxStuff.h"
#include "ToolCam.h"
#include "PhysiCol.h"
#include "Family.h"
#include "PO.h"
#include "ChanList.h"
#include "always.h"
#include "mainchar.h"
#include "PRF.h"
 
 
#define C_wStaticObject       0
#define C_wMobileObject       1
 
/* ANNECY AV {*/
#define C_ulCustomBit_Projectile  0x00000008
/* END ANNECY AV }*/
 
#define C_xHalfSqr3 MTH_M_xDoubleToReal(.8660254037844)
 

/* jt 260599 */
long COL_g_lMaxNumberOfCollisions = COL_C_xMaxNumberOfCollisions;

/* anthony */
extern COL_tdstCollisionCase COL_g_stCollisionCase [COL_C_xMaxNumberOfCollisions];

extern COL_tdstCollisionCase *COL_g_stCollisionCaseReal;
extern long COL_g_lNbElementsInTable;

extern ACP_tdxBool HISPEED;
/* end anthony*/


/* end jt 260599 */
 
/*-----------------------------------------------------------------------------*/
/* fn_eGetLimbTypeFromGameMaterial*/
/*-----------------------------------------------------------------------------*/
/*DNM_tdeLimbType fn_eGetLimbTypeFromGameMaterial (GMT_tdxHandleToGameMaterial _hGMT)
{
   if( GMT_fn_xMultipleTestCollideIdentifierFromGameMaterial(_hGMT,GMT_C_uwPieds) )         return DNM_eLTFoot;
   else if( GMT_fn_xMultipleTestCollideIdentifierFromGameMaterial(_hGMT,GMT_C_uwCorps) )    return DNM_eLTTrunk;
   else if( GMT_fn_xMultipleTestCollideIdentifierFromGameMaterial(_hGMT,GMT_C_uwTete) )     return DNM_eLTHead;
   else if( GMT_fn_xMultipleTestCollideIdentifierFromGameMaterial(_hGMT,GMT_C_uwMains) )    return DNM_eLTHand;
   else                                                                                     return DNM_eLTError;
}*/
 
/*-----------------------------------------------------------------------------*/
/* fn_bIsGeometricObjectValidForCollision*/
/*-----------------------------------------------------------------------------*/
ACP_tdxBool fn_bIsGeometricObjectValidForCollision (ACP_tdxHandleOfObject _hGeoObj)
{
   /* IMPORTANT : if the geometric objet has no point, it is not necessary to call the collision*/
   return (ACP_tdxBool) (GEO_xGetGeometricObjectNumberOfPoints(_hGeoObj) >= 1);
}
 
/*-----------------------------------------------------------------------------*/
/* COL_lHaveITakeSThgIntoTheMug*/
/**/
/* The main function for the collisions :*/
/* Test the collision between one super object and the rest of the world*/
/*-----------------------------------------------------------------------------*/
/* used*/
long COL_lHaveITakeSThgIntoTheMug(DNM_tdstMecObstacle        _a_stResultObstacle [COL_C_xMaxNumberOfCollisions] ,
                                  HIE_tdxHandleToSuperObject _p_stSupObj ,
                                  POS_tdstCompletePosition * _p_stStartPosition ,
                                  POS_tdstCompletePosition * _p_stEndPosition)
{
   static MTH_tdxReal xSlideCoef   = MTH_C_ZERO;
   static MTH_tdxReal xReboundCoef = MTH_C_ZERO;
 
/*   ACP_tdxBool                bCollision;*/

   ACP_tdxIndex               i;
   MTH3D_tdstVector *         p_stAxis = DNM_M_p_stObstacleGetNorm(& _a_stResultObstacle [0]);
   MTH3D_tdstVector           stDummy;
   long                       lResult = 0;
   long						  lParameter2 = 0;
/*   COL_tdstCollisionCase      a_stCollisionCase [COL_C_xMaxNumberOfCollisions];*/

/*   COL_tdstCollisionCase *    p_stCollisionCase; */

   DNM_tdxHandleToMecMatCharacteristics hCollidedMechanicMaterial;
   DNM_tdstMecMatCharacteristics *p_stMechanicMaterial;
 
#if defined(USE_PROFILER) && !defined(PRESS_DEMO)
   unsigned char ucDNMRunning , ucIARunning;
   void          *p_vCurrentAIData  = NULL;
   void          *p_vCurrentDNMData = NULL;
 
   ucDNMRunning = (unsigned char) (( PRF_fn_iGetFunctionNumberOfStart( PRF_C_ulFctDNM, &p_vCurrentDNMData ) > 0 ) ? 1 : 0);
   ucIARunning =  (unsigned char) (( PRF_fn_iGetFunctionNumberOfStart( PRF_C_ulFctAI,  &p_vCurrentAIData ) > 0 ) ? 1 : 0);
 
   if( ucDNMRunning )
	   PRF_fn_vStopChrono( PRF_C_ulFctDNM, p_vCurrentDNMData );
   if( ucIARunning  )
	   PRF_fn_vStopChrono( PRF_C_ulFctAI,  p_vCurrentAIData );
 
   PRF_fn_vStartChrono( PRF_C_ulFctCollisions, _p_stSupObj );
#endif
 
   MTH3D_M_vSetVectorElements(&stDummy,MTH_C_ZERO,MTH_C_ZERO,MTH_M_xFloatToReal(0.1f));
 
   /* NOCLIP Ghost Mode*/
   if(g_ucIsEdInGhostMode && CAM_fn_bSuperObjectIsACamera(_p_stSupObj))
   {
/*      DNM_M_eObstacleSetType(& _a_stResultObstacle [0] ,DNM_ObsType_Nothing);*/
      DNM_M_eObstacleSetType(& _a_stResultObstacle [0] ,0);
#if defined(USE_PROFILER) && !defined(PRESS_DEMO)
      PRF_fn_vStopChrono( PRF_C_ulFctCollisions, _p_stSupObj );
 
      if( ucDNMRunning )
		  PRF_fn_vStartChrono( PRF_C_ulFctDNM, p_vCurrentDNMData );
      if( ucIARunning  )
		  PRF_fn_vStartChrono( PRF_C_ulFctAI,  p_vCurrentAIData );
#endif
      return 0;
   }
 
   /* Dealing whit changes of sectors*/
	 /*prabaly useless, because the sector in which we are new is most certainly in the collision list of our current sector,*/
	 /*and will be tested for collisions anyway...*/
   /*GAM_fn_vSectInfoTestChangeSectorForCharacter(_p_stSupObj);  */
 
   /* If character has a Collision Set and has at least one Zdm*/
   if (M_GetMSHandle (_p_stSupObj , CollSet) && CS_fn_hGetZdxList (C_ucTypeZdm , _p_stSupObj))
   {
      /* Do collision computation*/
/*			COL_tdstCollisionCase *p_stCurrentCollisionCase;*/
			DNM_tdstMecObstacle *p_stCurrentResultObstacle;

		/* Warning anthony */
		COL_g_stCollisionCaseReal = (COL_tdstCollisionCase *)_a_stResultObstacle; /* replace bcollision = COL_fn_bGetMultipleResultCollision (& p_stCollisionCase);*/
 
       /* Test the collisions with all zones (hand and no hand)*/

	  /*if (!HISPEED)*/ COL_fn_vInitCollisionTable();
 
      COL_fn_vNewStaticCollisionForCharacter (_p_stSupObj, fn_h_SectInfoGetCurrentSector(M_GetMSHandle(_p_stSupObj,SectInfo)), _p_stStartPosition, _p_stEndPosition);
 
      /*bCollision = COL_fn_bGetMultipleResultCollision (& p_stCollisionCase);*/
	

      for
			(
				i = 0, /*p_stCurrentCollisionCase = p_stCollisionCase, */ p_stCurrentResultObstacle = _a_stResultObstacle;
				i < COL_g_lNbElementsInTable; /*COL_g_lMaxNumberOfCollisions;*/
				i ++, /*p_stCurrentCollisionCase ++,*/ p_stCurrentResultObstacle ++
			) 
          /* if (p_stCurrentCollisionCase->bCollisionState) */
          {
 
/* comment by jt 071098*/
/*             DNM_M_p_stObstacleSetDNMObject(p_stCurrentResultObstacle, NULL);*/
  
			lParameter2 = ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->sParameter2;		
										
			/* In case of collision between two characters*/
//			 if( (((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->sParameter2 & 0x1) == C_wMobileObject )
			 if( (lParameter2 & 0x1) == C_wMobileObject )
             {
                HIE_tdxHandleToSuperObject hSOInCollision;
 
                hSOInCollision = (HIE_tdxHandleToSuperObject)((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->p_vParameter1;
                DNM_M_eObstacleSetType(p_stCurrentResultObstacle, DNM_ObsType_Mobile);
                /* Add this test in case of global ZDR*/
 
/* comment by jt 071098*/
/*               	if( HIE_fn_ulGetSuperObjectType(hSOInCollision)==HIE_C_ulActor )
                {
                   if((h_Dynam = M_GetMSHandle(hSOInCollision,Dynam)) != NULL )
                      if((p_stDynamics = fn_p_stDynamGetDynamics(h_Dynam)) != NULL)
                         DNM_M_p_stObstacleSetDNMObject(p_stCurrentResultObstacle, p_stDynamics);
                }
                else
                {
					hFather = HIE_fn_hGetSuperObjectFather(hSOInCollision);
					if(HIE_fn_bIsSuperObjectValid(hFather))
						if(HIE_fn_ulGetSuperObjectType(hFather) == HIE_C_ulActor)
							if((h_Dynam = M_GetMSHandle(hFather,Dynam)) != NULL )
								if((p_stDynamics = fn_p_stDynamGetDynamics(h_Dynam)) != NULL)
									DNM_M_p_stObstacleSetDNMObject(p_stCurrentResultObstacle, p_stDynamics);
                }*/
             }
             else DNM_M_eObstacleSetType(p_stCurrentResultObstacle, DNM_ObsType_Scenery);
 
 
/* jt 060199*/
			 /* double edge report */
//			 if ( ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->sParameter2 & 0x2 )
			 if ( lParameter2 & 0x2 )
				DNM_M_eObstacleSetType ( p_stCurrentResultObstacle, DNM_M_eObstacleGetType(p_stCurrentResultObstacle) | DNM_ObsType_DoubleEdge );
/* end jt*/
 
             /* Partie collisionnée */
             if(((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->hStaticMaterial != NULL)
             {
                hCollidedMechanicMaterial = GMT_fn_hGetMechanicsMaterial( ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->hStaticMaterial );
 
                if(DNM_fn_bIsMatCharacteristicsValid(hCollidedMechanicMaterial))
                {
			       p_stMechanicMaterial = DNM_fn_p_stMecMatCharacteristicsGiveBackSemantic(hCollidedMechanicMaterial);
		
				   DNM_M_xObstacleSetSlide(p_stCurrentResultObstacle, DNM_M_xMatCharacteristicsGetSlide(p_stMechanicMaterial));
                   DNM_M_xObstacleSetRebound(p_stCurrentResultObstacle, DNM_M_xMatCharacteristicsGetRebound(p_stMechanicMaterial));
			    }
                else
                {
                   DNM_M_xObstacleSetSlide(p_stCurrentResultObstacle, xSlideCoef);
                   DNM_M_xObstacleSetRebound(p_stCurrentResultObstacle, xReboundCoef);
 
                }
             }
             else
             {
                DNM_M_xObstacleSetSlide(p_stCurrentResultObstacle, xSlideCoef);
                DNM_M_xObstacleSetRebound(p_stCurrentResultObstacle, xReboundCoef);
 
             }
 
			/* anthony */
             /*DNM_M_p_stObstacleSetObject(p_stCurrentResultObstacle, (HIE_tdxHandleToSuperObject)((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->p_vParameter1);
             DNM_M_vObstacleSetCollidedMaterial(p_stCurrentResultObstacle, ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->hStaticMaterial);
             DNM_M_vObstacleSetMyMaterial(p_stCurrentResultObstacle, ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->hDynamicMaterial);
             DNM_M_xObstacleSetMyEntity(p_stCurrentResultObstacle, ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->xDynamicGeomEntity);
             DNM_M_xObstacleSetCollidedEntity(p_stCurrentResultObstacle, ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->xStaticGeomEntity);*/
			/*anthony end */

/*            if( p_stCurrentCollisionCase->hDynamicMaterial )*/
/*                  DNM_M_eObstacleSetLimbType(p_stCurrentResultObstacle, fn_eGetLimbTypeFromGameMaterial(p_stCurrentCollisionCase->hDynamicMaterial));*/
/*             else DNM_M_eObstacleSetLimbType(p_stCurrentResultObstacle, DNM_eLTDefault);*/
 
				/* anthony */
            /* p_stAxis = DNM_M_p_stObstacleGetNorm(p_stCurrentResultObstacle);
             *p_stAxis = ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->stCollisionNormal;
             p_stAxis = DNM_M_p_stObstacleGetContact(p_stCurrentResultObstacle);
             *p_stAxis = ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->stCollisionPoint;
             DNM_M_xObstacleSetRate(p_stCurrentResultObstacle,((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->xCollisionTime);
 
             DNM_M_xObstacleSetTranslation  (p_stCurrentResultObstacle, & ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->stTranslation);
             DNM_M_xObstacleSetZoneMove     (p_stCurrentResultObstacle, & ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->stMovement);
             DNM_M_xObstacleSetZoneRadius   (p_stCurrentResultObstacle,   ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->xSphereRadius);
             DNM_M_xObstacleSetZonePosition (p_stCurrentResultObstacle, & ((COL_tdstCollisionCase *)p_stCurrentResultObstacle)->stEndPosition);*/
 
             lResult = i + 1;
          }    /* End if (p_stCurrentCollisionCase->bCollisionState)*/
         /* else break;    /* No collision : it is not necessary to test the next elements of the array*/
   }    /* End if M_GetMSHandle(_p_stSupObj,CollSet) : if the character has a Collision Set*/
 
#if defined(USE_PROFILER) && !defined(PRESS_DEMO)
   PRF_fn_vStopChrono( PRF_C_ulFctCollisions, _p_stSupObj );
 
   if( ucDNMRunning )
	   PRF_fn_vStartChrono( PRF_C_ulFctDNM, p_vCurrentDNMData );
   if( ucIARunning  )
	   PRF_fn_vStartChrono( PRF_C_ulFctAI,  p_vCurrentAIData );
#endif
 
   return lResult;
}
 
/*-----------------------------------------------------------------------------*/
/* fn_vCollideStaticCharacterWithStaticPhysicals*/
/* test static collisions between a character and a static physical object*/
/*-----------------------------------------------------------------------------*/
/* used*/
void fn_vCollideStaticCharacterWithStaticPhysicals
(
	HIE_tdxHandleToSuperObject _hDynamicCharacter ,
	ACP_tdxHandleOfObject      _hDynamicGeoCol ,
	HIE_tdxHandleToSuperObject _hModule ,
	POS_tdstCompletePosition * p_stStartMatrix , 
	POS_tdstCompletePosition * p_stEndMatrix
)
{
	PCS_tdxHandleToPhysicalCollSet hStaticCollSet = PO_fn_hGetCollideSet ( ( PO_tdxHandleToPhysicalObject ) HIE_fn_hGetSuperObjectObject ( _hModule ) ) ;

	/* Down with module ZDR*/
	if ( hStaticCollSet )
	{
		GEO_tdstGeometricObject * p_stStaticGeoColl = PCS_fn_hGetGeoObjOfPhysicalCollSet ( C_ucTypeZdr , hStaticCollSet ) ;

		if ( p_stStaticGeoColl )
		{
			COL_fn_vCollideStaticGeomObj1WithStaticGeomObj2 (
				_hDynamicGeoCol , p_stStartMatrix , p_stEndMatrix , p_stStaticGeoColl ,
				HIE_fn_hGetSuperObjectGlobalMatrix ( _hModule ) ,
				( void * ) _hModule , C_wMobileObject ,
				( ACP_tdxBool ) HIE_fn_SO_bHasNoTransformationMatrix ( _hModule ) ,
				( ACP_tdxBool ) HIE_fn_SO_bHasZoomInsteadOfScale     ( _hDynamicCharacter )
			);
		}
	}
}
 
/*--------------------------------------------------------------------
 * Test static collisions between 2 characters, taking in account Zdr,
 * modules and priority.
 *--------------------------------------------------------------------*/
/* used*/
void fn_vNewTestStaticCollideFor2Characters (HIE_tdxHandleToSuperObject hCharacter ,
                                             ACP_tdxHandleOfObject      _hDynamicZdm ,
                                             HIE_tdxHandleToSuperObject hStaticCharacter ,
                                             POS_tdstCompletePosition * p_stStartMatrix , 
											 POS_tdstCompletePosition * p_stEndMatrix)
{
	GEO_tdxHandleToBoundingSphere		hBoundingVolumeCharacter = NULL;
	GEO_tdxHandleToBoundingSphere		hBoundingVolumeStaticCharacter = NULL;
	CHN_tdxHandleToChannel				hChannel;
	MS_tdxHandleToCollSet				hStaticCollSet;
	MS_tdxHandleToCollSet				hDynamicCollSet;
	HIE_tdxHandleToSuperObject			hMainChar ;
/*   ACP_tdxIndex							xIndex;*/
 
/* ANNECY AV {*/
	/* Is static character active ?*/
	if (! M_ObjectIsActive ((struct tdstEngineObject_ *) HIE_fn_hGetSuperObjectObject (hStaticCharacter)))
/* END ANNECY AV }*/
	{
		return;
	}
 
	/* Is static character collidable ?*/
	if ( HIE_fn_SO_bIsNotPickable ( hStaticCharacter ) )
	{
		return;
	}
 
	hDynamicCollSet = M_GetMSHandle (hCharacter, CollSet);
	hStaticCollSet  = M_GetMSHandle (hStaticCharacter, CollSet);
 
	/* Test the priority : the dynamic priority must be >= than the static priority*/
	if ( CS_fn_ucGetCharacterPriority ( hDynamicCollSet ) < ( hStaticCollSet ? CS_fn_ucGetCharacterPriority( hStaticCollSet ) : 0 ) )
	{
		return;
	}

	hMainChar = MC_fn_hGetCharacterInMainCharacterNode ( MC_fn_hGetFirstMainCharNode ( ) ) ;
 
	if ( hDynamicCollSet )
	{
		/* Test if the dynamic character can collide projectiles*/
		if
		(
			fn_bCollSetGetCharacterNoCollisionWithProjectile (hDynamicCollSet) &&
			(fn_ulStandardGameGetCustomBitsSO (hStaticCharacter) & C_ulCustomBit_Projectile)
		)
		{
			return;
		}

		if ( hStaticCharacter == hMainChar )
		{
			/* Test if the dynamic character can collide the main character*/
			if ( fn_bCollSetGetCharacterNoCollisionWithMainCharacter ( hDynamicCollSet ) )
				return ;
		}
		else
		{
			/* Test if the dynamic character can collide the secondary characters*/
			if
			(
				fn_bCollSetGetCharacterNoCollisionWithSecondaryCharacter ( hDynamicCollSet )
				&& ! fn_ucIsAnAlwaysObject ( ( tdstEngineObject *)  HIE_fn_hGetSuperObjectObject ( hStaticCharacter ) )
			)
				return ;
		}
	}
 
	if ( hStaticCollSet )
	{
		/* Test if the static character can collide projectiles*/
		if
		(
			fn_bCollSetGetCharacterNoCollisionWithProjectile (hStaticCollSet) &&
			(fn_ulStandardGameGetCustomBitsSO (hCharacter) & C_ulCustomBit_Projectile)
		)
		{
			return;
		}

		if ( hMainChar == hCharacter )
		{
			/* Test if the dynamic character can collide the main character*/
			if ( fn_bCollSetGetCharacterNoCollisionWithMainCharacter ( hStaticCollSet ) )
				return ;
		}
		else
		{
			/* Test if the dynamic character can collide the secondary characters */
			if
			(
				fn_bCollSetGetCharacterNoCollisionWithSecondaryCharacter ( hStaticCollSet )
				&& ! fn_ucIsAnAlwaysObject ( ( tdstEngineObject * ) HIE_fn_hGetSuperObjectObject ( hCharacter ) )
			)
				return ;
		}
	}
 
	/* Testing bounding volumes*/
	hBoundingVolumeCharacter = ( GEO_tdxHandleToBoundingSphere ) HIE_fn_hGetSuperObjectBoundingVolume( hCharacter ) ;
	hBoundingVolumeStaticCharacter = ( GEO_tdxHandleToBoundingSphere ) HIE_fn_hGetSuperObjectBoundingVolume ( hStaticCharacter ) ;
 
	if ( hBoundingVolumeCharacter && hBoundingVolumeStaticCharacter )
	if
	(
		! COL_fn_bDetectCollisionStaticGeomObjWithStaticGeomObj (
			hBoundingVolumeCharacter, p_stEndMatrix,
			(void *) hBoundingVolumeStaticCharacter ,
			HIE_fn_hGetSuperObjectGlobalMatrix ( hStaticCharacter ) ,
			( ACP_tdxBool ) HIE_fn_SO_bHasNoTransformationMatrix ( hStaticCharacter ) ,
			( ACP_tdxBool ) HIE_fn_SO_bHasZoomInsteadOfScale ( hCharacter ) , 
			FALSE	/* The Static Character Has NOT a Box Bounding Volume*/
		)
	)
	{
		return;
	}
 
	/* Here, we have to test the collisions*/
	PRF_fn_vIncreaseVariable( PRF_C_ulVarDynColl, hCharacter, 1 );
	/* Dynamic global Zdm Vs Static global Zdr*/
	if ( hStaticCollSet )
	{
		GEO_tdstGeometricObject * hStaticZdr = fn_hStaticMakeOneObjectFromManyZdx ( C_ucTypeZdr , hStaticCharacter ) ;
 
		if ( fn_bIsGeometricObjectValidForCollision (hStaticZdr) )
		{
			COL_fn_vCollideStaticGeomObj1WithStaticGeomObj2(
				_hDynamicZdm, p_stStartMatrix, p_stEndMatrix,
				hStaticZdr, HIE_fn_hGetSuperObjectGlobalMatrix (hStaticCharacter),
				(void *) hStaticCharacter, C_wMobileObject,
				(ACP_tdxBool) HIE_fn_SO_bHasNoTransformationMatrix(hStaticCharacter),
				(ACP_tdxBool) HIE_fn_SO_bHasZoomInsteadOfScale(hCharacter)
			);
		}
   }
 
	/* Dynamic global Zdm Vs static modular Zdr */
	hChannel = fn_h3dDataGetFirstActiveChannel (M_GetMSHandle (hStaticCharacter , 3dData));
	while ( hChannel )
	{
		HIE_tdxHandleToSuperObject hModule = hChannel->hZoomSupObject ? hChannel->hZoomSupObject : hChannel->hSupObject ;
 
		/* check if module position is up to date*/
		/* check if there is a zdr */
		if
		(
			( HIE_fn_ulGetSuperObjectType (hModule) == HIE_C_ulPO )
			&& ( ! ( HIE_M_xGetSuperObjectMember(hModule, ulFlags) & HIE_C_Flag_ulHidden ) ) /* don't use a zone when its channel is deactivated */
		)
		{
#ifdef ACTIVE_EDITOR
			unsigned char ucChannelNumber;
			GEO_tdstGeometricObject * p_stStaticGeoColl;
			MTH_tdxReal	xScaleX,xScaleY,xScaleZ;
			static BOOL s_bColBox = FALSE;
			if ( PO_fn_hGetCollideSet ((PO_tdxHandleToPhysicalObject) HIE_fn_hGetSuperObjectObject (hModule)))
			{
				p_stStaticGeoColl = PCS_fn_hGetGeoObjOfPhysicalCollSet (C_ucTypeZdr , PO_fn_hGetCollideSet ((PO_tdxHandleToPhysicalObject) HIE_fn_hGetSuperObjectObject (hModule)));
			   
				if ( p_stStaticGeoColl )
				{
					/* ok, zdr found, check that position is up to date*/
					ucChannelNumber = (unsigned char) (hChannel - fn_h3dDataGetChannelSOList(M_GetMSHandle(hStaticCharacter, 3dData)));
					fn_vCheckModuleAccessGam(hStaticCharacter, ucChannelNumber);
 
					/* now, check if the module global matrix has a scale or a zoom*/
					if ( ! s_bColBox )
					{
 
						/* if it is a scale, error because scale is not compatible with zdr-itself!*/
						MTH3D_tdstVector stI,stJ,stK;
 
						POS_fn_vGetScaleMatrix(HIE_fn_hGetSuperObjectGlobalMatrix(hModule),&stI,&stJ,&stK);
 
						xScaleX = stI.xX;
						xScaleY = stJ.xY;
						xScaleZ = stK.xZ;
						if ( ! s_bColBox && ! ( MTH_M_bEqualWithEpsilon ( xScaleX , xScaleY , 0.1f ) && MTH_M_bEqualWithEpsilon( xScaleX , xScaleZ , 0.1f ) ) )
						{
							/* error !*/
							char cText[1000];
 
							sprintf(cText,
								"a ZDR_itself module has a scale !! This is forbidden!\n"
								"this module belongs to : %s\n"
								"who is currently in state : %s\n"
								"The number of the channel you try to access is : %i\n"
								"ScaleX = %f, scaleY = %f, scaleZ = %f\n",
								M_GetMSHandle(hStaticCharacter,Brain)
								? (M_pstGetMindOfBrain(M_GetMSHandle(hStaticCharacter,Brain)))->szPersoName
								: "**unknown**",
								fn_p_szGetStateName(fn_h3dDataGetCurrentState(M_GetMSHandle(hStaticCharacter,3dData))),
								(unsigned char) (hChannel - fn_h3dDataGetChannelSOList(M_GetMSHandle(hStaticCharacter, 3dData))),
								xScaleX,xScaleY,xScaleZ
							);
 
							if (hChannel->hZoomSupObject)
							{
								strcat(cText,"\nThis module is a symetric module\n");
							}
							MessageBox(NULL,cText,"Module collision error",MB_OK|MB_ICONWARNING);
							s_bColBox = TRUE;
						}
					}
				}
			}
#endif /* ! ACTIVE_EDITOR */
			fn_vCollideStaticCharacterWithStaticPhysicals (
				hCharacter ,
				_hDynamicZdm ,
				hModule ,
				p_stStartMatrix , p_stEndMatrix
			) ;
		}
		hChannel = hChannel -> p_stNextActiveChannel ;
	}
}
 
/*-----------------------------------------------------------------------------*/
/* New function of collision for a character.*/
/*-----------------------------------------------------------------------------*/
/*used*/
void COL_fn_vNewStaticCollisionForCharacter (HIE_tdxHandleToSuperObject _hCharacter,
                                             HIE_tdxHandleToSuperObject _hSector,
                                             POS_tdstCompletePosition *_p_stStartMatrix,
                                             POS_tdstCompletePosition *_p_stEndMatrix)
{
	MS_tdxHandleToCollSet               hCollSet;
	SECT_tdxHandleOfElementLstCharacter hCharacterList;
	SECT_tdxHandleOfElementLstCollisionInteraction hCollisionList;
	ACP_tdxHandleOfObject hDynamicZDM;
	HIE_tdxHandleToSuperObject hStaticCharacter ;
    GEO_tdxHandleToParallelBox			hParallelBoxStatic = NULL;
	GEO_tdxHandleToBoundingSphere		hBoundingSphereStatic = NULL;
	MTH3D_tdstVector					stMove;
	GEO_tdstParallelBox					stBackupParallelBox;
	MTH_tdxReal							xBackupSphereRadius;
	
	long i , j;
	
	hDynamicZDM = fn_hMakeOneObjectFromManyZdx (C_ucTypeZdm , _hCharacter);
	
	PRF_fn_vStartChrono( PRF_C_ulFctCollisionsChar, _hCharacter );
	
	hCollSet = M_GetMSHandle (_hCharacter, CollSet);

	
	/* jt 270599 */
	/* Enlarge bounding volume */

	/* compute move */
	  MTH3D_M_vSubVector ( &stMove, POS_fn_p_stGetTranslationVector(_p_stEndMatrix), POS_fn_p_stGetTranslationVector(_p_stStartMatrix) );

	  if(HIE_fn_SO_bHasABoxBoundingVolume (_hCharacter))
	  {
			hParallelBoxStatic = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoundingVolume(_hCharacter);
			memcpy(&stBackupParallelBox,hParallelBoxStatic,sizeof(GEO_tdstParallelBox));
			if (MTH_M_bGreaterZero(MTH3D_M_xGetXofVector(&stMove)))
				MTH3D_M_vSetXofVector ( &(hParallelBoxStatic->stMaxPoint), MTH_M_xAdd ( MTH3D_M_xGetXofVector(&(hParallelBoxStatic->stMaxPoint)), MTH3D_M_xGetXofVector(&stMove) ) )
			else
				MTH3D_M_vSetXofVector ( &(hParallelBoxStatic->stMinPoint), MTH_M_xAdd ( MTH3D_M_xGetXofVector(&(hParallelBoxStatic->stMinPoint)), MTH3D_M_xGetXofVector(&stMove) ) )

			if (MTH_M_bGreaterZero(MTH3D_M_xGetYofVector(&stMove)))
				MTH3D_M_vSetYofVector ( &(hParallelBoxStatic->stMaxPoint), MTH_M_xAdd ( MTH3D_M_xGetYofVector(&(hParallelBoxStatic->stMaxPoint)), MTH3D_M_xGetYofVector(&stMove) ) )
			else
				MTH3D_M_vSetYofVector ( &(hParallelBoxStatic->stMinPoint), MTH_M_xAdd ( MTH3D_M_xGetYofVector(&(hParallelBoxStatic->stMinPoint)), MTH3D_M_xGetYofVector(&stMove) ) )

			if (MTH_M_bGreaterZero(MTH3D_M_xGetZofVector(&stMove)))
				MTH3D_M_vSetZofVector ( &(hParallelBoxStatic->stMaxPoint), MTH_M_xAdd ( MTH3D_M_xGetZofVector(&(hParallelBoxStatic->stMaxPoint)), MTH3D_M_xGetZofVector(&stMove) ) )
			else
				MTH3D_M_vSetZofVector ( &(hParallelBoxStatic->stMinPoint), MTH_M_xAdd ( MTH3D_M_xGetZofVector(&(hParallelBoxStatic->stMinPoint)), MTH3D_M_xGetZofVector(&stMove) ) )
	  }
	  else
	  {
			hBoundingSphereStatic = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume(_hCharacter);
			xBackupSphereRadius = hBoundingSphereStatic->xRadius;
			hBoundingSphereStatic->xRadius = MTH_M_xAdd ( hBoundingSphereStatic->xRadius, MTH3D_M_xNormVector(&stMove) );
			
	  }
	/* end jt 270599 */


	/* The collisions with the other characters*/
	if (! fn_bCollSetGetCharacterNoCollisionWithProjectile         (hCollSet) ||
		! fn_bCollSetGetCharacterNoCollisionWithSecondaryCharacter (hCollSet) ||
		! fn_bCollSetGetCharacterNoCollisionWithMainCharacter      (hCollSet))
	{
		/* Deal with interactions between characters*/
		/* First, the Active Sector*/
		SECT_M_ForEachCharListInSector ( _hSector, hCharacterList, i )
		{
			hStaticCharacter = SECT_GetCharacterInList ( hCharacterList ) ;
			if ( _hCharacter != hStaticCharacter )
			{
				fn_vNewTestStaticCollideFor2Characters (
					_hCharacter , hDynamicZDM , hStaticCharacter ,
					_p_stStartMatrix , _p_stEndMatrix
				) ;
			}
		}
		
		/* And now, the collision list*/
		if (! fn_bCollSetGetCharacterNoCollisionWithOtherSectors (hCollSet))
		{
			SECT_M_ForEachCollisionNodeInCollisionInteractionList ( _hSector , hCollisionList , i )
			{
				SECT_M_ForEachCharListInSector ( SECT_GetSectorInCollisionList ( hCollisionList ) , hCharacterList, j )
				{
					hStaticCharacter = SECT_GetCharacterInList ( hCharacterList ) ;
					/* Coz hCharacter may have changed of sector*/
					if ( _hCharacter != hStaticCharacter )
					{
						fn_vNewTestStaticCollideFor2Characters (
							_hCharacter , hDynamicZDM , hStaticCharacter ,
							_p_stStartMatrix , _p_stEndMatrix
						) ;
					}
				}
			}
		}
	}
	
	PRF_fn_vStopChrono( PRF_C_ulFctCollisionsChar, _hCharacter );
	
	/* The collisions with the map*/
	if (! fn_bCollSetGetCharacterNoCollisionWithMap (hCollSet) && ! SECT_fn_bIsThisSectorVirtual (_hSector))
	{
		/* Deal with the static world*/
		COL_fn_vStaticCollisionWithPartOfTreeForSector (_hCharacter, _hSector, hDynamicZDM, _p_stStartMatrix, _p_stEndMatrix);
		
		/* Testing sectors in collision interaction*/
		if (! fn_bCollSetGetCharacterNoCollisionWithOtherSectors (hCollSet))
		{
			SECT_M_ForEachCollisionNodeInCollisionInteractionList ( _hSector, hCollisionList, i )
			{
				HIE_tdxHandleToSuperObject hSectorToCollide = SECT_GetSectorInCollisionList (hCollisionList);
				if (! SECT_fn_bIsThisSectorVirtual (hSectorToCollide))
				{
					COL_fn_vStaticCollisionWithPartOfTreeForSector (_hCharacter, hSectorToCollide, hDynamicZDM,
						_p_stStartMatrix, _p_stEndMatrix);
				}
			}
		}
	}
	
	/* restore initial Bounding Volume */
	if(HIE_fn_SO_bHasABoxBoundingVolume (_hCharacter))
	{
		hParallelBoxStatic = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoundingVolume(_hCharacter);
		memcpy(hParallelBoxStatic,&stBackupParallelBox,sizeof(GEO_tdstParallelBox));
	}
	else
	{
		hBoundingSphereStatic = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume(_hCharacter);
		hBoundingSphereStatic->xRadius = xBackupSphereRadius;		
	}

	return;
 
}
 
/*-----------------------------------------------------------------------------*/
/* COL_fn_vStaticCollisionWithPartOfTreeForSector*/
/* New exploration of the static tree with use of sectors*/
/*-----------------------------------------------------------------------------*/
/* used*/
void COL_fn_vStaticCollisionWithPartOfTreeForSector (HIE_tdxHandleToSuperObject _p_stEngineObj,
                                                     HIE_tdxHandleToSuperObject _p_stSuperObj,
                                                     GEO_tdstGeometricObject * _p_stDynamicGeoColl,
                                                     POS_tdstCompletePosition * _p_stStartMatrix,
                                                     POS_tdstCompletePosition * _p_stEndMatrix)
{
  unsigned long p;
  HIE_tdxHandleToSuperObject		pChild;
  GEO_tdstGeometricObject *			p_stStaticGeoColl;
  PO_tdxHandleToPhysicalObject		hPhysicalObject;
  PCS_tdxHandleToPhysicalCollSet	hPhyCollSet;
  GEO_tdxHandleToBoundingSphere		hBoundingVolumeCharacter = NULL;
  GEO_tdxHandleToParallelBox		hParallelBoxStatic = NULL;
  GEO_tdxHandleToBoundingSphere		hBoundingSphereStatic = NULL;
  void					*			hBoundingVolumeStatic;
  long								lType;
 
 
  if (HIE_fn_SO_bIsNotPickable( _p_stSuperObj ) )
  {
      return;
  }
 
  hBoundingVolumeCharacter = HIE_fn_hGetSuperObjectBoundingVolume (_p_stEngineObj);
  if(HIE_fn_SO_bHasABoxBoundingVolume (_p_stSuperObj))
  {
	  hParallelBoxStatic = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoundingVolume(_p_stSuperObj);
	  hBoundingVolumeStatic = (void *)hParallelBoxStatic;
  }
  else
  {
	  hBoundingSphereStatic = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume(_p_stSuperObj);
	  hBoundingVolumeStatic = (void *)hBoundingSphereStatic;
  }
  
  if (hBoundingVolumeCharacter && hBoundingVolumeStatic)
  {
			 if (! COL_fn_bDetectCollisionStaticGeomObjWithStaticGeomObj (hBoundingVolumeCharacter , _p_stEndMatrix ,
				 hBoundingVolumeStatic, HIE_fn_hGetSuperObjectGlobalMatrix (_p_stSuperObj),
				 (ACP_tdxBool) HIE_fn_SO_bHasNoTransformationMatrix (_p_stSuperObj),
				 (ACP_tdxBool) HIE_fn_SO_bHasZoomInsteadOfScale     (_p_stEngineObj),
				 (ACP_tdxBool) HIE_fn_SO_bHasABoxBoundingVolume     (_p_stSuperObj)))
      {
		  if(HIE_fn_SO_bCheckChildren(_p_stSuperObj))
		  {
			  HIE_M_ForEachChildOf ( _p_stSuperObj, pChild, p )
			  {
				  COL_fn_vStaticCollisionWithPartOfTreeForSector (_p_stEngineObj, pChild, _p_stDynamicGeoColl, _p_stStartMatrix, _p_stEndMatrix);
			  }
			  return;
		  }
		  else			  
			  return;
      }
   }
 
    PRF_fn_vSetIndependantVariable( PRF_C_ulIdpCollComputed, 0 );
 
	lType = HIE_fn_ulGetSuperObjectType(_p_stSuperObj);
	
#ifdef D_THROW_IPO
	if( lType & (HIE_C_ulPO | HIE_C_ulPO_Mirror ))
	{
		hPhysicalObject = (PO_tdxHandleToPhysicalObject)HIE_fn_hGetSuperObjectObject(_p_stSuperObj);
		hPhyCollSet = PO_fn_hGetCollideSet(hPhysicalObject);
		if ( hPhyCollSet ) /* GIZMO 070897*/
		{
			p_stStaticGeoColl = PCS_fn_hGetZdrGeoObjOfPhysicalCollSet(hPhyCollSet);
			COL_fn_vCollideStaticGeomObj1WithStaticGeomObj2 (_p_stDynamicGeoColl, _p_stStartMatrix, _p_stEndMatrix, p_stStaticGeoColl, HIE_fn_hGetSuperObjectGlobalMatrix(_p_stSuperObj),
				(void *) _p_stSuperObj , C_wStaticObject ,
				(ACP_tdxBool) HIE_fn_SO_bHasNoTransformationMatrix(_p_stSuperObj),
				(ACP_tdxBool) HIE_fn_SO_bHasZoomInsteadOfScale(_p_stEngineObj));
		}
	}
#else /*D_THROW_IPO*/
	if (lType & ( HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
	{
		hPhysicalObject = IPO_fn_hGetPhysicalObject((IPO_tdxHandleToInstanciatedPhysicalObject)HIE_fn_hGetSuperObjectObject(_p_stSuperObj));
		hPhyCollSet = PO_fn_hGetCollideSet(hPhysicalObject);
		if ( hPhyCollSet ) /* GIZMO 070897*/
		{
			p_stStaticGeoColl = PCS_fn_hGetZdrGeoObjOfPhysicalCollSet(hPhyCollSet);
			COL_fn_vCollideStaticGeomObj1WithStaticGeomObj2 (_p_stDynamicGeoColl, _p_stStartMatrix, _p_stEndMatrix, p_stStaticGeoColl, HIE_fn_hGetSuperObjectGlobalMatrix(_p_stSuperObj),
				(void *) _p_stSuperObj , C_wStaticObject ,
				(ACP_tdxBool) HIE_fn_SO_bHasNoTransformationMatrix(_p_stSuperObj),
				(ACP_tdxBool) HIE_fn_SO_bHasZoomInsteadOfScale(_p_stEngineObj));
		}
	}
#endif /* D_THROW_IPO */
/*End XB*/
 
#ifdef USE_PROFILER
  if( PRF_fn_lGetIndependantVariable( PRF_C_ulIdpCollComputed ) )
    PRF_fn_vIncreaseVariable( PRF_C_ulVarStaColl, _p_stEngineObj, 1 );
#endif /* USE_PROFILER */
 
  /* test all objects in sector*/
  HIE_M_ForEachChildOf ( _p_stSuperObj, pChild, p )
  {
    COL_fn_vStaticCollisionWithPartOfTreeForSector (_p_stEngineObj, pChild, _p_stDynamicGeoColl, _p_stStartMatrix, _p_stEndMatrix);
  }
}
 
