
#include "ModelMD2.h"
#include "MemoryManager/DebugNew.h"

using namespace RenderSystem;


float ModelMD2::limitTimeForAnim;


float md2VertexNormals[NUMVERTEXNORMALS][3] =
{
	{-0.525731f, 0.000000f, 0.850651f}, 
	{-0.442863f, 0.238856f, 0.864188f}, 
	{-0.295242f, 0.000000f, 0.955423f}, 
	{-0.309017f, 0.500000f, 0.809017f}, 
	{-0.162460f, 0.262866f, 0.951056f}, 
	{0.000000f, 0.000000f, 1.000000f}, 
	{0.000000f, 0.850651f, 0.525731f}, 
	{-0.147621f, 0.716567f, 0.681718f}, 
	{0.147621f, 0.716567f, 0.681718f}, 
	{0.000000f, 0.525731f, 0.850651f}, 
	{0.309017f, 0.500000f, 0.809017f}, 
	{0.525731f, 0.000000f, 0.850651f}, 
	{0.295242f, 0.000000f, 0.955423f}, 
	{0.442863f, 0.238856f, 0.864188f}, 
	{0.162460f, 0.262866f, 0.951056f}, 
	{-0.681718f, 0.147621f, 0.716567f}, 
	{-0.809017f, 0.309017f, 0.500000f}, 
	{-0.587785f, 0.425325f, 0.688191f}, 
	{-0.850651f, 0.525731f, 0.000000f}, 
	{-0.864188f, 0.442863f, 0.238856f}, 
	{-0.716567f, 0.681718f, 0.147621f}, 
	{-0.688191f, 0.587785f, 0.425325f}, 
	{-0.500000f, 0.809017f, 0.309017f}, 
	{-0.238856f, 0.864188f, 0.442863f}, 
	{-0.425325f, 0.688191f, 0.587785f}, 
	{-0.716567f, 0.681718f, -0.147621f}, 
	{-0.500000f, 0.809017f, -0.309017f}, 
	{-0.525731f, 0.850651f, 0.000000f}, 
	{0.000000f, 0.850651f, -0.525731f}, 
	{-0.238856f, 0.864188f, -0.442863f}, 
	{0.000000f, 0.955423f, -0.295242f}, 
	{-0.262866f, 0.951056f, -0.162460f}, 
	{0.000000f, 1.000000f, 0.000000f}, 
	{0.000000f, 0.955423f, 0.295242f}, 
	{-0.262866f, 0.951056f, 0.162460f}, 
	{0.238856f, 0.864188f, 0.442863f}, 
	{0.262866f, 0.951056f, 0.162460f}, 
	{0.500000f, 0.809017f, 0.309017f}, 
	{0.238856f, 0.864188f, -0.442863f}, 
	{0.262866f, 0.951056f, -0.162460f}, 
	{0.500000f, 0.809017f, -0.309017f}, 
	{0.850651f, 0.525731f, 0.000000f}, 
	{0.716567f, 0.681718f, 0.147621f}, 
	{0.716567f, 0.681718f, -0.147621f}, 
	{0.525731f, 0.850651f, 0.000000f}, 
	{0.425325f, 0.688191f, 0.587785f}, 
	{0.864188f, 0.442863f, 0.238856f}, 
	{0.688191f, 0.587785f, 0.425325f}, 
	{0.809017f, 0.309017f, 0.500000f}, 
	{0.681718f, 0.147621f, 0.716567f}, 
	{0.587785f, 0.425325f, 0.688191f}, 
	{0.955423f, 0.295242f, 0.000000f}, 
	{1.000000f, 0.000000f, 0.000000f}, 
	{0.951056f, 0.162460f, 0.262866f}, 
	{0.850651f, -0.525731f, 0.000000f}, 
	{0.955423f, -0.295242f, 0.000000f}, 
	{0.864188f, -0.442863f, 0.238856f}, 
	{0.951056f, -0.162460f, 0.262866f}, 
	{0.809017f, -0.309017f, 0.500000f}, 
	{0.681718f, -0.147621f, 0.716567f}, 
	{0.850651f, 0.000000f, 0.525731f}, 
	{0.864188f, 0.442863f, -0.238856f}, 
	{0.809017f, 0.309017f, -0.500000f}, 
	{0.951056f, 0.162460f, -0.262866f}, 
	{0.525731f, 0.000000f, -0.850651f}, 
	{0.681718f, 0.147621f, -0.716567f}, 
	{0.681718f, -0.147621f, -0.716567f}, 
	{0.850651f, 0.000000f, -0.525731f}, 
	{0.809017f, -0.309017f, -0.500000f}, 
	{0.864188f, -0.442863f, -0.238856f}, 
	{0.951056f, -0.162460f, -0.262866f}, 
	{0.147621f, 0.716567f, -0.681718f}, 
	{0.309017f, 0.500000f, -0.809017f}, 
	{0.425325f, 0.688191f, -0.587785f}, 
	{0.442863f, 0.238856f, -0.864188f}, 
	{0.587785f, 0.425325f, -0.688191f}, 
	{0.688191f, 0.587785f, -0.425325f}, 
	{-0.147621f, 0.716567f, -0.681718f}, 
	{-0.309017f, 0.500000f, -0.809017f}, 
	{0.000000f, 0.525731f, -0.850651f}, 
	{-0.525731f, 0.000000f, -0.850651f}, 
	{-0.442863f, 0.238856f, -0.864188f}, 
	{-0.295242f, 0.000000f, -0.955423f}, 
	{-0.162460f, 0.262866f, -0.951056f}, 
	{0.000000f, 0.000000f, -1.000000f}, 
	{0.295242f, 0.000000f, -0.955423f}, 
	{0.162460f, 0.262866f, -0.951056f}, 
	{-0.442863f, -0.238856f, -0.864188f}, 
	{-0.309017f, -0.500000f, -0.809017f}, 
	{-0.162460f, -0.262866f, -0.951056f}, 
	{0.000000f, -0.850651f, -0.525731f}, 
	{-0.147621f, -0.716567f, -0.681718f}, 
	{0.147621f, -0.716567f, -0.681718f}, 
	{0.000000f, -0.525731f, -0.850651f}, 
	{0.309017f, -0.500000f, -0.809017f}, 
	{0.442863f, -0.238856f, -0.864188f}, 
	{0.162460f, -0.262866f, -0.951056f}, 
	{0.238856f, -0.864188f, -0.442863f}, 
	{0.500000f, -0.809017f, -0.309017f}, 
	{0.425325f, -0.688191f, -0.587785f}, 
	{0.716567f, -0.681718f, -0.147621f}, 
	{0.688191f, -0.587785f, -0.425325f}, 
	{0.587785f, -0.425325f, -0.688191f}, 
	{0.000000f, -0.955423f, -0.295242f}, 
	{0.000000f, -1.000000f, 0.000000f}, 
	{0.262866f, -0.951056f, -0.162460f}, 
	{0.000000f, -0.850651f, 0.525731f}, 
	{0.000000f, -0.955423f, 0.295242f}, 
	{0.238856f, -0.864188f, 0.442863f}, 
	{0.262866f, -0.951056f, 0.162460f}, 
	{0.500000f, -0.809017f, 0.309017f}, 
	{0.716567f, -0.681718f, 0.147621f}, 
	{0.525731f, -0.850651f, 0.000000f}, 
	{-0.238856f, -0.864188f, -0.442863f}, 
	{-0.500000f, -0.809017f, -0.309017f}, 
	{-0.262866f, -0.951056f, -0.162460f}, 
	{-0.850651f, -0.525731f, 0.000000f}, 
	{-0.716567f, -0.681718f, -0.147621f}, 
	{-0.716567f, -0.681718f, 0.147621f}, 
	{-0.525731f, -0.850651f, 0.000000f}, 
	{-0.500000f, -0.809017f, 0.309017f}, 
	{-0.238856f, -0.864188f, 0.442863f}, 
	{-0.262866f, -0.951056f, 0.162460f}, 
	{-0.864188f, -0.442863f, 0.238856f}, 
	{-0.809017f, -0.309017f, 0.500000f}, 
	{-0.688191f, -0.587785f, 0.425325f}, 
	{-0.681718f, -0.147621f, 0.716567f}, 
	{-0.442863f, -0.238856f, 0.864188f}, 
	{-0.587785f, -0.425325f, 0.688191f}, 
	{-0.309017f, -0.500000f, 0.809017f}, 
	{-0.147621f, -0.716567f, 0.681718f}, 
	{-0.425325f, -0.688191f, 0.587785f}, 
	{-0.162460f, -0.262866f, 0.951056f}, 
	{0.442863f, -0.238856f, 0.864188f}, 
	{0.162460f, -0.262866f, 0.951056f}, 
	{0.309017f, -0.500000f, 0.809017f}, 
	{0.147621f, -0.716567f, 0.681718f}, 
	{0.000000f, -0.525731f, 0.850651f}, 
	{0.425325f, -0.688191f, 0.587785f}, 
	{0.587785f, -0.425325f, 0.688191f}, 
	{0.688191f, -0.587785f, 0.425325f}, 
	{-0.955423f, 0.295242f, 0.000000f}, 
	{-0.951056f, 0.162460f, 0.262866f}, 
	{-1.000000f, 0.000000f, 0.000000f}, 
	{-0.850651f, 0.000000f, 0.525731f}, 
	{-0.955423f, -0.295242f, 0.000000f}, 
	{-0.951056f, -0.162460f, 0.262866f}, 
	{-0.864188f, 0.442863f, -0.238856f}, 
	{-0.951056f, 0.162460f, -0.262866f}, 
	{-0.809017f, 0.309017f, -0.500000f}, 
	{-0.864188f, -0.442863f, -0.238856f}, 
	{-0.951056f, -0.162460f, -0.262866f}, 
	{-0.809017f, -0.309017f, -0.500000f}, 
	{-0.681718f, 0.147621f, -0.716567f}, 
	{-0.681718f, -0.147621f, -0.716567f}, 
	{-0.850651f, 0.000000f, -0.525731f}, 
	{-0.688191f, 0.587785f, -0.425325f}, 
	{-0.587785f, 0.425325f, -0.688191f}, 
	{-0.425325f, 0.688191f, -0.587785f}, 
	{-0.425325f, -0.688191f, -0.587785f}, 
	{-0.587785f, -0.425325f, -0.688191f}, 
	{-0.688191f, -0.587785f, -0.425325f}
};

ModelMD2::ModelMD2(void)
{
	this->texCoords = NULL;
	this->triangles = NULL;
	this->nbAnimation = 0;
	this->nbDegeneratedTris = 0;
	this->nbTris = 0;
	this->nbVertex = 0;
}

ModelMD2::~ModelMD2(void)
{
	delete [] this->name;
	delete [] this->texCoords;
	delete [] this->triangles;
	for(int i=0;i<this->nbAnimation;i++)
	{
		for(int j=0;j<this->anims[i].nbFrame;j++)
		{
			delete [] this->anims[i].frames[j].vertex;
			delete [] this->anims[i].frames[j].normal;
			delete [] this->anims[i].frames[j].trisNormal;
		}
		delete [] this->anims[i].frames;
	}
	delete [] this->anims;
}

bool ModelMD2::load(char* path, char* _name)
{
	//les variables temporaires

	bool ret = false;
	FILE *f;

	float max[3],min[3];//les vertices max et min pour aabb
	for(int i=0;i<3;i++)
	{
		min[i]=999999.0f;
		max[i]=-999999.0f;
	}
	nbDegeneratedTris = 0;

	f = fopen (path,"rb");

	md2_frame_info_load* frameLoad;
	if(f!=NULL)
	{
		//on affecte le nom
		this->name = new char[strlen(_name)+1];
		strcpy(this->name,_name);
		this->name[strlen(_name)]='\0';

		/**************************************************
		**** On charge les informations du fichier md2 ****
		***************************************************/
		md2_file_header md2Header;
		md2_textureCoordinate_info_load* texCoordLoad;
		md2_triangle_info_load* triangleInfoLoad;

		//////on lit l'entête
		fread(&md2Header, sizeof(md2_file_header), 1, f);
		if(md2Header.version!=8)
		{
			printf("Version invalid : %d.\n",md2Header.version);
			return false;
		}

		//////On lit les frames
		//pour chaque frame on alloue la mémoire
		frameLoad = new md2_frame_info_load[md2Header.numFrames];
		for(int i=0;i<md2Header.numFrames;i++)
		{
			frameLoad[i].vertices=new md2_vertex[md2Header.numVertices];
			frameLoad[i].trisNormal=new float[md2Header.numTriangles*3];
		}
		//////mémoire pour le skin
		char skinsLoad[64];
		//////On alloue la mémoire pour les coordonées de textures
		texCoordLoad = new md2_textureCoordinate_info_load[md2Header.numTexCoords];
		//////On alloue la mémoire pour les index pour les triangles
		triangleInfoLoad = new md2_triangle_info_load[md2Header.numTriangles];



		// On ce place pour la lecture des skins
		fseek(f, md2Header.offsetSkins, SEEK_SET);
		// on lit le skins
		if(md2Header.numSkins==1)
			fread(skinsLoad, sizeof(md2_skin_load), md2Header.numSkins, f);//je récupère le skin mais ne l'utilise pas
		

		// On ce place pour la lecture des coordonnées de textures
		fseek(f, md2Header.offsetTexCoords, SEEK_SET);
		// on lit les coordonnées de textures
		fread(texCoordLoad, sizeof(md2_textureCoordinate_info_load), md2Header.numTexCoords, f);


		// On ce place pour la lecture des infos de triangles
		fseek(f, md2Header.offsetTriangles, SEEK_SET);
		// on lit les infos de triangles
		fread(triangleInfoLoad, sizeof(md2_triangle_info_load), md2Header.numTriangles, f);
			
		
		// On ce place pour la lecture des infos des frames
		fseek(f, md2Header.offsetFrames, SEEK_SET);
		//on créer un buffer qui contiendra les animations
		unsigned char buffer[MD2_MAX_FRAMESIZE];
		//////On lit les frames
		for (int i=0; i < md2Header.numFrames; i++)
		{
			// on fait pointer le alias temporaire sur le buffer temp;
			md2_alias_frame_info_load *pFrame = (md2_alias_frame_info_load *) &buffer[0];

			// Lit la frame de l'animation courante
			fread(pFrame, 1, md2Header.frameSize, f);

			// copie le nom de l'animation
			strcpy(frameLoad[i].name, pFrame->name);
				
			// pointe sur le tableau de vertex final(transformé)
			md2_vertex *pVertices = frameLoad[i].vertices;

			for (int j=0; j < md2Header.numVertices; j++)
			{
				pVertices[j].normal[0] = pVertices[j].normal[1] = pVertices[j].normal[2] = 0;
			}
			//on transforme chaque vertices pour avoir leur coordonnée final
			//REM : on inverse Y et Z et une négationne Z pour un bonne transformation(ah! Carmack...)
			//on ajoute normal
			for (int j=0; j < md2Header.numVertices; j++)
			{
				pVertices[j].pos[0] = pFrame->vertex[j].vertex[0] * pFrame->scale[0] + pFrame->translate[0];
				pVertices[j].pos[2] = -1 * (pFrame->vertex[j].vertex[1] * pFrame->scale[1] + pFrame->translate[1]);
				pVertices[j].pos[1] = pFrame->vertex[j].vertex[2] * pFrame->scale[2] + pFrame->translate[2];
			}
			float l;
			int ind;
			float v01x,v01y,v01z,v02x,v02y,v02z;
			float fx,fy,fz;
			//normalisation des normals
			for(int t=0;t<md2Header.numTriangles;t++)
			{
				//vecteur allant du point 1 au point 0
				v01x = pVertices[triangleInfoLoad[t].vertexIndices[1]].pos[0] - pVertices[triangleInfoLoad[t].vertexIndices[0]].pos[0];
				v01y = pVertices[triangleInfoLoad[t].vertexIndices[1]].pos[1] - pVertices[triangleInfoLoad[t].vertexIndices[0]].pos[1];
				v01z = pVertices[triangleInfoLoad[t].vertexIndices[1]].pos[2] - pVertices[triangleInfoLoad[t].vertexIndices[0]].pos[2];
				//vecteur allant du point 2 au point 0
				v02x = pVertices[triangleInfoLoad[t].vertexIndices[2]].pos[0] - pVertices[triangleInfoLoad[t].vertexIndices[0]].pos[0];
				v02y = pVertices[triangleInfoLoad[t].vertexIndices[2]].pos[1] - pVertices[triangleInfoLoad[t].vertexIndices[0]].pos[1];
				v02z = pVertices[triangleInfoLoad[t].vertexIndices[2]].pos[2] - pVertices[triangleInfoLoad[t].vertexIndices[0]].pos[2];
				//produit vectoriel pour obtenir la normal
				fx= v01y*v02z - v01z*v02y;
				fy= v01z*v02x - v01x*v02z;
				fz= v01x*v02y - v01y*v02x;
				//normalisation de la normal
				l = -sqrt(fx*fx + fy*fy + fz*fz);	//	je mes un - ainsi les normal seront calculé dans le bon sens car
				fx/=l;								//carmack utilise des tris en CW pour le front-face.
				fy/=l;
				fz/=l;
				//affectation
				pVertices[triangleInfoLoad[t].vertexIndices[0]].normal[0] += fx;
				pVertices[triangleInfoLoad[t].vertexIndices[0]].normal[1] += fy;
				pVertices[triangleInfoLoad[t].vertexIndices[0]].normal[2] += fz;
				pVertices[triangleInfoLoad[t].vertexIndices[1]].normal[0] += fx;
				pVertices[triangleInfoLoad[t].vertexIndices[1]].normal[1] += fy;
				pVertices[triangleInfoLoad[t].vertexIndices[1]].normal[2] += fz;
				pVertices[triangleInfoLoad[t].vertexIndices[2]].normal[0] += fx;
				pVertices[triangleInfoLoad[t].vertexIndices[2]].normal[1] += fy;
				pVertices[triangleInfoLoad[t].vertexIndices[2]].normal[2] += fz;

				frameLoad[i].trisNormal[t*3   ] = fx;
				frameLoad[i].trisNormal[t*3 +1] = fy;
				frameLoad[i].trisNormal[t*3 +2] = fz;
			}
			//normalisation des normals de triangles
			for(int t=0;t<md2Header.numTriangles;t++)
			{
				for(int j=0; j<3; j++)
				{
					ind = triangleInfoLoad[t].vertexIndices[j];
					l = sqrt(	pVertices[ind].normal[0]*pVertices[ind].normal[0] +
								pVertices[ind].normal[1]*pVertices[ind].normal[1] +
								pVertices[ind].normal[2]*pVertices[ind].normal[2] );
					if(l!=0)
					{
						pVertices[ind].normal[0] /= l;
						pVertices[ind].normal[1] /= l;
						pVertices[ind].normal[2] /= l;
					}
				}
			}
		}

		/*********************************************************
		**** Convertion du md2 dans mon format d'informations ****
		*********************************************************/

		int size;
		int curAnimNum;
		int i3;

		//on supprime le numéro de l'animation dans le nom de l'anim
		for(int i=0;i<md2Header.numFrames;i++)
		{
			//2 chiffre possible pour numéro de frame dans une anim
			size = strlen(frameLoad[i].name);
			if( (size>=1) && isDigit(frameLoad[i].name[size-1]))
				frameLoad[i].name[size-1] = '\0';
			if( (size>=2) && isDigit(frameLoad[i].name[size-2]))
				frameLoad[i].name[size-2] = '\0';
		}
		//on compte le nombre d'animation suivant le nom
		curAnimNum = 0;
		this->nbAnimation = 1;
		for(int i=1;i<md2Header.numFrames;i++)
		{
			if(strcmp(frameLoad[curAnimNum].name,frameLoad[i].name)!=0)
			{
				this->nbAnimation++;
				curAnimNum = i;
			}
		}
		//on compte les frame des différentes animations
		this->anims = new Animation[this->nbAnimation];
		curAnimNum = 0;
		strcpy(this->anims[curAnimNum].name, frameLoad[curAnimNum].name);
		this->anims[curAnimNum].nbFrame = 1;
		for(int i=1;i<md2Header.numFrames;i++)
		{
			if(strcmp(this->anims[curAnimNum].name,frameLoad[i].name)!=0)
			{
				//on a découvert une nouvelle animation
				curAnimNum++;
				strcpy(this->anims[curAnimNum].name, frameLoad[i].name);
				this->anims[curAnimNum].nbFrame = 1;

			}
			else
			{
				//on a une nouvelle frame de l'animation courante
				this->anims[curAnimNum].nbFrame++;
			}
		}
		//allocation mémoire de chaque frame
		this->nbTris = md2Header.numTriangles;
		this->nbVertex = md2Header.numTriangles*3;

		this->triangles = new unsigned short[this->nbTris*3];
		this->texCoords = new float[this->nbTris*3*2];

		//on genere le tableau d'indice des vertices pour chaques triangles
		for(int i=0;i<this->nbTris;i++)
		{
			i3 = i*3;
			//on inverse m'ordre des triangle pour avoir CCW en front face
			this->triangles[i3 +1] = i3;
			this->triangles[i3   ] = i3+1;
			this->triangles[i3 +2] = i3+2;
			//coordonnée de texture
			this->texCoords[this->triangles[i3+1]*2  ] = (float)texCoordLoad[ triangleInfoLoad[i].textureIndices[0] ].s/(float)md2Header.skinWidth;
			this->texCoords[this->triangles[i3+1]*2+1] = 1.0f - (float)texCoordLoad[ triangleInfoLoad[i].textureIndices[0] ].t/(float)md2Header.skinHeight;
			this->texCoords[this->triangles[i3+0]*2  ] = (float)texCoordLoad[ triangleInfoLoad[i].textureIndices[1] ].s/(float)md2Header.skinWidth;
			this->texCoords[this->triangles[i3+0]*2+1] = 1.0f - (float)texCoordLoad[ triangleInfoLoad[i].textureIndices[1] ].t/(float)md2Header.skinHeight;
			this->texCoords[this->triangles[i3+2]*2  ] = (float)texCoordLoad[ triangleInfoLoad[i].textureIndices[2] ].s/(float)md2Header.skinWidth;
			this->texCoords[this->triangles[i3+2]*2+1] = 1.0f - (float)texCoordLoad[ triangleInfoLoad[i].textureIndices[2] ].t/(float)md2Header.skinHeight;
		}

		for(int i=0;i<this->nbAnimation;i++)
		{
			this->anims[i].frames = new AnimationFrame[this->anims[i].nbFrame];
			for(int j=0;j<this->anims[i].nbFrame;j++)
			{
				this->anims[i].frames[j].vertex = new float[3*this->nbTris*3];	//chaque vertices : x,y,z(pas w dans TACTIC)
				this->anims[i].frames[j].trisNormal = new float[this->nbTris*3];
				this->anims[i].frames[j].normal = new float[3*this->nbTris*3];
			}
		}

		Animation* a;
		AnimationFrame* af;
		int ct;
		int t3;
		int ct3;
		md2_frame_info_load* fLoad = &frameLoad[0];
		for(int i=0;i<this->nbAnimation;i++)
		{
			a = &this->anims[i];
			a->loop = true;
			for(int j=0;j<a->nbFrame;j++)
			{
				af = &a->frames[j];
				ct = 0;
				for(int t=0;t<md2Header.numTriangles;t++)
				{
					t3 = t*3;
					ct3 = ct*3;
					af->vertex[ ct3   ] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[0] ].pos[0];
					af->vertex[ ct3 +1] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[0] ].pos[1];
					af->vertex[ ct3 +2] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[0] ].pos[2];
					af->normal[ ct3   ] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[0] ].normal[0];
					af->normal[ ct3 +1] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[0] ].normal[1];
					af->normal[ ct3 +2] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[0] ].normal[2];
					ct++;
					
					ct3 = ct*3;
					af->vertex[ ct3   ] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[1] ].pos[0];
					af->vertex[ ct3 +1] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[1] ].pos[1];
					af->vertex[ ct3 +2] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[1] ].pos[2];
					af->normal[ ct3   ] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[1] ].normal[0];
					af->normal[ ct3 +1] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[1] ].normal[1];
					af->normal[ ct3 +2] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[1] ].normal[2];
					ct++;
					
					ct3 = ct*3;
					af->vertex[ ct3   ] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[2] ].pos[0];
					af->vertex[ ct3 +1] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[2] ].pos[1];
					af->vertex[ ct3 +2] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[2] ].pos[2];
					af->normal[ ct3   ] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[2] ].normal[0];
					af->normal[ ct3 +1] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[2] ].normal[1];
					af->normal[ ct3 +2] =  fLoad->vertices[ triangleInfoLoad[t].vertexIndices[2] ].normal[2];
					ct++;

					//normal de se triangle
					af->trisNormal[t*3   ] =  fLoad->trisNormal[t*3   ];
					af->trisNormal[t*3 +1] =  fLoad->trisNormal[t*3 +1];
					af->trisNormal[t*3 +2] =  fLoad->trisNormal[t*3 +2];
				}
				fLoad++;
			}
			ret = true;
		}
		this->calcFrameData();

		//TODO indiquer quel animation ne boucle pas dans le md2

		/********** restauration de la mémoire **********/
		for(int i=0;i<md2Header.numFrames;i++)
		{
			delete [] frameLoad[i].vertices;
			delete [] frameLoad[i].trisNormal;
		}
		delete [] frameLoad;
		delete [] texCoordLoad;
		delete [] triangleInfoLoad;

		fclose(f);	//on ferme le fichier
	}

	return ret;
}

//TODO faire une foncion dinit pour delete la mémoire(pour évité delete d'un model statique si on passe dune inst sttc a dyn
void ModelMD2::initInstance(ModelInstance *mi)
{
	mi->animState.allowGeometryUpdate = false;
	mi->animState.curTime = 0;
	mi->animState.curAnim = 0;
	mi->animState.curFrame = 0;
	mi->animState.curTime = 0;
	mi->animState.nextAnim = 0;
	mi->texCoord = this->texCoords;
	mi->triangles = this->triangles;
	mi->model = this;
	mi->isGeometricalyStatic = false;
	mi->animState.nextFrame = this->anims[mi->animState.curAnim].nbFrame>1 ? 1 : 0;
	mi->animState.aabb = this->anims[mi->animState.curAnim].frames[mi->animState.curFrame].aabb;

	if(mi->vertex!=NULL) delete [] mi->vertex;
	mi->vertex = new float[mi->model->nbVertex*3];
	if(mi->normal!=NULL) delete [] mi->normal;
	mi->normal = new float[mi->model->nbVertex*3];
	if(mi->trisNormal!=NULL) delete [] mi->trisNormal;
	mi->trisNormal = new float[mi->model->nbTris*3];

	//On initialise le tableau de géométrie de l'instance
	float tmp = this->limitTimeForAnim;
	this->limitTimeForAnim = 0;
	mi->model->updateInstance_aabbAndAnimState(mi,0);
	mi->model->updateInstance_geometry(mi);
	this->limitTimeForAnim = tmp;
}

void ModelMD2::releaseInstance(ModelInstance *mi)
{
	if(mi->vertex!=NULL) delete [] mi->vertex;
	if(mi->normal!=NULL) delete [] mi->normal;
	if(mi->trisNormal!=NULL) delete [] mi->trisNormal;

	mi->vertex = NULL;
	mi->normal = NULL;
	mi->trisNormal = NULL;
	mi->texCoord = NULL;
	mi->triangles = NULL;
	mi->model = NULL;
}

void ModelMD2::scale(float factor)
{
	Animation* a;
	AnimationFrame* af;
	int vi;
	int lim = this->nbVertex; 
	for(int i=0;i<this->nbAnimation;i++)
	{
		a = &this->anims[i];
		for(int j=0;j<a->nbFrame;j++)
		{
			af = &a->frames[j];
			for(int v=0;v<lim;v++)
			{
				vi = v*3;
				af->vertex[vi  ] *= factor;
				af->vertex[vi+1] *= factor;
				af->vertex[vi+2] *= factor;
			}
			//scale de la boudingBox
			af->aabb.pos = af->aabb.pos * factor;
			af->aabb.sizex *= factor;
			af->aabb.sizey *= factor;
			af->aabb.sizez *= factor;
			af->aabb.computeLimit();
		}
	}
}

bool ModelMD2::isDigit(char c)
{
	if(	(c=='0') |
		(c=='1') |
		(c=='2') |
		(c=='3') |
		(c=='4') |
		(c=='5') |
		(c=='6') |
		(c=='7') |
		(c=='8') |
		(c=='9') )
	{
		return true;
	}
	return false;
}



void ModelMD2::calcFrameData()
{	
	//calcul des AABB
	float max[3],min[3];//les vertices max et min pour aabb
	for(int i=0;i<this->nbAnimation;i++)
	{
		for(int j=0;j<this->anims[i].nbFrame;j++)
		{
			//init par defaut
			for(int a=0;a<3;a++)
			{
				min[a]=999999.0f;
				max[a]=-999999.0f;
			}
			//recherche des min et max
			for(int iv=0;iv<this->nbVertex;iv++)
			{
				if(max[0]<this->anims[i].frames[j].vertex[iv*3 +0]) max[0]=this->anims[i].frames[j].vertex[iv*3 +0];
				if(max[1]<this->anims[i].frames[j].vertex[iv*3 +1]) max[1]=this->anims[i].frames[j].vertex[iv*3 +1];
				if(max[2]<this->anims[i].frames[j].vertex[iv*3 +2]) max[2]=this->anims[i].frames[j].vertex[iv*3 +2];
				if(min[0]>this->anims[i].frames[j].vertex[iv*3 +0]) min[0]=this->anims[i].frames[j].vertex[iv*3 +0];
				if(min[1]>this->anims[i].frames[j].vertex[iv*3 +1]) min[1]=this->anims[i].frames[j].vertex[iv*3 +1];
				if(min[2]>this->anims[i].frames[j].vertex[iv*3 +2]) min[2]=this->anims[i].frames[j].vertex[iv*3 +2];
			}
			//calcul de la AABB
			this->anims[i].frames[j].aabb.pos[0] = (max[0]+min[0])/2;
			this->anims[i].frames[j].aabb.pos[1] = (max[1]+min[1])/2;
			this->anims[i].frames[j].aabb.pos[2] = (max[2]+min[2])/2;
			this->anims[i].frames[j].aabb.sizex  = (max[0]-min[0])/2;
			this->anims[i].frames[j].aabb.sizey  = (max[1]-min[1])/2;
			this->anims[i].frames[j].aabb.sizez  = (max[2]-min[2])/2;
			this->anims[i].frames[j].aabb.computeLimit();

			//on remonte les vertices du model pour que le bas de la AABB soit au niveau 0
			/*float dy = 0-this->anims[i].frames[j].aabb.miny;
			this->anims[i].frames[j].aabb.miny+=0.0f;
			this->anims[i].frames[j].aabb.maxy+=dy;
			this->anims[i].frames[j].aabb.computeLimitInverse();
			float* pv = &this->anims[i].frames[j].vertex[1];	//on point sur la composante y
			for(int t=0;t<this->nbVertex;t++){
				*pv += dy;
				pv+=3;
			}*/
		}
	}
}

void ModelMD2::updateInstance_aabbAndAnimState(ModelInstance *mi, float time_ms)
{
	//printf("ModelMD2::updateInstance_aabbAndAnimState\n");
	AnimationState* stt = &mi->animState;

	//on ajoute le temp écoulé
	stt->curTime+=time_ms;

	if(stt->curTime >= this->limitTimeForAnim)//problème avec l'animation ici
	{
		stt->allowGeometryUpdate = true;
		while(stt->curTime>=MD2_FRAME_TIME)
		{
			//la frame a atteindre devient la courante
			stt->curAnim = stt->nextAnim;
			stt->curFrame = stt->nextFrame;

			//on change la frame a atteindre en prenant en compte les bornes
			//stt->nextAnim reste le meme : on ne change pas d'animation!
			stt->nextFrame++;
			if( stt->nextFrame >= this->anims[stt->nextAnim].nbFrame && this->anims[stt->nextAnim].loop ) {
				//en fin d'anim qui boucle
				stt->nextFrame = 0;
			}
			else if(stt->nextFrame >= this->anims[stt->nextAnim].nbFrame && !this->anims[stt->nextAnim].loop){
				//en fin d'anim qui ne boucle pas boucle
				stt->nextFrame = this->anims[stt->nextAnim].nbFrame-1;
			}

			stt->curTime -= MD2_FRAME_TIME;//on prend en compte le temp utilisé pour cette frame
		}

		//interpolation linéaire de la AABB
		BoundingBox* aabbCalc = &stt->aabb;
		BoundingBox* src = &this->anims[stt->curAnim].frames[stt->curFrame].aabb;
		BoundingBox* dst = &this->anims[stt->nextAnim].frames[stt->nextFrame].aabb;
		float f = stt->curTime/MD2_FRAME_TIME;//le facteur d'interpolation entre la source et la destination
		aabbCalc->maxx = src->maxx + f*(dst->maxx - src->maxx);
		aabbCalc->maxy = src->maxy + f*(dst->maxy - src->maxy);
		aabbCalc->maxz = src->maxz + f*(dst->maxz - src->maxz);
		aabbCalc->minx = src->minx + f*(dst->minx - src->minx);
		aabbCalc->miny = src->miny + f*(dst->miny - src->miny);
		aabbCalc->minz = src->minz + f*(dst->minz - src->minz);
		aabbCalc->computeLimitInverse();
	}
}

void ModelMD2::updateInstance_geometry(ModelInstance *mi)
{
	AnimationState* stt = &mi->animState;
	if(stt->allowGeometryUpdate)
	{
		float f = stt->curTime/MD2_FRAME_TIME;//le facteur d'interpolation entre la source et la destination

		// On interpole pas les normales de triangles qui ne nous serve a rien dans TACTIC

		//normal par triangle
		/*const float* ntsrc = this->anims[stt->curAnim].frames[stt->curFrame].trisNormal;
		const float* ntdst = this->anims[stt->nextAnim].frames[stt->nextFrame].trisNormal;
		float* ntCalc = mi->trisNormal;*/
		//vertex
		const float* vsrc = this->anims[stt->curAnim].frames[stt->curFrame].vertex;
		const float* vdst = this->anims[stt->nextAnim].frames[stt->nextFrame].vertex;
		float* vCalc = mi->vertex;
		//normal par vertex
		const float* nsrc = this->anims[stt->curAnim].frames[stt->curFrame].normal;
		const float* ndst = this->anims[stt->nextAnim].frames[stt->nextFrame].normal;
		float* nCalc = mi->normal;
		
		//interpolation linéaire des données par triangles
		/*for(int i=0;i<mi->model->nbTris;i++)
		{
			(*ntCalc)= (*ntsrc) + f*( (*ntdst)-(*ntsrc) );			// X
			ntCalc++;
			ntsrc++;
			ntdst++;
			(*ntCalc)= (*ntsrc) + f*( (*ntdst)-(*ntsrc) );			// Y
			ntCalc++;
			ntsrc++;
			ntdst++;
			(*ntCalc)= (*ntsrc) + f*( (*ntdst)-(*ntsrc) );			// Z
			ntCalc++;
			ntsrc++;
			ntdst++;
		}*/
		//interpolation linéaire des vertices
		for(int i=0;i<mi->model->nbVertex;i++)		//on interpole pas les vertex avec w=0 : dans TACTIC : pas de shadowVolum.
		{
			//TODO optimisé avec une boucle de nbVertex et une simple copie dans le tableau avec W=0
			(*vCalc)= (*vsrc) + f*( (*vdst)-(*vsrc) );			// X
			vCalc++;
			vsrc++;
			vdst++;
			(*vCalc)= (*vsrc) + f*( (*vdst)-(*vsrc) );			// Y
			vCalc++;
			vsrc++;
			vdst++;
			(*vCalc)= (*vsrc) + f*( (*vdst)-(*vsrc) );			// Z et on saute W
			vCalc++;
			vsrc++;
			vdst++;
		}
		//interpolation linéaire des attributs des vertices
		for(int i=0;i<mi->model->nbVertex;i++)
		{
			(*nCalc)= (*nsrc) + f*( (*ndst)-(*nsrc) );			// X
			nCalc++;
			nsrc++;
			ndst++;
			(*nCalc)= (*nsrc) + f*( (*ndst)-(*nsrc) );			// Y
			nCalc++;
			nsrc++;
			ndst++;
			(*nCalc)= (*nsrc) + f*( (*ndst)-(*nsrc) );			// Z
			nCalc++;
			nsrc++;
			ndst++;
		}

		//on attend le prochain dépassement de temp d'animation pour animer...
		stt->allowGeometryUpdate = false;
	}
}


void ModelMD2::animationLoop(int animNum, bool loop)
{
	if(animNum>=0 && animNum<this->nbAnimation) {
		this->anims[animNum].loop = loop;
	}
}

