/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///																																  ///
///		FICHIER :	Rapid.h																									  ///
///																																  ///
///		NATURE	:	The rapid Algorithm!!                                                         								  ///
///																																  ///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





#ifndef RAPID_H
#define RAPID_H



#include	"..\Basic\ZooMatrix.h"


///////////////////////////////////////////
/// RAPID API RETURN VALUES				///
///////////////////////////////////////////

const int RAPID_OK = 10; 
	// Used by all API routines except constructors and destructors.


const int RAPID_ERR_MODEL_OUT_OF_MEMORY = 11; 
	// Returned when an API function cannot obtain enough memory to store
	// or process a RAPID_model object.


const int RAPID_ERR_COLLIDE_OUT_OF_MEMORY = 12;
	// Returned when RAPID_Collide() cannot allocate enough storage to hold
	// collision information.  In this case, there is as much collision
	// detection information available as could be allocated for.


const int RAPID_ERR_UNPROCESSED_MODEL = 13;
	// Returned when an unprocessed model is passed to a function which
	// expects only processed models, such as RAPID_Collide().


const int RAPID_ERR_BUILD_OUT_OF_SEQUENCE = 14;
	// Returned when: 
	//       1. AddTri() is called before BeginModel().  The triangle will 
	//          be added anyway as if BeginModel() had been previously called.
	//       2. BeginModel() is called immediately after AddTri().  The
	//          model will be placed into an empty initial state.  
	// This error code is something like a warning: the invoked
	// operation takes place anyway, but the returned error code may tip
	// off the client that something out of the ordinary is happenning.


const int RAPID_ERR_BUILD_EMPTY_MODEL = 15; 
	// Returned when EndModel() is called on a model to which no
	// triangles have been added.  This is similar in spirit to the
	// OUT_OF_SEQUENCE return code, except that the requested operation
	// has FAILED -- the model remains "unprocessed".









///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///			tri STRUCTURE
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct tri
{
	int		id;
	float	p1[3], p2[3], p3[3];
};




///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///			box CLASS
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class box
{
public:

	// placement in parent's space
	// box to parent space: x_m = pR*x_b + pT
	// parent to box space: x_b = pR.T()*(x_m - pT)
	float	pR[3][3];
	float	pT[3];
  
	// dimensions
	float	d[3];		// this is "radius", that is, half the measure of a side length
						// correspond en fait au stockage des 3 coordonnees de l'OBB, suivant x, y et z

	box		*P;			// points to but does not "own".  

	int		leaf() 		{	return unsigned int(P) & 1;	} 
	float	size()		{	return d[0];		} 

	int		split_recurse(int *t, int n);
	int		split_recurse(int *t);               // specialized for leaf nodes
};




const int RAPID_BUILD_STATE_CONST		= 0;    // "empty" state, after constructor
const int RAPID_BUILD_STATE_BEGIN		= 1;    // after BeginModel()
const int RAPID_BUILD_STATE_ADDTRI		= 2;    // after AddTri()
const int RAPID_BUILD_STATE_PROCESSED	= 3;	// after EndModel()






///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///			RAPID_model Class
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class RAPID_model
{

public:

	box		*b;
	int		num_boxes_alloced;

	tri		*tris;
	int		num_tris;
	int		num_tris_alloced;

	int		build_state;
  
	int		build_hierarchy();
  
	friend	int RAPID_Collide(float R1[3][3], float T1[3], float s1, RAPID_model *RAPID_model1, 
							  float R2[3][3], float T2[3], float s2, RAPID_model *RAPID_model2,
							  int flag);

public:

			RAPID_model();
			~RAPID_model();
  
	int		BeginModel();
	int		AddTri(const float *p1, const float *p2, const float *p3, int id);
	int		EndModel();

};









const int RAPID_ALL_CONTACTS  = 1;			// Find all pairwise intersecting triangles
const int RAPID_FIRST_CONTACT = 2;			// Just report one intersecting triangle pair, if there are any.
                                 





///////////////////////////////////////////////////////////////////////////
/// RAPID_Collide														///
///////////////////////////////////////////////////////////////////////////
///
/// This is the collision query invocation.  It assumes that the 
/// models are not being scaled up or down, but have their native
/// dimensions.
///
int	RAPID_Collide(float R1[3][3], float T1[3], RAPID_model *o1,
				  float R2[3][3], float T2[3], RAPID_model *o2,
				  int flag = RAPID_ALL_CONTACTS);

int RAPID_Collide_trans(float R1[3][3], float T1[3], float V1[3], RAPID_model *RAPID_model1,
   						float R2[3][3], float T2[3], float V2[3], RAPID_model *RAPID_model2,
						int flag = RAPID_ALL_CONTACTS);



///////////////////////////////////////////////////////////////////////////
/// RAPID_Collide														///
///////////////////////////////////////////////////////////////////////////
///
/// This collision query permits the models to each be scaled by
/// some positive factor (must be greater than 0).
///
int RAPID_Collide(float R1[3][3], float T1[3], float s1, RAPID_model *o1,
				  float R2[3][3], float T2[3], float s2, RAPID_model *o2,
				  int flag = RAPID_ALL_CONTACTS);

int RAPID_Collide_trans(float R1[3][3], float T1[3], float s1, float V1[3], RAPID_model *RAPID_model1,
						float R2[3][3], float T2[3], float s2, float V2[3], RAPID_model *RAPID_model2,
						int flag = RAPID_ALL_CONTACTS);





struct collision_pair
{
	int id1;
	int id2;
};





extern  int		RAPID_num_box_tests;
extern  int		RAPID_num_tri_tests;
extern  int		RAPID_num_contacts;

extern  int		RAPID_is_contact_trans;
extern	float	RAPID_coeff;
extern	int		RAPID_tri_id1,	RAPID_tri_id2;
extern	int		RAPID_axid1,	RAPID_axid2;

extern  struct	collision_pair	*RAPID_contact;






#endif








