
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///																																  ///
///		FICHIER :	overlap.cpp																									  ///
///																																  ///
///		NATURE	:	Find the intersection for Collision																			  ///
///																																  ///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




#include	"..\Collision\RAPID_version.H"



static char rapidtag_data[] = "RAPIDTAG  file: "__FILE__"    date: "__DATE__"    time: "__TIME__;


// to silence the compiler's complaints about unreferenced identifiers.
static void r1(char *f){  r1(f);  r1(rapidtag_data);  r1(rapid_version);}




#include	"..\Collision\matvec.H"
#include	"..\Basic\ZooMatrix.h"


extern	float	RAPID_coeff;
extern	int		RAPID_axid1, RAPID_axid2;



///////////////////////////////////////////////////////////////////////////////////
///		MAX																		///
///////////////////////////////////////////////////////////////////////////////////
inline float max(float a, float b, float c)
{
	float t = a;

	if (b > t) t = b;
	if (c > t) t = c;
	
	return t;
}



///////////////////////////////////////////////////////////////////////////////////
///		MIN																		///
///////////////////////////////////////////////////////////////////////////////////
inline float min(float a, float b, float c)
{
	float t = a;
	
	if (b < t) t = b;
	if (c < t) t = c;
	
	return t;
}



///////////////////////////////////////////////////////////////////////////////////
///		project6																///
///////////////////////////////////////////////////////////////////////////////////
int project6(float *ax, float *p1, float *p2, float *p3, float *q1, float *q2, float *q3)
{
	float P1 = VdotV(ax, p1);
	float P2 = VdotV(ax, p2);
	float P3 = VdotV(ax, p3);
	float Q1 = VdotV(ax, q1);
	float Q2 = VdotV(ax, q2);
	float Q3 = VdotV(ax, q3);
  
	float mx1 = max(P1, P2, P3);
	float mn1 = min(P1, P2, P3);
	float mx2 = max(Q1, Q2, Q3);
	float mn2 = min(Q1, Q2, Q3);

	if (mn1 > mx2) return 0;
	if (mn2 > mx1) return 0;
	
	return 1;
}



///////////////////////////////////////////////////////////////////////////////////
///																				///
/// very robust triangle intersection test										///
/// uses no divisions															///
/// works on coplanar triangles, too											///
///																				///
///////////////////////////////////////////////////////////////////////////////////
///
///	Renvoit 1 si contact, 0 sinon
///
int tri_contact(float *P1, float *P2, float *P3, float *Q1, float *Q2, float *Q3) 
{
	// Coordonnées des vertices : (p1,p2,p3) et (q1,q2,q3).
	// Les arêtes opposées aux vertices : (e1,e2,e3) et (f1,f2,f3).
	// Normales aux triangles : n1 et m1.
	// Verteurs orthogonaux (et sortant) aux arêtes : (g1,g2,g3) and (h1,h2,h3).

	// On suppose que les vertices sont dans le même système de coodonnées.

	// First thing we do is establish a new c.s. so that p1 is at (0,0,0).

	float p1[3], p2[3], p3[3];
	float q1[3], q2[3], q3[3];
	float e1[3], e2[3], e3[3];
	float f1[3], f2[3], f3[3];
	float g1[3], g2[3], g3[3];
	float h1[3], h2[3], h3[3];
	float n1[3], m1[3];
	float z[3];

	float ef11[3], ef12[3], ef13[3];
	float ef21[3], ef22[3], ef23[3];
	float ef31[3], ef32[3], ef33[3];

	z[0] = 0.0;  z[1] = 0.0;  z[2] = 0.0;

	// Place p1 au centre du repère <-> translate tous les points du vecteur (-p1)
	p1[0] = P1[0] - P1[0];  p1[1] = P1[1] - P1[1];  p1[2] = P1[2] - P1[2];
	p2[0] = P2[0] - P1[0];  p2[1] = P2[1] - P1[1];  p2[2] = P2[2] - P1[2];
	p3[0] = P3[0] - P1[0];  p3[1] = P3[1] - P1[1];  p3[2] = P3[2] - P1[2];

	q1[0] = Q1[0] - P1[0];  q1[1] = Q1[1] - P1[1];  q1[2] = Q1[2] - P1[2];
	q2[0] = Q2[0] - P1[0];  q2[1] = Q2[1] - P1[1];  q2[2] = Q2[2] - P1[2];
	q3[0] = Q3[0] - P1[0];  q3[1] = Q3[1] - P1[1];  q3[2] = Q3[2] - P1[2];

	// Calcule les arêtes opposées aux points
	e1[0] = p2[0] - p1[0];  e1[1] = p2[1] - p1[1];  e1[2] = p2[2] - p1[2];
	e2[0] = p3[0] - p2[0];  e2[1] = p3[1] - p2[1];  e2[2] = p3[2] - p2[2];
	e3[0] = p1[0] - p3[0];  e3[1] = p1[1] - p3[1];  e3[2] = p1[2] - p3[2];

	f1[0] = q2[0] - q1[0];  f1[1] = q2[1] - q1[1];  f1[2] = q2[2] - q1[2];
	f2[0] = q3[0] - q2[0];  f2[1] = q3[1] - q2[1];  f2[2] = q3[2] - q2[2];
	f3[0] = q1[0] - q3[0];  f3[1] = q1[1] - q3[1];  f3[2] = q1[2] - q3[2];

	// Calcule les normales aux deux triangles
	VcrossV(n1, e1, e2);
	VcrossV(m1, f1, f2);

	// Calcule les vecteurs sortants aux arêtes
	VcrossV(g1, e1, n1);
	VcrossV(g2, e2, n1);
	VcrossV(g3, e3, n1);
	VcrossV(h1, f1, m1);
	VcrossV(h2, f2, m1);
	VcrossV(h3, f3, m1);

	// Produits vectoriels 2à2 des arêtes des deux triangles
	VcrossV(ef11, e1, f1);
	VcrossV(ef12, e1, f2);
	VcrossV(ef13, e1, f3);
	VcrossV(ef21, e2, f1);
	VcrossV(ef22, e2, f2);
	VcrossV(ef23, e2, f3);
	VcrossV(ef31, e3, f1);
	VcrossV(ef32, e3, f2);
	VcrossV(ef33, e3, f3);

	// Commence la série de tests
	if (!project6(n1, p1, p2, p3, q1, q2, q3))		return 0;
	if (!project6(m1, p1, p2, p3, q1, q2, q3))		return 0;

	if (!project6(ef11, p1, p2, p3, q1, q2, q3))	return 0;
	if (!project6(ef12, p1, p2, p3, q1, q2, q3))	return 0;
	if (!project6(ef13, p1, p2, p3, q1, q2, q3))	return 0;
	if (!project6(ef21, p1, p2, p3, q1, q2, q3))	return 0;
	if (!project6(ef22, p1, p2, p3, q1, q2, q3))	return 0;
	if (!project6(ef23, p1, p2, p3, q1, q2, q3))	return 0;
	if (!project6(ef31, p1, p2, p3, q1, q2, q3))	return 0;
	if (!project6(ef32, p1, p2, p3, q1, q2, q3))	return 0;
	if (!project6(ef33, p1, p2, p3, q1, q2, q3))	return 0;

	if (!project6(g1, p1, p2, p3, q1, q2, q3))		return 0;
	if (!project6(g2, p1, p2, p3, q1, q2, q3))		return 0;
	if (!project6(g3, p1, p2, p3, q1, q2, q3))		return 0;
	if (!project6(h1, p1, p2, p3, q1, q2, q3))		return 0;
	if (!project6(h2, p1, p2, p3, q1, q2, q3))		return 0;
	if (!project6(h3, p1, p2, p3, q1, q2, q3))		return 0;

	return 1;
}



///////////////////////////////////////////////////////////////////////////////////
///																				///
/// int obb_disjoint(float B[3][3], float T[3], float a[3], float b[3]);		///
///																				///
/// This is a test between two boxes, box A and box B.  It is assumed that		///
/// the coordinate system is aligned and centered on box A.  The 3x3			///
/// matrix B specifies box B's orientation with respect to box A.				///
/// Specifically, the columns of B are the basis vectors (axis vectors) of		///
/// box B.  The center of box B is located at the vector T.  The				///
/// dimensions of box B are given in the array b.  The orientation and			///
/// placement of box A, in this coordinate system, are the identity matrix		///
/// and zero vector, respectively, so they need not be specified.  The			///
/// dimensions of box A are given in array a, and the dimension of B in b.		///
///																				///
/// This test operates in two modes, depending on how the library is			///
/// compiled.  It indicates whether the two boxes are overlapping, by			///
/// returning a boolean.														///
///																				///
/// The second version of the routine will return a conservative bounds on		///
/// the distance between the polygon sets which the boxes enclose.  It is		///
/// used when RAPID is being used to estimate the distance between two			///
/// models.																		///
///																				///
///////////////////////////////////////////////////////////////////////////////////
///
///	Renvoit 0 si intersection, 1 à 15 si disjoints (n° du plan séparateur).
///
int	obb_disjoint(float B[3][3], float T[3], float a[3], float b[3])
{
	register float	t, s;	// t = distance A-B  (translation de B) ;   s = intermédiaire de calcul
	register int	r;		// pour optimiser la comparaison
	
	float Bf[3][3];
	
	const float	reps = 1e-6f;

	// Bf = fabs(B)
	Bf[0][0] = myfabs(B[0][0]);  Bf[0][0] += reps;
	Bf[0][1] = myfabs(B[0][1]);  Bf[0][1] += reps;
	Bf[0][2] = myfabs(B[0][2]);  Bf[0][2] += reps;
	Bf[1][0] = myfabs(B[1][0]);  Bf[1][0] += reps;
	Bf[1][1] = myfabs(B[1][1]);  Bf[1][1] += reps;
	Bf[1][2] = myfabs(B[1][2]);  Bf[1][2] += reps;
	Bf[2][0] = myfabs(B[2][0]);  Bf[2][0] += reps;
	Bf[2][1] = myfabs(B[2][1]);  Bf[2][1] += reps;
	Bf[2][2] = myfabs(B[2][2]);  Bf[2][2] += reps;


	// if any of these tests are one-sided, then the polyhedra are disjoint
	r = 1;


	///////////////////////////////////////////////////////
	///	Tests sur les axes othogonaux aux faces			///
	/// equivalent aux tests sur les plans des faces	///
	///////////////////////////////////////////////////////

	// -------------- Axe A0 -------------- //
	t = myfabs(T[0]);

	r &= (t <= 
		  (a[0] + b[0] * Bf[0][0] + b[1] * Bf[0][1] + b[2] * Bf[0][2]));
	if (!r) return 1;

	// -------------- Axe B0 -------------- //
	s = T[0]*B[0][0] + T[1]*B[1][0] + T[2]*B[2][0];
	t = myfabs(s);

	r &= ( t <=
		  (b[0] + a[0] * Bf[0][0] + a[1] * Bf[1][0] + a[2] * Bf[2][0]));
	if (!r) return 2;
  
	// -------------- Axe A1 -------------- //
	t = myfabs(T[1]);

	r &= ( t <= 
		  (a[1] + b[0] * Bf[1][0] + b[1] * Bf[1][1] + b[2] * Bf[1][2]));
	if (!r) return 3;

	// -------------- Axe A2 -------------- //
	t = myfabs(T[2]);

	r &= ( t <= 
		  (a[2] + b[0] * Bf[2][0] + b[1] * Bf[2][1] + b[2] * Bf[2][2]));
	if (!r) return 4;

	// -------------- Axe B1 -------------- //
	s = T[0]*B[0][1] + T[1]*B[1][1] + T[2]*B[2][1];
	t = myfabs(s);

	r &= ( t <=
		  (b[1] + a[0] * Bf[0][1] + a[1] * Bf[1][1] + a[2] * Bf[2][1]));
	if (!r) return 5;

	// -------------- Axe B2 -------------- //
	s = T[0]*B[0][2] + T[1]*B[1][2] + T[2]*B[2][2];
	t = myfabs(s);

	r &= ( t <=
		  (b[2] + a[0] * Bf[0][2] + a[1] * Bf[1][2] + a[2] * Bf[2][2]));
	if (!r) return 6;

	


	///////////////////////////////////////////////////////////
	///	Tests sur les axes othogonaux à deux arêtes			///
	///	equivalent aux tests sur les plans paral aux arêtes	///
	///////////////////////////////////////////////////////////

	// -------------- Axe (A0 x B0) -------------- //
	s = T[2] * B[1][0] - T[1] * B[2][0];
	t = myfabs(s);

	r &= ( t <= 
		(a[1] * Bf[2][0] + a[2] * Bf[1][0] +
		 b[1] * Bf[0][2] + b[2] * Bf[0][1]));
	if (!r) return 7;

	// -------------- Axe (A0 x B1) -------------- //
	s = T[2] * B[1][1] - T[1] * B[2][1];
	t = myfabs(s);

	r &= ( t <=
		(a[1] * Bf[2][1] + a[2] * Bf[1][1] +
		 b[0] * Bf[0][2] + b[2] * Bf[0][0]));
	if (!r) return 8;

	// -------------- Axe (A0 x B2) -------------- //
	s = T[2] * B[1][2] - T[1] * B[2][2];
	t = myfabs(s);

	r &= ( t <=
		  (a[1] * Bf[2][2] + a[2] * Bf[1][2] +
		   b[0] * Bf[0][1] + b[1] * Bf[0][0]));
	if (!r) return 9;

	// -------------- Axe (A1 x B0) -------------- //
	s = T[0] * B[2][0] - T[2] * B[0][0];
	t = myfabs(s);

	r &= ( t <=
		  (a[0] * Bf[2][0] + a[2] * Bf[0][0] +
		   b[1] * Bf[1][2] + b[2] * Bf[1][1]));
	if (!r) return 10;

	// -------------- Axe (A1 x B1) -------------- //
	s = T[0] * B[2][1] - T[2] * B[0][1];
	t = myfabs(s);

	r &= ( t <=
		  (a[0] * Bf[2][1] + a[2] * Bf[0][1] +
		   b[0] * Bf[1][2] + b[2] * Bf[1][0]));
	if (!r) return 11;

	// -------------- Axe (A1 x B2) -------------- //
	s = T[0] * B[2][2] - T[2] * B[0][2];
	t = myfabs(s);

	r &= (t <=
		  (a[0] * Bf[2][2] + a[2] * Bf[0][2] +
		   b[0] * Bf[1][1] + b[1] * Bf[1][0]));
	if (!r) return 12;

	// -------------- Axe (A2 x B0) -------------- //
	s = T[1] * B[0][0] - T[0] * B[1][0];
	t = myfabs(s);

	r &= (t <=
		  (a[0] * Bf[1][0] + a[1] * Bf[0][0] +
		   b[1] * Bf[2][2] + b[2] * Bf[2][1]));
	if (!r) return 13;

	// -------------- Axe (A2 x B1) -------------- //
	s = T[1] * B[0][1] - T[0] * B[1][1];
	t = myfabs(s);

	r &= ( t <=
		  (a[0] * Bf[1][1] + a[1] * Bf[0][1] +
		   b[0] * Bf[2][2] + b[2] * Bf[2][0]));
	if (!r) return 14;

	// -------------- Axe (A2 x B2) -------------- //
	s = T[1] * B[0][2] - T[0] * B[1][2];
	t = myfabs(s);

	r &= ( t <=
		  (a[0] * Bf[1][2] + a[1] * Bf[0][2] +
		   b[0] * Bf[2][1] + b[1] * Bf[2][0]));
	if (!r) return 15;




	return 0;  // Dans le cas où ils s'intersectent
}



///////////////////////////////////////////////////////////////////////////////////
///		project6_trans															///
///////////////////////////////////////////////////////////////////////////////////
///
/// Retourne -1 s'il ya intersection au départ
/// Retourne 1 s'il ya intersection en translation
/// Retourne 0 s'il n'y a pas intersection
///
int project6_trans(float *ax, float *p1, float *p2, float *p3, float *q1, float *q2, float *q3, float *Vb2, float *result)
{
	float P1 = VdotV(ax, p1);
	float P2 = VdotV(ax, p2);
	float P3 = VdotV(ax, p3);
	float Q1 = VdotV(ax, q1);
	float Q2 = VdotV(ax, q2);
	float Q3 = VdotV(ax, q3);

	float v  = VdotV(ax, Vb2);

	float mx1 = max(P1, P2, P3);
	float mn1 = min(P1, P2, P3);
	float mx2 = max(Q1, Q2, Q3);
	float mn2 = min(Q1, Q2, Q3);

	float diff1 = mn1 - mx2;
	// Si pas intersection au départ, on teste la translation
	if(diff1>0)
	{
		float k = diff1/v;
		// s'il ya contact pendant la translation
		if((k<=1)&(k>0))
		{
			*result = k;
			return 1;
		}
		// sinon, les polys sont disjoints
		return 0;
	}
	
	float diff2 = mx1 - mn2;
	// Si pas intersection au départ, on teste la translation
	if(diff2<0)
	{
		float k = diff2/v;
		// s'il ya contact pendant la translation
		if((k<=1)&(k>0))
		{
			*result = k;
			return 1;
		}
		// sinon, les polys sont disjoints
		return 0;
	}

	return -1;
}



///////////////////////////////////////////////////////////////////////////////////
///																				///
/// very robust triangle intersection test										///
/// uses no divisions															///
/// works on coplanar triangles, too											///
///																				///
///////////////////////////////////////////////////////////////////////////////////
///
///	Vb2 = vecteur de tranlation de b2 par rapport a b1, dans le CS de b2.
///
///	Renvoit 1 si contact en translation, -1 si prime intersection, 0 si disjoints
///
int tri_contact_trans (float *P1, float *P2, float *P3, float *Q1, float *Q2, float *Q3, float Vb2[3]) 
{
	// Coordonnées des vertices : (p1,p2,p3) et (q1,q2,q3).
	// Les arêtes opposées aux vertices : (e1,e2,e3) et (f1,f2,f3).
	// Normales aux triangles : n1 et m1.
	// Verteurs orthogonaux (et sortant) aux arêtes : (g1,g2,g3) and (h1,h2,h3).

	// On suppose que les vertices sont dans le même système de coodonnées.

	// First thing we do is establish a new c.s. so that p1 is at (0,0,0).

	float p1[3], p2[3], p3[3];
	float q1[3], q2[3], q3[3];
	float e1[3], e2[3], e3[3];
	float f1[3], f2[3], f3[3];
	float g1[3], g2[3], g3[3];
	float h1[3], h2[3], h3[3];
	float n1[3], m1[3];
	float z[3];

	float ef11[3], ef12[3], ef13[3];
	float ef21[3], ef22[3], ef23[3];
	float ef31[3], ef32[3], ef33[3];

	z[0] = 0.0;  z[1] = 0.0;  z[2] = 0.0;

	// Place p1 au centre du repère <-> translate tous les points du vecteur (-p1)
	p1[0] = P1[0] - P1[0];		p1[1] = P1[1] - P1[1];		p1[2] = P1[2] - P1[2];
	p2[0] = P2[0] - P1[0];		p2[1] = P2[1] - P1[1];		p2[2] = P2[2] - P1[2];
	p3[0] = P3[0] - P1[0];		p3[1] = P3[1] - P1[1];		p3[2] = P3[2] - P1[2];

	q1[0] = Q1[0] - P1[0];		q1[1] = Q1[1] - P1[1];		q1[2] = Q1[2] - P1[2];
	q2[0] = Q2[0] - P1[0];		q2[1] = Q2[1] - P1[1];		q2[2] = Q2[2] - P1[2];
	q3[0] = Q3[0] - P1[0];		q3[1] = Q3[1] - P1[1];		q3[2] = Q3[2] - P1[2];

	// Calcule les arêtes opposées aux points
	e1[0] = p2[0] - p1[0];		e1[1] = p2[1] - p1[1];		e1[2] = p2[2] - p1[2];
	e2[0] = p3[0] - p2[0];		e2[1] = p3[1] - p2[1];		e2[2] = p3[2] - p2[2];
	e3[0] = p1[0] - p3[0];		e3[1] = p1[1] - p3[1];		e3[2] = p1[2] - p3[2];

	f1[0] = q2[0] - q1[0];		f1[1] = q2[1] - q1[1];		f1[2] = q2[2] - q1[2];
	f2[0] = q3[0] - q2[0];		f2[1] = q3[1] - q2[1];		f2[2] = q3[2] - q2[2];
	f3[0] = q1[0] - q3[0];		f3[1] = q1[1] - q3[1];		f3[2] = q1[2] - q3[2];

	// Calcule les normales aux deux triangles
	VcrossV(n1, e1, e2);
	VcrossV(m1, f1, f2);

	// Calcule les vecteurs sortants aux arêtes
	VcrossV(g1, e1, n1);
	VcrossV(g2, e2, n1);
	VcrossV(g3, e3, n1);
	VcrossV(h1, f1, m1);
	VcrossV(h2, f2, m1);
	VcrossV(h3, f3, m1);

	// Produits vectoriels 2à2 des arêtes des deux triangles
	VcrossV(ef11, e1, f1);
	VcrossV(ef12, e1, f2);
	VcrossV(ef13, e1, f3);
	VcrossV(ef21, e2, f1);
	VcrossV(ef22, e2, f2);
	VcrossV(ef23, e2, f3);
	VcrossV(ef31, e3, f1);
	VcrossV(ef32, e3, f2);
	VcrossV(ef33, e3, f3);

	// Commence la série de tests
	int		k;
	float	r, resmin;
	int		axid1 = 0, axid2 = 0;


	resmin = -1;

	// Prototype du test :
	// - test de l'un des 17 axes
	// - si les deux triangles sont disjoints, on arrête les tests (k=0)
	// - si les deux triangles sont en prime intersection, on continue les tests sans rien faire (k=-1)
	// - si les deux triangles sont en intersection de translation, alors on retient le coeff ssi il est le plus grand (k=1)

	k = project6_trans(n1, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 2;	axid1 = 1;	}

	k = project6_trans(m1, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 1;	axid1 = 2;	}

	k = project6_trans(ef11, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 3;	axid1 = 2;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(ef12, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 4;	axid1 = 4;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(ef13, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 5;	axid1 = 5;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(ef21, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 6;	axid1 = 6;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(ef22, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 7;	axid1 = 7;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(ef23, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 8;	axid1 = 8;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(ef31, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 9;	axid1 = 9;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(ef32, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 10;	axid1 = 10;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(ef33, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 11;	axid1 = 11;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(g1, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 12;	axid1 = 12;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(g2, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 13;	axid1 = 13;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(g3, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 14;	axid1 = 14;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(h1, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 15;	axid1 = 15;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(h2, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 16;	axid1 = 16;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}

	k = project6_trans(h3, p1, p2, p3, q1, q2, q3, Vb2, &r);
	if(!k)		return 0;
//	if((k==1)&&(r>resmin))		{	resmin = r;		axid2 = 17;	axid1 = 17;	}
	if((k==1)&&(r>resmin))		{	resmin = r;	}



	
	// Cas de prime intersection
	
	if(resmin<0)		return -1;


	// Cas d'intersection en translation :
	// - si le coeff pour ces deux triangles est le plus petit, on le stocke et on stocke l'axe
	// (on recherche le coeff des deux triangles les plus proches)

	if((resmin < RAPID_coeff)&&(axid1))	// attention !! la condition (axid!=0) est importante, car elle permet de savoir si les normales aux faces ont contribué ou pas
	{
		RAPID_coeff  = resmin;
		
	//	if(axid1>2)		axid1 = axid2 = 1;
	/*	if(VdotV(n1, Vb2) > 0)
		{
			RAPID_axid1  = 1;
			RAPID_axid2  = 2;
		}
		if(VdotV(m1, Vb2) > 0)
		{
			RAPID_axid1  = 2;
			RAPID_axid2  = 1;
		}
*/

		RAPID_axid1  = axid1;
		RAPID_axid2  = axid2;
	}

	return 1;
}



///////////////////////////////////////////////////////////////////////////////////////////////
/// MACRO for OBB's translation collision determination										///
///////////////////////////////////////////////////////////////////////////////////////////////
#define TRANS_COLL_OBB(nbAxe)																		\
	/* S'il ya une prime intersection : on ne fait rien. Sinon, test sur la translation :	*/		\
	if(myfabs(t)>somme)																				\
	{																								\
		/* si la translation ecarte les OBB, aucune intersection - c'est fini. */					\
		if((t>0)&&(v>=0))		return 0;															\
		if((t<0)&&(v<=0))		return 0;															\
																									\
		/* si la translation rapproche les objets, on teste suivant la valeur de |t+k.v|. */		\
		if(t>0)		res =  (somme-t)/v;		/* |t+k.v| = t+kv   ---> k =  (s-t) / v */				\
		if(t<0)		res = -(somme+t)/v;		/* |t+k.v| = -t-kv  ---> k = -(s+t) / v */				\
																									\
		if((res<0)||(res>1))	return 0;															\
																									\
		if(res>resmin)																				\
		{																							\
			resmin = res;																			\
			axe	   = nbAxe;																			\
		}																							\
	}





int	obb_inter_trans(float B[3][3], float T[3], float a[3], float b[3], float V[3])
{
	float t;				// t = distance A-B  (translation de B);
	float v;				// v = projection de la translation de V;
	register int	r;		// pour optimiser la comparaison
	float	 somme;

	float	res, resmin;
	int		axe;

	float	Bf[3][3];

	const float	reps = 1e-6f;

	// Bf = fabs(B)
	Bf[0][0] = myfabs(B[0][0]);  Bf[0][0] += reps;
	Bf[0][1] = myfabs(B[0][1]);  Bf[0][1] += reps;
	Bf[0][2] = myfabs(B[0][2]);  Bf[0][2] += reps;
	Bf[1][0] = myfabs(B[1][0]);  Bf[1][0] += reps;
	Bf[1][1] = myfabs(B[1][1]);  Bf[1][1] += reps;
	Bf[1][2] = myfabs(B[1][2]);  Bf[1][2] += reps;
	Bf[2][0] = myfabs(B[2][0]);  Bf[2][0] += reps;
	Bf[2][1] = myfabs(B[2][1]);  Bf[2][1] += reps;
	Bf[2][2] = myfabs(B[2][2]);  Bf[2][2] += reps;


	// if any of these tests are one-sided, then the polyhedra are disjoint
	r = 1;


	// for translation tests
	resmin = -1;
	res	   = 1;


	///////////////////////////////////////////////////////
	///	Tests sur les axes othogonaux aux faces			///
	/// equivalent aux tests sur les plans des faces	///
	///////////////////////////////////////////////////////


	// -------------- Axe A0 -------------- //
	t = T[0];		v = V[0];													// projection de T et V sur l'axe
	somme = (a[0] + b[0] * Bf[0][0] + b[1] * Bf[0][1] + b[2] * Bf[0][2]);		// ra + rb
	
	TRANS_COLL_OBB(1)

	// -------------- Axe B0 -------------- //
	t = T[0]*B[0][0] + T[1]*B[1][0] + T[2]*B[2][0];								// projection de T sur l'axe
	v = V[0]*B[0][0] + V[1]*B[1][0] + V[2]*B[2][0];								// projection de V sur l'axe
	somme = (b[0] + a[0] * Bf[0][0] + a[1] * Bf[1][0] + a[2] * Bf[2][0]);		// ra + rb
	
	TRANS_COLL_OBB(2)
	
	
	// -------------- Axe A1 -------------- //
	t = T[1];																	// projection de T sur l'axe
	v = V[1];																	// projection de V sur l'axe
	somme = (a[1] + b[0] * Bf[1][0] + b[1] * Bf[1][1] + b[2] * Bf[1][2]);		// ra + rb
	
	TRANS_COLL_OBB(3)
	
	
	// -------------- Axe A2 -------------- //
	t = T[2];																	// projection de T sur l'axe
	v = V[2];																	// projection de V sur l'axe
	somme = (a[2] + b[0] * Bf[2][0] + b[1] * Bf[2][1] + b[2] * Bf[2][2]);		// ra + rb
	
	TRANS_COLL_OBB(4)
	
	
	// -------------- Axe B1 -------------- //
	t = T[0]*B[0][1] + T[1]*B[1][1] + T[2]*B[2][1];								// projection de T sur l'axe
	v = V[0]*B[0][1] + V[1]*B[1][1] + V[2]*B[2][1];								// projection de V sur l'axe
	somme = (b[1] + a[0] * Bf[0][1] + a[1] * Bf[1][1] + a[2] * Bf[2][1]);		// ra + rb
	
	TRANS_COLL_OBB(5)
	
	
	// -------------- Axe B2 -------------- //
	t = T[0]*B[0][2] + T[1]*B[1][2] + T[2]*B[2][2];								// projection de T sur l'axe
	v = V[0]*B[0][2] + V[1]*B[1][2] + V[2]*B[2][2];								// projection de V sur l'axe
	somme = (b[2] + a[0] * Bf[0][2] + a[1] * Bf[1][2] + a[2] * Bf[2][2]);		// ra + rb
	
	TRANS_COLL_OBB(6)




	///////////////////////////////////////////////////////////
	///	Tests sur les axes othogonaux à deux arêtes			///
	///	equivalent aux tests sur les plans paral aux arêtes	///
	///////////////////////////////////////////////////////////

	// -------------- Axe (A0 x B0) -------------- //
	t = T[2] * B[1][0] - T[1] * B[2][0];						// projection de T sur l'axe
	v = V[2] * B[1][0] - V[1] * B[2][0];						// projection de V sur l'axe
	somme = (a[1] * Bf[2][0] + a[2] * Bf[1][0] +
			 b[1] * Bf[0][2] + b[2] * Bf[0][1]);				// ra + rb
	
	TRANS_COLL_OBB(7)


	// -------------- Axe (A0 x B1) -------------- //
	t = T[2] * B[1][1] - T[1] * B[2][1];						// projection de T sur l'axe
	v = V[2] * B[1][1] - V[1] * B[2][1];						// projection de V sur l'axe
	somme = (a[1] * Bf[2][1] + a[2] * Bf[1][1] +
			 b[0] * Bf[0][2] + b[2] * Bf[0][0]);				// ra + rb
	
	TRANS_COLL_OBB(8)


	// -------------- Axe (A0 x B2) -------------- //
	t = T[2] * B[1][2] - T[1] * B[2][2];						// projection de T sur l'axe
	v = V[2] * B[1][2] - V[1] * B[2][2];						// projection de V sur l'axe
	somme = (a[1] * Bf[2][2] + a[2] * Bf[1][2] +
			 b[0] * Bf[0][1] + b[1] * Bf[0][0]);				// ra + rb
	
	TRANS_COLL_OBB(9)
	

	// -------------- Axe (A1 x B0) -------------- //
	t = T[0] * B[2][0] - T[2] * B[0][0];						// projection de T sur l'axe
	v = V[0] * B[2][0] - V[2] * B[0][0];						// projection de V sur l'axe
	somme = (a[0] * Bf[2][0] + a[2] * Bf[0][0] +
			 b[1] * Bf[1][2] + b[2] * Bf[1][1]);				// ra + rb
	
	TRANS_COLL_OBB(1)

	// -------------- Axe (A1 x B1) -------------- //
	t = T[0] * B[2][1] - T[2] * B[0][1];						// projection de T sur l'axe
	v = V[0] * B[2][1] - V[2] * B[0][1];						// projection de V sur l'axe
	somme = (a[0] * Bf[2][1] + a[2] * Bf[0][1] +
			 b[0] * Bf[1][2] + b[2] * Bf[1][0]);				// ra + rb
	
	TRANS_COLL_OBB(10)
	

	// -------------- Axe (A1 x B2) -------------- //
	t = T[0] * B[2][2] - T[2] * B[0][2];						// projection de T sur l'axe
	v = V[0] * B[2][2] - V[2] * B[0][2];						// projection de V sur l'axe
	somme = (a[0] * Bf[2][2] + a[2] * Bf[0][2] +
			 b[0] * Bf[1][1] + b[1] * Bf[1][0]);				// ra + rb
	
	TRANS_COLL_OBB(11)


	// -------------- Axe (A2 x B0) -------------- //
	t = T[1] * B[0][0] - T[0] * B[1][0];						// projection de T sur l'axe
	v = V[1] * B[0][0] - V[0] * B[1][0];						// projection de V sur l'axe
	somme = (a[0] * Bf[1][0] + a[1] * Bf[0][0] +
			 b[1] * Bf[2][2] + b[2] * Bf[2][1]);				// ra + rb

	TRANS_COLL_OBB(12)


	// -------------- Axe (A2 x B1) -------------- //
	t = T[1] * B[0][1] - T[0] * B[1][1];						// projection de T sur l'axe
	v = V[1] * B[0][1] - V[0] * B[1][1];						// projection de V sur l'axe
	somme = (a[0] * Bf[1][1] + a[1] * Bf[0][1] +
			 b[0] * Bf[2][2] + b[2] * Bf[2][0]);				// ra + rb
	
	TRANS_COLL_OBB(13)


	// -------------- Axe (A2 x B2) -------------- //
	t = T[1] * B[0][2] - T[0] * B[1][2];						// projection de T sur l'axe
	v = V[1] * B[0][2] - V[0] * B[1][2];						// projection de V sur l'axe
	somme = (a[0] * Bf[1][2] + a[1] * Bf[0][2] +
			 b[0] * Bf[2][1] + b[1] * Bf[2][0]);				// ra + rb
	
	TRANS_COLL_OBB(14)


	

	if(resmin<0)		return -1;			// déjà intersection - pas d'axe.
	
	return 1;								// Intersection - axe renvoyé dans 'axis', et valeur de translation dans 'result'.
}

