
#ifndef RENDERER_MODEL_MD2
#define RENDERER_MODEL_MD2

#include "stdlib.h"
#include "stdio.h"
#include "math.h"
#include <vector>
#include "ModelStruct.h"
#include "Model.h"

#include "MemoryManager/DebugNew.h"

namespace RenderSystem
{
	#define MD2_MAX_TRIANGLES		4096
	#define MD2_MAX_VERTICES		2048
	#define MD2_MAX_TEXCOORDS		2048
	#define MD2_MAX_FRAMES			512
	#define MD2_MAX_SKINS			32
	#define MD2_MAX_FRAMESIZE		(MD2_MAX_VERTICES * 4 + 128)
	#define NUMVERTEXNORMALS		162
	#define MD2_FRAME_TIME			(1000.0f*(1.0f/12.0f))	//la durée d'une frame en millisecond
															//TACTIC : 1 frame dure 1/25 de seconde

	#define MD2_DEFAULT_LIMIT_TIME_FOR_ANIM	40.0f	//la durée a atteindre pour autorisé l'animation(24fps)

	//////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////Structure servant au chargement d'un md2//////////////////////////////
	//////////////////////////////////////////////////////////////////////////////////////////////

	/**
	*	Structure stockant l'entête d'un fichier md2
	*/
	struct md2_file_header
	{ 
		int magic;					// identifie le fichier
		int version;				// la version md2 (doit être 8)
		int skinWidth;				// la largeur du skin en pixel
		int skinHeight;				// la hauteur du skin en pixel
		int frameSize;				// la taille de chaque frame (en byte)
		int numSkins;				// le nombre de skin associer au model
		int numVertices;			// le nombre de vertices (constant pour chaque frame)
		int numTexCoords;			// le nombre de coordonnée de texture (constant pour chaque frame)
		int numTriangles;			// le nombre de triangle (constant pour chaque frame)
		int numGlCommands;			// le nombre de command OpenGL
		int numFrames;				// le nombre de frame
		int offsetSkins;			// l'offset des donnée du skin dans le fichier
		int offsetTexCoords;		// l'offset des coordonnées de texture dans le fichier
		int offsetTriangles;		// l'offset des données des faces dans le fichier
		int offsetFrames;			// l'offset des donnée des frame dans le fichier
		int offsetGlCommands;		// l'offset des commandes OpenGL dans le fichier
		int offsetEnd;				// l'offset de la fin du fichier
	};

	/**
	*	Structure stockant les informations d'un vertex qui doit être modifier pour l'affichage
	*/
	struct md2_alias_triangle
	{
		BYTE vertex[3];
		BYTE lightNormalIndex;
	};
	/**
	* association position du vertex et normal
	*/
	struct md2_vertex
	{
		float pos[3];
		float normal[3];
	};

	/**
	*	Structure stockant les informations de chargement d'une frame et son nom
	*/
	struct md2_alias_frame_info_load
	{
		float scale[3];
		float translate[3];
		char name[16];
		md2_alias_triangle vertex[1];
	};

	/**
	*	Structure stockant les informations d'une face
	*/
	struct md2_triangle_info_load
	{
		short vertexIndices[3];
		short textureIndices[3];
	};

	/**
	*	Structure stockant les informations de chargement d'une frame avec ces vertices
	*/
	struct md2_frame_info_load
	{
		char name[16];
		md2_vertex* vertices;		//vertices = new vertex[md2_file_header.numVertices];
		float* trisNormal;			//les normal des triangles de taille : md2_file_header.numVertices*3
	};

	/**
	*	Structure stockant les coordonnées de textures (à normalisé avec la taille du skin)
	*/
	struct md2_textureCoordinate_info_load
	{
		short s, t;
	};


	/**
	*	Structure stockant les nom des textures-skin
	*/
	typedef char md2_skin_load[64];


	/**
	*	Structure utilisé pour comptabilisé les couples (vertex,texCoord).
	*/
	struct md2_vtn
	{
		/**
		* l'indice de coordonnée de texture dans md2_textureCoordinate_info_load
		*/
		float it;
		/**
		* l'indice du vertex dans md2_vertex
		*/
		float iv;
		/**
		* position x,y,z du vertex
		*/
		float v[3];
		/**
		* coordonnée de texture u,v du vertex
		*/
		float t[2];
		/**
		* coordonnée de texture u,v du vertex
		*/
		float n[2];
	};




	/**
	*	Cette classe implémente l'interface Model pour la manipulation de model animé
	* de type wavefront MD2.(un format utilisé par idSoftware pour QuakeII.
	* @author Hillaire Sébastien
	*/
	class ModelMD2 : public Model
	{
	private:

		/**
		*	Permet de savori si un caractère est un chiffre
		*
		* @param c : le caractère a testé
		* @return true si le caractère est un chiffre
		*/
		bool isDigit(char c);

		/**
		*	Ajoute le couple (t,v->pos) s'il n'existe pas déjà et retourne l'id de se vertex pour le triangle.
		*
		* @param vect : le vector contenant les couple finaux correspondant au tableau vertex et texCoord
		* @param t : les coordonnées de texture
		* @param v : la position du vertex
		*
		* @return le numéro du vertex por le rendu du triangle
		*/
//		unsigned int addVTgetTid(std::vector<md2_vt>* vect, md2_textureCoordinate_info_load* t, md2_vertex* v);

		/**
		*	Permet de calculé les info nécessaire pour chaque frame au chargement.
		* ne sert plus a rien dans cette version simplifier du loader pour TACTIC.
		*/
		void calcFrameData();

	protected:

		/**
		*	Les différentes animations disponible pour ce md2
		*/
		Animation* anims;

		/**
		* la durée a atteindre pour autorisé l'animation(24fps)
		*/
		static float limitTimeForAnim;

	public:

		/**
		* Le constructeur
		*/
		ModelMD2(void);

		/**
		* Le destructeur virtuel
		*/
		virtual ~ModelMD2(void);

		/**
		* Permet de charger le model à partir d'un fichier.
		*
		* @param path le pointeur sur le chemin du fichier
		* @param _name le pointeur sur le nom du model(une copie est effectuée)
		* @return true si le fichier est chargé
		*/
		bool load(char *path, char* _name);

		/**
		*	Permet d'initialisé une instance de model. On règle les tableau de pointeur pour l'instance
		* la aabb et l'animation.
		*
		* @param mi : le pointeur l'instance du model a créer.
		*/
		void initInstance(ModelInstance *mi);

		/**
		* Permet de relacher un instance.(rend la mémoire utilisé par celle ci).
		*
		* @param mi : l'instance de ce model a initialisé.
		*/
		virtual void releaseInstance(ModelInstance *mi);

		/**
		*	Fonction virtuelle pure permettant d'updaté une instance de model suivant le temps
		* écouler. Seul la aabb et l'état d'animation sont updatés.
		*
		* @param mi : l'instance de ce model a updaté.
		* @param time_ms : le temp écouler depuis la dernière frame en milliseconde
		*/
		virtual void updateInstance_aabbAndAnimState(ModelInstance *mi, float time_ms);

		/**
		*	Fonction virtuelle pure permettant d'updaté une instance de model suivant le temps
		* écouler. Seul la aabb et l'état d'animation sont updatés.
		*
		* @param mi : l'instance de ce model a updaté.
		*/
		virtual void updateInstance_geometry(ModelInstance *mi);
		
		/**
		*	Fonction permettant de changer l'échelle de l'objet. A faire de préference avant, enregistrement
		* des instances auprès du Renderer. Pour être sur, le faire juste après le chargement.
		*
		* @param factor : le facteur de changement de taille. Pour un objet 2 fois plus grand, factor=2.0f.
		*/
		void scale(float factor);

		/**
		*	Permet de régler la durée a atteindre pour autorisé l'update de la géométrie des models MD2.
		* Ceci et un optimisation empechant le calcul des interpolation à chaque frame.
		*
		* @post limitTimeForAnim est dans une borne de valeur valide
		*/
		static void setLimitTimeForAnim(float limitTFA)
		{
			limitTimeForAnim = limitTFA>=0 ? limitTFA : 0;
		}

		/**
		*	Permet d'accéder à la durée a atteindre pour autorisé l'update de la géométrie des models MD2.
		* Ceci et un optimisation empechant le calcul des interpolation à chaque frame.
		*/
		static float getLimitTimeForAnim()
		{
			return limitTimeForAnim;
		}

		void animationLoop(int animNum, bool loop);

	};
};// namespace RenderSystem

#include "MemoryManager/DebugNewOff.h"

#endif
