


#include	"..\Datas\ZooMesh.h"
















///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// ZFace Class
///
///		- Classe des faces d'un objet
///		- Méthode de setting des références aux vertices de l'objet
///		- Normale à la face, des normales aux points, des coordonnées de texture des vertices,
///		  et identité de la texture à afficher pour cette face
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////
/// Constructor					 										///
///////////////////////////////////////////////////////////////////////////
// !WARNING!   IT MUST BE LIKE THIS BECOZ OF THE DYNAMIC ARRAY OF FACES !WARNING!
void ZFace::initFace()
{
	material = NULL;

	dependency   = false;

	UV1[0].SetCoord(0.0f, 0.0f);	UV1[1].SetCoord(1.0f, 0.0f);	UV1[2].SetCoord(0.0f, 1.0f);
	UV2[0].SetCoord(0.0f, 0.0f);	UV2[1].SetCoord(1.0f, 0.0f);	UV2[2].SetCoord(0.0f, 1.0f);

	clampU1 = clampV1 = clampU2 = clampV2 = true;

	index = -1;
}

void ZFace::DeleteFace()
{
	if(material)			material->DecRef();
}




///////////////////////////////////////////////////////////////////////////
/// Set the vertice references of the face								///
///////////////////////////////////////////////////////////////////////////
void ZFace::SetVertsRef(long ref0, long ref1, long ref2)
{
	VertRef[0] = ref0;
	VertRef[1] = ref1;
	VertRef[2] = ref2;
}


///////////////////////////////////////////////////////////////////////////
/// Set the material of the face										///
///////////////////////////////////////////////////////////////////////////
void ZFace::SetMaterial(ZMaterial *newMat)
{
	if(newMat!=material)
	{
		if(material!=NULL)			material->DecRef();

		material = newMat;
		if(material!=NULL)			material->IncRef();
	}
}















///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// ZMesh Class
///
///		- Classe des meshs
///		- Méthode d'intialisation du mesh -> nbre faces et vertices, et allocation de mémoire
///		- Méthode de libération du mesh (faces et vertices)
///		- Méthodes de création des normales aux faces et aux points
///		- Tableaux de vertices et de faces
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



///////////////////////////////////////////////////////////////////////////
/// Constructor					 										///
///////////////////////////////////////////////////////////////////////////
ZMesh::ZMesh(int s3d, int nvert, int nface) : ZData()
{
	scene3D = s3d;

	type = MSH_TYPE_ID;

	// Init des tableaux de faces et vertices
	NbVerts = nvert;
	NbFaces = nface;

	Verts.resize(nvert);
	Faces.resize(nface);
	
	for(int i=0; i<nface; i++)		Faces[i].initFace();

	for(i=0; i<nvert; i++)		
	{
		Verts[i].color1.SetCoord(1.0f, 1.0f, 1.0f);
		Verts[i].color2.SetCoord(1.0f, 1.0f, 1.0f);
	}

	// Init des tableaux de tri
	FacesFlat.gour.resize(0);
	FacesFlat.flat.resize(0);
	FacesFlat.no.resize(0);

	FacesEnv.resize(0);
	FacesColTransp.resize(0);
	FacesTex1.resize(0);
	FacesTex2.resize(0);

	FacesMatGour.resize(0);
	FacesMatFlat.resize(0);
	FacesMatNo.resize(0);
	
	FacesTransp.resize(0);

	// Dernières inits..
	multiTex	 = false;
	
	rapid = NULL;
	rapidCreated = false;

	hasTopoChanged = hasViewChanged = true;

	dependency		  = false;
	
	displayListCreate = true;


	Pass1ListID = Pass2ListID = Pass3ListID = Pass4ListID = -1;
}



ZMesh::~ZMesh()
{
	for(int i=0; i<NbFaces; i++)		Faces[i].DeleteFace();

	FacesFlat.gour.resize(0);
	FacesFlat.flat.resize(0);
	FacesFlat.no.resize(0);

	for(i=0; i<FacesTex1.size(); i++)	
	{
		FacesTex1[i].ClampUV.flat.resize(0);	FacesTex1[i].ClampUV.gour.resize(0);	FacesTex1[i].ClampUV.no.resize(0);
		FacesTex1[i].ClampU. flat.resize(0);	FacesTex1[i].ClampU. gour.resize(0);	FacesTex1[i].ClampU .no.resize(0);
		FacesTex1[i].ClampV. flat.resize(0);	FacesTex1[i].ClampV. gour.resize(0);	FacesTex1[i].ClampV .no.resize(0);
		FacesTex1[i].NoClamp.flat.resize(0);	FacesTex1[i].NoClamp.gour.resize(0);	FacesTex1[i].NoClamp.no.resize(0);
	}
	FacesTex1.resize(0);

	for(i=0; i<FacesEnv.size(); i++)	
	{
		FacesEnv[i].NoClamp.flat.resize(0);
		FacesEnv[i].NoClamp.gour.resize(0);
		FacesEnv[i].NoClamp.no.resize(0);
	}
	FacesEnv.resize(0);

	for(i=0; i<FacesColTransp.size(); i++)	
	{
		FacesColTransp[i].ClampUV.flat.resize(0);	FacesColTransp[i].ClampUV.gour.resize(0);	FacesColTransp[i].ClampUV.no.resize(0);
		FacesColTransp[i].ClampU. flat.resize(0);	FacesColTransp[i].ClampU. gour.resize(0);	FacesColTransp[i].ClampU .no.resize(0);
		FacesColTransp[i].ClampV. flat.resize(0);	FacesColTransp[i].ClampV. gour.resize(0);	FacesColTransp[i].ClampV .no.resize(0);
		FacesColTransp[i].NoClamp.flat.resize(0);	FacesColTransp[i].NoClamp.gour.resize(0);	FacesColTransp[i].NoClamp.no.resize(0);
	}
	FacesColTransp.resize(0);

	for(i=0; i<FacesTex2.size(); i++)
	{
		FacesTex2[i].ClampUV.flat.resize(0);	FacesTex2[i].ClampUV.gour.resize(0);	FacesTex2[i].ClampUV.no.resize(0);
		FacesTex2[i].ClampU. flat.resize(0);	FacesTex2[i].ClampU. gour.resize(0);	FacesTex2[i].ClampU .no.resize(0);
		FacesTex2[i].ClampV. flat.resize(0);	FacesTex2[i].ClampV. gour.resize(0);	FacesTex2[i].ClampV .no.resize(0);
		FacesTex2[i].NoClamp.flat.resize(0);	FacesTex2[i].NoClamp.gour.resize(0);	FacesTex2[i].NoClamp.no.resize(0);
	}
	FacesTex2.resize(0);

	for(i=0; i<FacesMatGour.size(); i++)
	{
		FacesMatGour[i].faces.resize(0);
	}
	FacesMatGour.resize(0);

	for(i=0; i<FacesMatFlat.size(); i++)
	{
		FacesMatFlat[i].faces.resize(0);
	}
	FacesMatFlat.resize(0);

	for(i=0; i<FacesMatNo.size(); i++)
	{
		FacesMatNo[i].faces.resize(0);
	}
	FacesMatNo.resize(0);


	FacesTransp.resize(0);
	
	Verts.resize(0);
	Faces.resize(0);

	if(rapid!=NULL)		delete(rapid);



	if(Pass1ListID!=-1)			glDeleteLists(Pass1ListID, 1);
	if(Pass2ListID!=-1)			glDeleteLists(Pass2ListID, 1);
	if(Pass3ListID!=-1)			glDeleteLists(Pass3ListID, 1);
	if(Pass4ListID!=-1)			glDeleteLists(Pass4ListID, 1);
}



///////////////////////////////////////////////////////////////////////////
/// Creation des listes de faces										///
///////////////////////////////////////////////////////////////////////////
void ZMesh::MakeFacesList()
{
	int				j, k;
	
	ListFaceByMat	*listMat;
	FacesBySHADE	*listFace;

	multiTex = false;

	FacesFlat.gour.resize(0);
	FacesFlat.flat.resize(0);
	FacesFlat.no.resize(0);

	FacesEnv.resize(0);
	FacesColTransp.resize(0);
	FacesTex1.resize(0);
	FacesTex2.resize(0);

	FacesMatGour.resize(0);
	FacesMatFlat.resize(0);
	FacesMatNo.resize(0);

	FacesTransp.resize(0);

	ZMaterial	*curMat;
	ZTexture	*tex1, *tex2;

	bool		idemTex1, idemTex2, idemMat;

	for(int i=0; i<NbFaces; i++)
	{
		curMat = Faces[i].GetMaterial();

		if( curMat!=NULL )
		{
			//////////////////////////////////////////////////////////////////////////////////
			/// Si le matériau existe, on classe la face dans l'une des liste qui convient ///
			//////////////////////////////////////////////////////////////////////////////////			

			// ---> FOR NOT TRANSPARENCY FACES OR transpCOLOR FACES <---
			if( (!(curMat->IsOnMode(RENDER_TRANSP)) || curMat->GetCoeffTransp()==0)  && (curMat->IsOnMode(RENDER_TEXTURED)) && (curMat->GetTexture1()!=NULL) && (curMat->GetTexture1()->activated) )
			{
				////////////////////////////////////////////////////////////////////////////////////////////
				/// Si la face est texturée et opaque, on la classe parmi les faces avec la même texture ///
				////////////////////////////////////////////////////////////////////////////////////////////

				idemTex1 = false;
				idemTex2 = false; 

				tex1 = curMat->GetTexture1();
				tex2 = curMat->GetTexture2();

				// ---> Teste la présence d'une liste qui convient pour cette face <---
				j = k = 0;
				// PASS 1
				if(curMat->IsOnMode(RENDER_TRANSP))		// TRANSP COLOR MAP (pour le coeffTransp=0 ou Attracteur)
				{
					while( (j<FacesColTransp.size()) && (!idemTex1) )
					{
						if (tex1 == FacesColTransp[j].tex)		idemTex1 = true;
						j++;
					}
				}
				else
				if(curMat->IsOnMode(RENDER_ENVMAP))					// ENVMAP
				{
					while( (j<FacesEnv.size()) && (!idemTex1) )
					{
						if (tex1 == FacesEnv[j].tex)		idemTex1 = true;
						j++;
					}
				}
				else												// CLASSICAL MAP
				{
					while( (j<FacesTex1.size()) && (!idemTex1) )
					{
						if (tex1 == FacesTex1[j].tex)		idemTex1 = true;
						j++;
					}
				}
				// PASS 2
				while( (k<FacesTex2.size()) && (!idemTex2) )
				{
					if (tex2 == FacesTex2[k].tex)		idemTex2 = true;
					k++;
				}

				// ---> S'il existe une liste qui convient, on stocke <---
				// PASS 1
				if(curMat->IsOnMode(RENDER_TRANSP))			// --- TRANSP COLOR MAP ---
				{
					if (idemTex1)
					{
						j--;

						if(Faces[i].clampU1 && Faces[i].clampV1)		listFace = &FacesColTransp[j].ClampUV;
						else if(Faces[i].clampU1)						listFace = &FacesColTransp[j].ClampU;
						else if(Faces[i].clampV1)						listFace = &FacesColTransp[j].ClampV;
						else											listFace = &FacesColTransp[j].NoClamp;

						if( (curMat->IsOnMode(RENDER_COLOR_VERTEX)) && (curMat->IsOnMode(RENDER_COLOR1)) )
						{
							listFace->gour.resize(listFace->gour.size()+1);				// agrandit la liste qui convient					
							listFace->gour[listFace->gour.size()-1] = &(Faces[i]);		// ajoute la face dans la liste						
						}
						else
						if (curMat->IsOnMode(RENDER_COLOR1))
						{
							listFace->flat.resize(listFace->flat.size()+1);				// agrandit la liste qui convient					
							listFace->flat[listFace->flat.size()-1] = &(Faces[i]);		// ajoute la face dans la liste						
						}
						else
						{
							listFace->no.resize(listFace->no.size()+1);					// agrandit la liste qui convient					
							listFace->no[listFace->no.size()-1] = &(Faces[i]);			// ajoute la face dans la liste						
						}
					}
					// ---> sinon, on crée une nouvelle liste <---
					else	
					{
						FacesColTransp.resize(FacesColTransp.size()+1);									// crée une nouvelle liste							
						FacesColTransp[j].tex = tex1;

						FacesColTransp[j].ClampUV.flat.resize(0);	FacesColTransp[j].ClampUV.gour.resize(0);	FacesColTransp[j].ClampUV.no.resize(0);
						FacesColTransp[j].ClampU. flat.resize(0);	FacesColTransp[j].ClampU. gour.resize(0);	FacesColTransp[j].ClampU .no.resize(0);
						FacesColTransp[j].ClampV. flat.resize(0);	FacesColTransp[j].ClampV. gour.resize(0);	FacesColTransp[j].ClampV .no.resize(0);
						FacesColTransp[j].NoClamp.flat.resize(0);	FacesColTransp[j].NoClamp.gour.resize(0);	FacesColTransp[j].NoClamp.no.resize(0);

						if(Faces[i].clampU1 && Faces[i].clampV1)		listFace = &FacesColTransp[j].ClampUV;
						else if(Faces[i].clampU1)						listFace = &FacesColTransp[j].ClampU;
						else if(Faces[i].clampV1)						listFace = &FacesColTransp[j].ClampV;
						else											listFace = &FacesColTransp[j].NoClamp;

						if( (curMat->IsOnMode(RENDER_COLOR_VERTEX)) && (curMat->IsOnMode(RENDER_COLOR1)) )
						{
							listFace->gour.resize(1);										// permet le placement d'un élément dans cette liste
							listFace->gour[0] = &(Faces[i]);									// ajoute la face dans la liste
						}
						else
						if (curMat->IsOnMode(RENDER_COLOR1))
						{
							listFace->flat.resize(1);										// permet le placement d'un élément dans cette liste
							listFace->flat[0] = &(Faces[i]);									// ajoute la face dans la liste		
						}
						else
						{
							listFace->no.resize(1);											// permet le placement d'un élément dans cette liste
							listFace->no[0] = &(Faces[i]);									// ajoute la face dans la liste		
						}

					}
				}
				else
				if(curMat->IsOnMode(RENDER_ENVMAP))			// --- ENVIRONMENT MAP ---
				{
					if (idemTex1)
					{
						j--;

						listFace = &FacesEnv[j].NoClamp;

						if( curMat->IsOnMode(RENDER_GOURAUD_LIGHT) )
						{
							listFace->gour.resize(listFace->gour.size()+1);				// agrandit la liste qui convient					
							listFace->gour[listFace->gour.size()-1] = &(Faces[i]);		// ajoute la face dans la liste						
						}
						else
						{
							listFace->flat.resize(listFace->flat.size()+1);				// agrandit la liste qui convient					
							listFace->flat[listFace->flat.size()-1] = &(Faces[i]);		// ajoute la face dans la liste						
						}
					}
					// ---> sinon, on crée une nouvelle liste <---
					else	
					{
						FacesEnv.resize(FacesEnv.size()+1);									// crée une nouvelle liste							
						FacesEnv[j].tex = tex1;

						FacesEnv[j].NoClamp.flat.resize(0);		
						FacesEnv[j].NoClamp.gour.resize(0);		

						listFace = &FacesEnv[j].NoClamp;

						if( curMat->IsOnMode(RENDER_GOURAUD_LIGHT) )
						{
							listFace->gour.resize(1);										// permet le placement d'un élément dans cette liste
							listFace->gour[0] = &(Faces[i]);									// ajoute la face dans la liste
						}
						else
						{
							listFace->flat.resize(1);										// permet le placement d'un élément dans cette liste
							listFace->flat[0] = &(Faces[i]);									// ajoute la face dans la liste		
						}
					}
				}
				else										// --- CLASSICAL MAP ---
				{
					// PASS 1
					if (idemTex1)
					{
						j--;

						if(Faces[i].clampU1 && Faces[i].clampV1)		listFace = &FacesTex1[j].ClampUV;
						else if(Faces[i].clampU1)						listFace = &FacesTex1[j].ClampU;
						else if(Faces[i].clampV1)						listFace = &FacesTex1[j].ClampV;
						else											listFace = &FacesTex1[j].NoClamp;

						if( (curMat->IsOnMode(RENDER_COLOR_VERTEX)) && (curMat->IsOnMode(RENDER_COLOR1)) )
						{
							listFace->gour.resize(listFace->gour.size()+1);				// agrandit la liste qui convient					
							listFace->gour[listFace->gour.size()-1] = &(Faces[i]);		// ajoute la face dans la liste						
						}
						else
						if (curMat->IsOnMode(RENDER_COLOR1))
						{
							listFace->flat.resize(listFace->flat.size()+1);				// agrandit la liste qui convient					
							listFace->flat[listFace->flat.size()-1] = &(Faces[i]);		// ajoute la face dans la liste						
						}
						else
						{
							listFace->no.resize(listFace->no.size()+1);					// agrandit la liste qui convient					
							listFace->no[listFace->no.size()-1] = &(Faces[i]);			// ajoute la face dans la liste						
						}
					}
					// ---> sinon, on crée une nouvelle liste <---
					else	
					{
						FacesTex1.resize(FacesTex1.size()+1);									// crée une nouvelle liste							
						FacesTex1[j].tex = tex1;

						FacesTex1[j].ClampUV.flat.resize(0);	FacesTex1[j].ClampUV.gour.resize(0);	FacesTex1[j].ClampUV.no.resize(0);
						FacesTex1[j].ClampU. flat.resize(0);	FacesTex1[j].ClampU. gour.resize(0);	FacesTex1[j].ClampU .no.resize(0);
						FacesTex1[j].ClampV. flat.resize(0);	FacesTex1[j].ClampV. gour.resize(0);	FacesTex1[j].ClampV .no.resize(0);
						FacesTex1[j].NoClamp.flat.resize(0);	FacesTex1[j].NoClamp.gour.resize(0);	FacesTex1[j].NoClamp.no.resize(0);

						if(Faces[i].clampU1 && Faces[i].clampV1)		listFace = &FacesTex1[j].ClampUV;
						else if(Faces[i].clampU1)						listFace = &FacesTex1[j].ClampU;
						else if(Faces[i].clampV1)						listFace = &FacesTex1[j].ClampV;
						else											listFace = &FacesTex1[j].NoClamp;

						if( (curMat->IsOnMode(RENDER_COLOR_VERTEX)) && (curMat->IsOnMode(RENDER_COLOR1)) )
						{
							listFace->gour.resize(1);										// permet le placement d'un élément dans cette liste
							listFace->gour[0] = &(Faces[i]);									// ajoute la face dans la liste
						}
						else
						if (curMat->IsOnMode(RENDER_COLOR1))
						{
							listFace->flat.resize(1);										// permet le placement d'un élément dans cette liste
							listFace->flat[0] = &(Faces[i]);									// ajoute la face dans la liste		
						}
						else
						{
							listFace->no.resize(1);											// permet le placement d'un élément dans cette liste
							listFace->no[0] = &(Faces[i]);									// ajoute la face dans la liste		
						}
					}
				}


				// PASS 2
				if (idemTex2 && tex2 && (curMat->IsOnMode(RENDER_TEXTURED_BIS)) && (tex2->activated) )
				{
					k--;

					if(Faces[i].clampU2 && Faces[i].clampV2)		listFace = &FacesTex2[k].ClampUV;
					else if(Faces[i].clampU2)						listFace = &FacesTex2[k].ClampU;
					else if(Faces[i].clampV2)						listFace = &FacesTex2[k].ClampV;
					else											listFace = &FacesTex2[k].NoClamp;

					if( (curMat->IsOnMode(RENDER_COLOR_VERTEX)) && (curMat->IsOnMode(RENDER_COLOR2)) )
					{
						listFace->gour.resize(listFace->gour.size()+1);							
						listFace->gour[listFace->gour.size()-1] = &(Faces[i]);					
					}
					else
					if (curMat->IsOnMode(RENDER_COLOR2))
					{
						listFace->flat.resize(listFace->flat.size()+1);							
						listFace->flat[listFace->flat.size()-1] = &(Faces[i]);					
					}
					else
					{
						listFace->no.resize(listFace->no.size()+1);								
						listFace->no[listFace->no.size()-1] = &(Faces[i]);						
					}
				}
				// ---> sinon, on crée une nouvelle liste <---
				else
				if( tex2 && curMat->IsOnMode(RENDER_TEXTURED_BIS) && (tex2->activated) )
				{
					int curSize = FacesTex2.size();
					FacesTex2.resize(curSize+1);									// crée une nouvelle liste							
					//FacesTex2.resize(FacesTex2.size()+1);									// crée une nouvelle liste							
					FacesTex2[k].tex = curMat->GetTexture2();

					FacesTex2[k].ClampUV.flat.resize(0);	FacesTex2[k].ClampUV.gour.resize(0);	FacesTex2[k].ClampUV.no.resize(0);
					FacesTex2[k].ClampU. flat.resize(0);	FacesTex2[k].ClampU. gour.resize(0);	FacesTex2[k].ClampU .no.resize(0);
					FacesTex2[k].ClampV. flat.resize(0);	FacesTex2[k].ClampV. gour.resize(0);	FacesTex2[k].ClampV .no.resize(0);
					FacesTex2[k].NoClamp.flat.resize(0);	FacesTex2[k].NoClamp.gour.resize(0);	FacesTex2[k].NoClamp.no.resize(0);

					if(Faces[i].clampU2 && Faces[i].clampV2)		listFace = &FacesTex2[k].ClampUV;
					else if(Faces[i].clampU2)						listFace = &FacesTex2[k].ClampU;
					else if(Faces[i].clampV2)						listFace = &FacesTex2[k].ClampV;
					else											listFace = &FacesTex2[k].NoClamp;

					if( (curMat->IsOnMode(RENDER_COLOR_VERTEX)) && (curMat->IsOnMode(RENDER_COLOR2)) )
					{
						listFace->gour.resize(1);		
						listFace->gour[0] = &(Faces[i]);
					}
					else
					if (curMat->IsOnMode(RENDER_COLOR2))
					{
						listFace->flat.resize(1);		
						listFace->flat[0] = &(Faces[i]);
					}
					else
					{
						listFace->no.resize(1);			
						listFace->no[0] = &(Faces[i]);	
					}

					multiTex = true;
				}
			}
			// ---> FOR (REAL) TRANSPARENCY FACES <---
			else
			if( curMat->IsOnMode(RENDER_TRANSP) && curMat->GetCoeffTransp()!=0)
			{
				///////////////////////////////////////////////////////////////////////////
				/// Si la face est transparente, on la met avec les faces transparentes ///
				///////////////////////////////////////////////////////////////////////////

				FacesTransp.resize(FacesTransp.size()+1);
				FacesTransp[FacesTransp.size()-1] = &(Faces[i]);							// ajoute la face dans la liste des faces transparentes
			}
			// ---> FOR NOT TEXTURED FACES <---
			else
			{
				///////////////////////////////////////////////////////////////////////
				/// Si la face n'est pas texturée, on la met avec les faces en FLAT	///
				///////////////////////////////////////////////////////////////////////
				
				if( (curMat->IsOnMode(RENDER_COLOR_VERTEX)) && (curMat->IsOnMode(RENDER_COLOR1)) )
				{
					FacesFlat.gour.resize(FacesFlat.gour.size()+1);
					FacesFlat.gour[FacesFlat.gour.size()-1] = &(Faces[i]);					// ajoute la face dans la liste des faces en mode flat
				}
				else
				if (curMat->IsOnMode(RENDER_COLOR1))
				{
					FacesFlat.flat.resize(FacesFlat.flat.size()+1);
					FacesFlat.flat[FacesFlat.flat.size()-1] = &(Faces[i]);					// ajoute la face dans la liste des faces en mode flat
				}
				else
				{
					FacesFlat.no.resize(FacesFlat.no.size()+1);
					FacesFlat.no[FacesFlat.no.size()-1] = &(Faces[i]);						// ajoute la face dans la liste des faces en mode flat
				}
			}



			/////////////////////////////////////////////
			/// On tri maintenant suivant le matériau ///
			/////////////////////////////////////////////
			// PASS 3

			j = 0;

			idemMat = false;

			if(curMat->IsOnMode(RENDER_LIGHTED) && (curMat->IsOnMode(RENDER_TRANSP)==false || curMat->GetCoeffTransp()==0))
			{
				if(curMat->IsOnMode(RENDER_GOURAUD_LIGHT))		listMat = &FacesMatGour;
				else											listMat = &FacesMatFlat;
			}
			else
				listMat = &FacesMatNo;


			// Recherche
			while( (j<listMat->size()) && (!idemMat) )
			{
				if (curMat == (*listMat)[j].mat)			idemMat = true;
				j++;
			}

			// Stockage existant
			if(idemMat)
			{
				j--;
				
				(*listMat)[j].faces.resize((*listMat)[j].faces.size()+1);
				(*listMat)[j].faces[(*listMat)[j].faces.size()-1] = &(Faces[i]);
			}
			// Stockage nouveau
			else
			{
				listMat->resize(j+1);
				(*listMat)[j].mat = curMat;
				(*listMat)[j].faces.resize(1);
				(*listMat)[j].faces[0] = &(Faces[i]);
			}
		}
	}
}



#define RENDER_SHADE_LIST_TEXTURED_PASS1									\
									 										\
	/***** GOURAUD COLOR *****/		 										\
									 										\
	if(shadeList->gour.size())	 											\
	{									 									\
		glShadeModel(GL_SMOOTH);											\
		facelist = &(shadeList->gour);										\
																			\
		glBegin(GL_TRIANGLES);												\
																			\
			for(i=0; i< facelist->size(); i++) 								\
			{																\
				curFace = (*facelist)[i];									\
				vrtRef	= curFace->VertRef;									\
				UV		= curFace->UV1;										\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glColor3fv(curVert->color1.vals);							\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glColor3fv(curVert->color1.vals);							\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glColor3fv(curVert->color1.vals);							\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
			}																\
																			\
		glEnd();															\
	}																		\
																			\
	/***** FLAT COLOR ******/												\
																			\
	if(shadeList->flat.size() || shadeList->no.size())						\
	{																		\
		glShadeModel(GL_FLAT);												\
																			\
		glBegin(GL_TRIANGLES);												\
																			\
			/** Face color **/												\
			facelist = &(shadeList->flat);									\
																			\
			for(i=0; i< facelist->size(); i++)								\
			{																\
				curFace = (*facelist)[i];									\
				vrtRef	= curFace->VertRef;									\
				UV		= curFace->UV1;										\
				glColor3fv(curFace->GetMaterial()->color1.vals);			\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
			}																\
																			\
			/** Default color **/											\
			facelist = &(shadeList->no);									\
																			\
			for(i=0; i< facelist->size(); i++)								\
			{																\
				curFace = (*facelist)[i];									\
				vrtRef	= curFace->VertRef;									\
				UV		= curFace->UV1;										\
				glColor3f(1.0f, 1.0f, 1.0f);								\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
			}																\
																			\
		glEnd();															\
	}							



///////////////////////////////////////////////////////////////////////////////////////////////////
/// Create a display list for texture rendering (CLASSIC mode)									///
///////////////////////////////////////////////////////////////////////////////////////////////////

void ZMesh::CreateListPass1()
{
	int				i, j;

	FaceList		*facelist;
	ZFace			*curFace;
	ZVert			*curVert;
	ZUV				*UV;
	int				*vrtRef;
	
	ZTexture		*curTex;

	FacesBySHADE	*shadeList;


	glNewList(Pass1ListID, GL_COMPILE);
	
	

	// ************* Treatment for non texturing ************** 

	glDisable(GL_TEXTURE_2D);
	glDisable(GL_BLEND);
	glDisable(GL_ALPHA_TEST);

	// ******* GOURAUD COLOR *******
	
	if(FacesFlat.gour.size())
	{
		glShadeModel(GL_SMOOTH);
		facelist = &(FacesFlat.gour);

		glBegin(GL_TRIANGLES);

			for(i=0; i< facelist->size(); i++)
			{
				curFace = (*facelist)[i];
				vrtRef	= curFace->VertRef;

				// Vertex number 0
				curVert = &(Verts[*vrtRef]);
				glColor3fv(curVert->color1.vals);
				glVertex3fv(curVert->vals);
				vrtRef++;

				// Vertex number 1
				curVert = &(Verts[*vrtRef]);
				glColor3fv(curVert->color1.vals);
				glVertex3fv(curVert->vals);
				vrtRef++;

				// Vertex number 2
				curVert = &(Verts[*vrtRef]);
				glColor3fv(curVert->color1.vals);
				glVertex3fv(curVert->vals);
			}

		glEnd();
	}

	// ******* FLAT COLOR *******
	
	if(FacesFlat.flat.size() || FacesFlat.no.size())
	{
		glShadeModel(GL_FLAT);

		glBegin(GL_TRIANGLES);

			// **** Face color ****
			facelist = &(FacesFlat.flat);

			for(i=0; i< facelist->size(); i++)
			{
				curFace = (*facelist)[i];
				vrtRef	= curFace->VertRef;
				glColor3fv(curFace->GetMaterial()->color1.vals);

				// Vertex number 0
				curVert = &(Verts[*vrtRef]);
				glVertex3fv(curVert->vals);
				vrtRef++;
		
				// Vertex number 1
				curVert = &(Verts[*vrtRef]);
				glVertex3fv(curVert->vals);
				vrtRef++;

				// Vertex number 2
				curVert = &(Verts[*vrtRef]);
				glVertex3fv(curVert->vals);
			}

			// *** Default color ***
			facelist = &(FacesFlat.no);

			for(i=0; i< facelist->size(); i++)
			{
				curFace = (*facelist)[i];
				vrtRef	= curFace->VertRef;
				glColor3fv(curFace->GetMaterial()->color.vals);

				// Vertex number 0
				curVert = &(Verts[*vrtRef]);
				glVertex3fv(curVert->vals);
				vrtRef++;
		
				// Vertex number 1
				curVert = &(Verts[*vrtRef]);
				glVertex3fv(curVert->vals);
				vrtRef++;

				// Vertex number 2
				curVert = &(Verts[*vrtRef]);
				glVertex3fv(curVert->vals);
			}

		glEnd();
	}



	// ************* Treatment by type of texture ************** 

	glEnable(GL_TEXTURE_2D);


	// ******* CLASSICAL MAPPING *******

	for(j=0; j<FacesTex1.size(); j++)
	{
		curTex = FacesTex1[j].tex;
		curTex->PutGLparams();

		///////////////////////////////////////////
		///				clamp u v				///
		///////////////////////////////////////////
		
		shadeList = &FacesTex1[j].ClampUV;

		if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

			RENDER_SHADE_LIST_TEXTURED_PASS1
		}

		///////////////////////////////////////////
		///				clamp u 				///
		///////////////////////////////////////////
		
		shadeList = &FacesTex1[j].ClampU;

		if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

			RENDER_SHADE_LIST_TEXTURED_PASS1
		}


		///////////////////////////////////////////
		///				clamp V 				///
		///////////////////////////////////////////

		shadeList = &FacesTex1[j].ClampV;

		if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

			RENDER_SHADE_LIST_TEXTURED_PASS1
		}

		///////////////////////////////////////////
		///				No clamp  				///
		///////////////////////////////////////////
		
		shadeList = &FacesTex1[j].NoClamp;

		if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

			RENDER_SHADE_LIST_TEXTURED_PASS1
		}

		///////////////////////////////////////////
		///				End clamping			///
		///////////////////////////////////////////
	}





	// ******* COLOR TRANSP MAPPING *******

	if(FacesColTransp.size())
	{
		glEnable(GL_ALPHA_TEST);
		glAlphaFunc(GL_GREATER, CONST_ALPHA_TEST);

		for(j=0; j<FacesColTransp.size(); j++)
		{
			curTex = FacesColTransp[j].tex;
			curTex->PutGLparams();


			///////////////////////////////////////////
			///				clamp u v				///
			///////////////////////////////////////////
			
			shadeList = &FacesColTransp[j].ClampUV;

			if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
			{
				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

				RENDER_SHADE_LIST_TEXTURED_PASS1
			}

			///////////////////////////////////////////
			///				clamp u 				///
			///////////////////////////////////////////
			
			shadeList = &FacesColTransp[j].ClampU;

			if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
			{
				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

				RENDER_SHADE_LIST_TEXTURED_PASS1
			}


			///////////////////////////////////////////
			///				clamp V 				///
			///////////////////////////////////////////
			
			shadeList = &FacesColTransp[j].ClampV;

			if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
			{
				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

				RENDER_SHADE_LIST_TEXTURED_PASS1
			}

			///////////////////////////////////////////
			///				No clamp  				///
			///////////////////////////////////////////
			
			shadeList = &FacesColTransp[j].NoClamp;

			if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
			{
				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

				RENDER_SHADE_LIST_TEXTURED_PASS1
			}

			///////////////////////////////////////////
			///				End clamping			///
			///////////////////////////////////////////

		}

		glDisable(GL_ALPHA_TEST);
	}


	// ************* ENVIRONMENTAL MAPPING *************

	if( FacesEnv.size() )
	{
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

		glEnable(GL_TEXTURE_GEN_S);
		glEnable(GL_TEXTURE_GEN_T);

		for(j=0; j<FacesEnv.size(); j++)
		{
			curTex = FacesEnv[j].tex;
			curTex->PutGLparams();

			shadeList = &FacesEnv[j].NoClamp;

			if(shadeList->gour.size())
			{
				// --------------> TEXTURED <---------------
				// ---> PASS for smooth color rendering <---

				glShadeModel(GL_SMOOTH);
				facelist = &(shadeList->gour);

				glBegin(GL_TRIANGLES);

					glColor3f(1.0f, 1.0f, 1.0f);

					for(i=0; i< facelist->size(); i++)
					{
						curFace = (*facelist)[i];
						vrtRef	= curFace->VertRef;

						// Vertex number 0
						curVert = &(Verts[*vrtRef]);
						glNormal3fv(curVert->Normal.vals);
						glVertex3fv(curVert->vals);
						vrtRef++;

						// Vertex number 1
						curVert = &(Verts[*vrtRef]);
						glNormal3fv(curVert->Normal.vals);
						glVertex3fv(curVert->vals);
						vrtRef++;

						// Vertex number 2
						curVert = &(Verts[*vrtRef]);
						glNormal3fv(curVert->Normal.vals);
						glVertex3fv(curVert->vals);
					}

				glEnd();
			}

			if(shadeList->flat.size())
			{
				// --------------> TEXTURED <---------------
				// ---> PASS for uniform color rendering <---

				glShadeModel(GL_FLAT);

				glBegin(GL_TRIANGLES);

					glColor3f(1.0f, 1.0f, 1.0f);

					facelist = &(shadeList->flat);

					for(i=0; i< facelist->size(); i++)
					{
						curFace = (*facelist)[i];
						vrtRef	= curFace->VertRef;
						glNormal3fv(curFace->Normal.vals);

						// Vertex number 0
						curVert = &(Verts[*vrtRef]);
						glVertex3fv(curVert->vals);
						vrtRef++;
				
						// Vertex number 1
						curVert = &(Verts[*vrtRef]);
						glVertex3fv(curVert->vals);
						vrtRef++;

						// Vertex number 2
						curVert = &(Verts[*vrtRef]);
						glVertex3fv(curVert->vals);
					}

				glEnd();
			}
		}

		glDisable(GL_TEXTURE_GEN_S);							// Enable Texture Coord Generation For S (NEW)
		glDisable(GL_TEXTURE_GEN_T);							// Enable Texture Coord Generation For T (NEW)
	}







#ifdef	_SHOW_NORMALS_

		ZVector3	centre;
		ZVector3	normale;

		glLineWidth(2.0);
		
		glShadeModel(GL_FLAT);
		glDisable(GL_TEXTURE_2D);

		glBegin(GL_LINES);

		for(j=0; j < Faces.size(); j++)
		{
			glColor3f(0.0f, 1.0f, 1.0f);

			curFace = &(Faces[j]);
			vrtRef	= curFace->VertRef;
			
			normale = curFace->Normal;
			normale.Normalize();
			normale *= 0.1f;

			// Vertex number 0
			curVert = &(Verts[*vrtRef]);
			centre.x = curVert->x;
			centre.y = curVert->y;
			centre.z = curVert->z;
			vrtRef++;

			// Vertex number 1
			curVert = &(Verts[*vrtRef]);
			centre.x += curVert->x;
			centre.y += curVert->y;
			centre.z += curVert->z;
			vrtRef++;

			// Vertex number 2
			curVert = &(Verts[*vrtRef]);
			centre.x += curVert->x;
			centre.y += curVert->y;
			centre.z += curVert->z;

			centre *= 0.33333333f;
			glVertex3fv(centre.vals);
			centre += normale;
			glVertex3fv(centre.vals);
		}

		glEnd();

		glEnable(GL_TEXTURE_2D);

#endif




	glEndList();

}





#define RENDER_SHADE_LIST_TEXTURED_PASS2									\
																			\
	/* Gouraud */															\
																			\
	if(shadeList->gour.size())												\
	{																		\
		glShadeModel(GL_SMOOTH);											\
		facelist = &(shadeList->gour);										\
																			\
		glBegin(GL_TRIANGLES);												\
																			\
			for(i=0; i< facelist->size(); i++)								\
			{																\
				curFace = (*facelist)[i];									\
				vrtRef	= curFace->VertRef;									\
				UV		= curFace->UV2;										\
				alpha	= curFace->GetMaterial()->alpha;					\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				color	= &(curVert->color2);								\
				glColor4f(color->x, color->y, color->z, alpha);				\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 1 */										\
				curVert = &(Verts[*vrtRef]);								\
				color	= &(curVert->color2);								\
				glColor4f(color->x, color->y, color->z, alpha);				\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 2 */										\
				curVert = &(Verts[*vrtRef]);								\
				color	= &(curVert->color2);								\
				glColor4f(color->x, color->y, color->z, alpha);				\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
			}																\
																			\
		glEnd();															\
	}																		\
																			\
	/* Flat */																\
																			\
	if(shadeList->flat.size() || shadeList->no.size())						\
	{																		\
		glShadeModel(GL_FLAT);												\
																			\
		glBegin(GL_TRIANGLES);												\
																			\
			/* COLOR 1 */													\
																			\
			facelist = &(shadeList->flat);									\
																			\
			for(i=0; i< facelist->size(); i++)								\
			{																\
				curFace = (*facelist)[i];									\
				vrtRef	= curFace->VertRef;									\
				UV		= curFace->UV2;										\
				color	= &(curFace->GetMaterial()->color2);				\
				glColor4f(color->x, color->y, color->z, curFace->GetMaterial()->alpha);		\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
			}																\
																			\
			/* DEFAULT COLOR */												\
																			\
			facelist = &(shadeList->no);									\
																			\
			for(i=0; i< facelist->size(); i++)								\
			{																\
				curFace = (*facelist)[i];									\
				vrtRef	= curFace->VertRef;									\
				UV		= curFace->UV2;										\
				color	= &(curFace->GetMaterial()->color);					\
				glColor4f(1.0f, 1.0f, 1.0f, curFace->GetMaterial()->alpha);	\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glTexCoord2fv(UV->vals);									\
				glVertex3fv(curVert->vals);									\
			}																\
																			\
		glEnd();															\
	}




///////////////////////////////////////////////////////////////////////////////////////////////////
/// Create a display list for light rendering (CLASSIC mode)									///
///////////////////////////////////////////////////////////////////////////////////////////////////

void ZMesh::CreateListPass2()
{
	int				i, j;

	FaceList		*facelist;

	ZFace			*curFace;
	ZVert			*curVert;
	ZVector3		*color;
	ZUV				*UV;
	int				*vrtRef;
	
	ZTexture		*curTex;

	float			alpha;

	FacesBySHADE	*shadeList;


	// Compile the new display list
	glNewList(Pass2ListID, GL_COMPILE);


	// --------------------------------------------------------
	// ------------- Treatment by type of texture -------------
	// --------------------------------------------------------

	glEnable(GL_TEXTURE_2D);

	for(j=0; j<FacesTex2.size(); j++)
	{
		curTex = FacesTex2[j].tex;
		curTex->PutGLparams();
		if(curTex->A)				{	glEnable(GL_ALPHA_TEST);	glAlphaFunc(GL_NOTEQUAL, 0);	}
		else						{	glDisable(GL_ALPHA_TEST);	}


		///////////////////////////////////////////
		///				clamp u v				///
		///////////////////////////////////////////
		
		shadeList = &FacesTex2[j].ClampUV;

		if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

			RENDER_SHADE_LIST_TEXTURED_PASS2
		}

		///////////////////////////////////////////
		///				clamp u					///
		///////////////////////////////////////////
		
		shadeList = &FacesTex2[j].ClampU;

		if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

			RENDER_SHADE_LIST_TEXTURED_PASS2
		}

		///////////////////////////////////////////
		///				clamp V					///
		///////////////////////////////////////////
		
		shadeList = &FacesTex2[j].ClampV;

		if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

			RENDER_SHADE_LIST_TEXTURED_PASS2
		}

		///////////////////////////////////////////
		///				No clamp 				///
		///////////////////////////////////////////
		
		shadeList = &FacesTex2[j].NoClamp;

		if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
		{
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

			RENDER_SHADE_LIST_TEXTURED_PASS2
		}

	}
	
	glEndList();

}



///////////////////////////////////////////////////////////////////////////////////////////////////
/// Create a display list for light rendering (CLASSIC mode)									///
///////////////////////////////////////////////////////////////////////////////////////////////////

void ZMesh::CreateListPass3()
{
	int				i, j;

	FaceList		*facelist;

	ZFace			*curFace;
	ZVert			*curVert;
	int				*vrtRef;
	
	ZMaterial		*curMat;



	// Compile the display list
	glNewList(Pass3ListID, GL_COMPILE);
	
	
	// --------------> LIGHTING <---------------
	// ---> PASS for SMOOTH light rendering <---

	if(FacesMatGour.size())
	{
		for(j=0; j < FacesMatGour.size(); j++)
		{
			curMat = FacesMatGour[j].mat;
			curMat->PutGLparams();
			
			facelist = &(FacesMatGour[j].faces);

			glBegin(GL_TRIANGLES);

				for(i=0; i< facelist->size(); i++)
				{
					curFace = (*facelist)[i];
					vrtRef	= curFace->VertRef;

					// Vertex number 0
					curVert = &(Verts[*vrtRef]);
					glNormal3fv(curVert->Normal.vals);
					glVertex3fv(curVert->vals);
					vrtRef++;
			
					// Vertex number 1
					curVert = &(Verts[*vrtRef]);
					glNormal3fv(curVert->Normal.vals);
					glVertex3fv(curVert->vals);
					vrtRef++;

					// Vertex number 2
					curVert = &(Verts[*vrtRef]);
					glNormal3fv(curVert->Normal.vals);
					glVertex3fv(curVert->vals);
				}

			glEnd();
		}
	}


	// --------------> LIGHTING <---------------
	// ----> PASS for FLAT light rendering <----
				
	if(FacesMatFlat.size())
	{
		for(j=0; j < FacesMatFlat.size(); j++)
		{
			curMat = FacesMatFlat[j].mat;
			curMat->PutGLparams();
			
			facelist = &(FacesMatFlat[j].faces);

			glBegin(GL_TRIANGLES);

				for(i=0; i< facelist->size(); i++)
				{
					curFace = (*facelist)[i];
					vrtRef	= curFace->VertRef;

					// Vertex number 0
					curVert = &(Verts[*vrtRef]);
					glNormal3fv(curFace->Normal.vals);
					glVertex3fv(curVert->vals);
					vrtRef++;
			
					// Vertex number 1
					curVert = &(Verts[*vrtRef]);
					glNormal3fv(curFace->Normal.vals);
					glVertex3fv(curVert->vals);
					vrtRef++;

					// Vertex number 2
					curVert = &(Verts[*vrtRef]);
					glNormal3fv(curFace->Normal.vals);
					glVertex3fv(curVert->vals);
				}

			glEnd();
		}
	}


	glEndList();

}



///////////////////////////////////////////////////////////////////////////////////////////////////
/// Create a display list for light rendering (CLASSIC mode)									///
///////////////////////////////////////////////////////////////////////////////////////////////////

void ZMesh::CreateListPass4()
{
	int				i, j;

	FaceList		*facelist;

	ZFace			*curFace;
	ZVert			*curVert;
	int				*vrtRef;
	


	// Compile the display list
	glNewList(Pass4ListID, GL_COMPILE);
	
	
	// --------------> LIGHTING <---------------
	// ----> PASS for FLAT light rendering <----

	if(FacesMatNo.size())
	{
		glShadeModel(GL_FLAT);

		for(j=0; j < FacesMatNo.size(); j++)
		{
			if(FacesMatNo[j].mat->IsOnMode(RENDER_TRANSP)==false)
			{
				facelist = &(FacesMatNo[j].faces);

				glBegin(GL_TRIANGLES);

					for(i=0; i< facelist->size(); i++)
					{
						curFace = (*facelist)[i];
						glColor3f(0.5f, 0.5f, 0.5f);
						vrtRef	= curFace->VertRef;

						// Vertex number 0
						curVert = &(Verts[*vrtRef]);
						glVertex3fv(curVert->vals);
						vrtRef++;
				
						// Vertex number 1
						curVert = &(Verts[*vrtRef]);
						glVertex3fv(curVert->vals);
						vrtRef++;

						// Vertex number 2
						curVert = &(Verts[*vrtRef]);
						glVertex3fv(curVert->vals);
					}

				glEnd();
			}
		}
	}


	glEndList();

}



///////////////////////////////////////////////////////////////////////////
/// General function of display lists									///
///////////////////////////////////////////////////////////////////////////
void ZMesh::CreateDisplayList()
{
	if(Pass1ListID != -1)		glDeleteLists(Pass1ListID, 1);
	if(Pass2ListID != -1)		glDeleteLists(Pass2ListID, 1);
	if(Pass3ListID != -1)		glDeleteLists(Pass3ListID, 1);
	if(Pass4ListID != -1)		glDeleteLists(Pass4ListID, 1);

	Pass1ListID		= glGenLists(1);
	Pass2ListID		= glGenLists(1);
	Pass3ListID		= glGenLists(1);
	Pass4ListID		= glGenLists(1);

	CreateListPass1();
	CreateListPass2();
	CreateListPass3();
	CreateListPass4();
}




///////////////////////////////////////////////////////////////////////////
/// General function of display lists									///
///////////////////////////////////////////////////////////////////////////
void ZMesh::DeleteDisplayList()
{
	if(Pass1ListID != -1)		glDeleteLists(Pass1ListID, 1);
	if(Pass2ListID != -1)		glDeleteLists(Pass2ListID, 1);
	if(Pass3ListID != -1)		glDeleteLists(Pass3ListID, 1);
	if(Pass4ListID != -1)		glDeleteLists(Pass4ListID, 1);

	Pass1ListID		= -1;
	Pass2ListID		= -1;
	Pass3ListID		= -1;
	Pass4ListID		= -1;
}








///////////////////////////////////////////////////////////////////////////////////////////////
/// MACRO de détermination d'un vertex partagé - Mesh definition							///
///////////////////////////////////////////////////////////////////////////////////////////////
#define FIND_SHARED_VERTEX_ZMesh											\
	ref    = *vrtRef;														\
	pere   = poss;															\
	nbVert = NbVerts;														\
	while(ref >= nbVert)													\
	{																		\
		ref -= nbVert;														\
		pere = (ZObject*) pere->father;										\
		nbVert = pere->GetMesh()->NbVerts;									\
	}




///////////////////////////////////////////////////////////////////////////
/// Creation des normales aux faces										///
///////////////////////////////////////////////////////////////////////////
void ZMesh::CreateFacesNormalsShared(ZObject *poss)
{
	ZVector3	a, b;

	ZFace		*curFace;
	int			*vrtRef;

	int			ref, nbVert;
	ZObject		*pere;
	ZVector3	pos[3];

	for(int i=0; i<NbFaces; i++)
	{
		curFace = &(Faces[i]);
		vrtRef	= curFace->VertRef;

		if(curFace->dependency)
		{
			// Vert 0
			FIND_SHARED_VERTEX_ZMesh
			pos[0] = pere->VertsTransf[ref];
			vrtRef++;

			// Vert 1
			FIND_SHARED_VERTEX_ZMesh
			pos[1] = pere->VertsTransf[ref];
			vrtRef++;

			// Vert 2
			FIND_SHARED_VERTEX_ZMesh
			pos[2] = pere->VertsTransf[ref];

			a = pos[0] - pos[1];
			b = pos[2] - pos[1];
		}
		else
		{
			a = poss->VertsTransf[*(vrtRef)]   - poss->VertsTransf[*(vrtRef+1)];
			b = poss->VertsTransf[*(vrtRef+2)] - poss->VertsTransf[*(vrtRef+1)];
		}

		curFace->Normal = b ^ a;
	}
}

void ZMesh::CreateFacesNormals()
{
	ZVector3	a, b;

	ZFace	*curFace;
	int		*vrtRef;

	for(int i=0; i<NbFaces; i++)
	{
		curFace = &(Faces[i]);
		vrtRef	= curFace->VertRef;

		a = Verts[*(vrtRef)]   - Verts[*(vrtRef+1)];
		b = Verts[*(vrtRef+2)] - Verts[*(vrtRef+1)];

		curFace->Normal = b ^ a;
	}
}



///////////////////////////////////////////////////////////////////////////
/// Creation des normales aux vertices									///
///////////////////////////////////////////////////////////////////////////
void ZMesh::CreateVertsNormals()
{
	// normales nulles au départ
	for(int i=0; i<NbVerts; i++)
	{
		Verts[i].Normal.SetNull();
	}

	// on additionne les normales des faces concourrantes
	ZVector3	*normal;
	ZFace		*curFace;
	int			*vrtRef;

	for(i=0; i<NbFaces; i++)
	{
		curFace = &(Faces[i]);
		vrtRef	= curFace->VertRef;
		normal	= &(curFace->Normal);

		if(curFace->dependency)
		{
			if(*vrtRef < NbVerts)		Verts[*vrtRef].Normal += (*normal);
			vrtRef++;
			if(*vrtRef < NbVerts)		Verts[*vrtRef].Normal += (*normal);
			vrtRef++;
			if(*vrtRef < NbVerts)		Verts[*vrtRef].Normal += (*normal);
		}
		else
		{
			Verts[*vrtRef].Normal += (*normal);
			vrtRef++;
			Verts[*vrtRef].Normal += (*normal);
			vrtRef++;
			Verts[*vrtRef].Normal += (*normal);
		}
	}

	for(i=0; i<NbVerts; i++)
	{
		if(Verts[i].Normal.SqLength() < 0.0000001f)		Verts[i].Normal.SetNull();
	}

}






///////////////////////////////////////////////////////////////////////////
/// Create rapid model													///
///////////////////////////////////////////////////////////////////////////
bool ZMesh::CreateRapidModel()
{
	int		*vrtRef;

	if(rapid!=NULL)		delete rapid;
	rapid = new RAPID_model;
	if(rapid==NULL)		return false;
	
	rapid->BeginModel();

		for(int i=0; i<NbFaces; i++)
		{
			vrtRef	= Faces[i].VertRef;
			rapid->AddTri(Verts[*(vrtRef)].vals, Verts[*(vrtRef+1)].vals, Verts[*(vrtRef+2)].vals, i);
		}
	
	rapid->EndModel();

	rapidCreated = true;

	return true;
}



///////////////////////////////////////////////////////////////////////////
/// Delete rapid model													///
///////////////////////////////////////////////////////////////////////////
void ZMesh::DeleteRapidModel()
{
	if(rapid!=NULL)		delete (rapid);
	rapidCreated = false;
}



///////////////////////////////////////////////////////////////////////////
/// Compute the OBB														///
///////////////////////////////////////////////////////////////////////////
void ZMesh::ComputeOBB()
{
	if(NbVerts<1)		return;

	xmin = xmax = Verts[0].x;
	ymin = ymax = Verts[0].y;
	zmin = zmax = Verts[0].z;
	
	ZVert	*vrt;

	for(int i=1; i<NbVerts; i++)
	{
		vrt = &(Verts[i]);

			 if(xmin > vrt->x)		xmin = vrt->x;
		else if(xmax < vrt->x)		xmax = vrt->x;

			 if(ymin > vrt->y)		ymin = vrt->y;
		else if(ymax < vrt->y)		ymax = vrt->y;

			 if(zmin > vrt->z)		zmin = vrt->z;
		else if(zmax < vrt->z)		zmax = vrt->z;
	}
}




