/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///																																  ///
///		FICHIER :	ZooMesh.cpp																									  ///
///																																  ///
///		NATURE	:	Management of the mesh, the face and the vertex (topology of a ZObject) for the 3D scene																		  ///
///																																  ///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



#include	"..\Datas\ZooMesh.h"
#include	"..\SCOL\winuser.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);
	UV3[0].SetCoord(0.0f, 0.0f);	UV3[1].SetCoord(1.0f, 0.0f);	UV3[2].SetCoord(0.0f, 1.0f);
	UV4[0].SetCoord(0.0f, 0.0f);	UV4[1].SetCoord(1.0f, 0.0f);	UV4[2].SetCoord(0.0f, 1.0f);

	clampU1 = clampV1 = clampU2 = clampV2 = clampU3 = clampV3 = clampU4 = clampV4 = 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()
{
#ifdef	_SCOL_DEBUG_
	MMechostr(0,"\nZMesh::ZMesh ");
#endif

	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);
	FacesLightMap.resize(0);

	FacesMatGour.resize(0);
	FacesMatFlat.resize(0);
	FacesMatNo.resize(0);
	
	FacesTransp.resize(0);

	// Dernières inits..
	multiTex	 = false;
	isAvatar	 = false ;

	//$LB (02/11/2004)
	texRenderMode = GL_CLAMP_TO_EDGE;
	
	rapid = NULL;
	rapidCreated = false;

	hasTopoChanged = hasViewChanged = true;

	dependency		  = false;
	
	displayListCreate = true;

	numberOfBones = 0 ;


	/* Add PassSkinningListID*/
	Pass1ListID = Pass2ListID = Pass3ListID = Pass4ListID = PassLightMapListID = PassSkinningListID = -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<FacesLightMap.size(); i++)	
	{
		FacesLightMap[i].ClampUV.flat.resize(0);	FacesLightMap[i].ClampUV.gour.resize(0);	FacesLightMap[i].ClampUV.no.resize(0);
		FacesLightMap[i].ClampU. flat.resize(0);	FacesLightMap[i].ClampU. gour.resize(0);	FacesLightMap[i].ClampU .no.resize(0);
		FacesLightMap[i].ClampV. flat.resize(0);	FacesLightMap[i].ClampV. gour.resize(0);	FacesLightMap[i].ClampV .no.resize(0);
		FacesLightMap[i].NoClamp.flat.resize(0);	FacesLightMap[i].NoClamp.gour.resize(0);	FacesLightMap[i].NoClamp.no.resize(0);
	}
	FacesLightMap.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(PassLightMapListID!=-1)			glDeleteLists(PassLightMapListID, 1);
	if(Pass3ListID!=-1)			glDeleteLists(Pass3ListID, 1);
	if(Pass4ListID!=-1)			glDeleteLists(Pass4ListID, 1);
	/* $MS : to delete skinning display list */
	if(PassSkinningListID!=-1)			glDeleteLists(PassSkinningListID, 1);
	DestroySkinningShader() ;
}



///////////////////////////////////////////////////////////////////////////
/// Creation des listes de faces										///
///////////////////////////////////////////////////////////////////////////
void ZMesh::MakeFacesList()
{
	int				j, k, n; 

#ifdef	_SCOL_DEBUG_
	MMechostr(0,"\nZMesh::MakeFacesList ");
#endif	


	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);
	FacesLightMap.resize(0);

	FacesMatGour.resize(0);
	FacesMatFlat.resize(0);
	FacesMatNo.resize(0);

	FacesTransp.resize(0);

	ZMaterial	*curMat;
	ZTexture	*tex1, *tex2, *lightMap;

	bool		idemTex1, idemTex2,idemLightMap, 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;
				idemLightMap = false ;

				tex1 = curMat->GetTexture1();
				tex2 = curMat->GetTexture2();
				lightMap = curMat->GetLightMap() ;

				// ---> Teste la présence d'une liste qui convient pour cette face <---
				j = k = n = 0;
				// PASS 1
				if(curMat->IsOnMode(RENDER_TRANSP) && !curMat->IsOnMode(RENDER_LIGHTMAP))		// 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) && !curMat->IsOnMode(RENDER_LIGHTMAP))					// ENVMAP
				{
					while( (j<FacesEnv.size()) && (!idemTex1) )
					{
						if (tex1 == FacesEnv[j].tex)		idemTex1 = true;
						j++;
					}
				}
				
				else
				if(!curMat->IsOnMode(RENDER_LIGHTMAP))
				{		
					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++;
				}
				
				// PASS LightMap
				while( (n<FacesLightMap.size()) && (!idemLightMap) )
				{
					if (lightMap == FacesLightMap[n].tex)		idemLightMap = true;
					n++;
				}
				
				
				if(!curMat->IsOnMode(RENDER_LIGHTMAP))
				{
					// ---> S'il existe une liste qui convient, on stocke <---
					// PASS 1
					if(curMat->IsOnMode(RENDER_TRANSP) /*&& !curMat->IsOnMode(RENDER_LIGHTMAP)*/)			// --- 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) /*&& !curMat->IsOnMode(RENDER_LIGHTMAP)*/)			// --- 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 ---
					if(!curMat->IsOnMode(RENDER_LIGHTMAP))
					{
						// 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)) && (!curMat->IsOnMode(RENDER_LIGHTMAP)) && (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) && !curMat->IsOnMode(RENDER_LIGHTMAP) && (tex2->activated) )
				{
					int curSize = FacesTex2.size();
					FacesTex2.resize(curSize+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;
				}
				
				
				// PASS 2
				if (idemLightMap && lightMap && (curMat->IsOnMode(RENDER_LIGHTMAP)) && (lightMap->activated))
				{
					n--;


					if(Faces[i].clampU2 && Faces[i].clampV2)		listFace = &FacesLightMap[n].ClampUV;
					else if(Faces[i].clampU2)						listFace = &FacesLightMap[n].ClampU;
					else if(Faces[i].clampV2)						listFace = &FacesLightMap[n].ClampV;
					else											listFace = &FacesLightMap[n].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( lightMap && curMat->IsOnMode(RENDER_LIGHTMAP) && (lightMap->activated) )
				{
					int curSize = FacesLightMap.size();
					FacesLightMap.resize(curSize+1);									// crée une nouvelle liste												
					FacesLightMap[n].lightMap = curMat->GetLightMap();
					if(curMat->GetTexture1() != NULL) FacesLightMap[n].tex = curMat->GetTexture1() ; 
					else FacesLightMap[n].tex = NULL;
					if(curMat->GetTexture2() != NULL) FacesLightMap[n].tex2 = curMat->GetTexture2() ;
					else FacesLightMap[n].tex2 = NULL;
					if(curMat->IsOnMode(RENDER_ENVMAP)) FacesLightMap[n].env = true ;
					else FacesLightMap[n].env = false ;
					if(curMat->IsOnMode(RENDER_TRANSP) && curMat->GetCoeffTransp()==0) FacesLightMap[n].colTransp = true ;
					else FacesLightMap[n].colTransp = false ;
					if(curMat->IsOnMode(RENDER_TEXTURED_BIS)) FacesLightMap[n].multi = true ;
					else FacesLightMap[n].multi = false ;

					FacesLightMap[n].ClampUV.flat.resize(0);	FacesLightMap[n].ClampUV.gour.resize(0);	FacesLightMap[n].ClampUV.no.resize(0);
					FacesLightMap[n].ClampU. flat.resize(0);	FacesLightMap[n].ClampU. gour.resize(0);	FacesLightMap[n].ClampU .no.resize(0);
					FacesLightMap[n].ClampV. flat.resize(0);	FacesLightMap[n].ClampV. gour.resize(0);	FacesLightMap[n].ClampV .no.resize(0);
					FacesLightMap[n].NoClamp.flat.resize(0);	FacesLightMap[n].NoClamp.gour.resize(0);	FacesLightMap[n].NoClamp.no.resize(0);

					if(Faces[i].clampU2 && Faces[i].clampV2)		listFace = &FacesLightMap[n].ClampUV;
					else if(Faces[i].clampU2)						listFace = &FacesLightMap[n].ClampU;
					else if(Faces[i].clampV2)						listFace = &FacesLightMap[n].ClampV;
					else											listFace = &FacesLightMap[n].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 && !curMat->IsOnMode(RENDER_LIGHTMAP))
			{
				///////////////////////////////////////////////////////////////////////////
				/// 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);							\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glColor3fv(curVert->color1.vals);							\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glColor3fv(curVert->color1.vals);							\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,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]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,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]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
			}																\
																			\
		glEnd();															\
	}	

						
#define RENDER_SHADE_LIST_TEXTURED_PASSLIGHTMAP_CLASSIC1					\
									 										\
	/***** 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;										\
				UV1		= curFace->UV3;										\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glColor3fv(curVert->color1.vals);							\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);			\
				glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV1->vals);			\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glColor3fv(curVert->color1.vals);							\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);			\
				glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV1->vals);			\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glColor3fv(curVert->color1.vals);							\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);			\
				glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV1->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;										\
				UV1		= curFace->UV3;										\
				glColor3fv(curFace->GetMaterial()->color1.vals);			\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);			\
				glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV1->vals);			\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);			\
				glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV1->vals);			\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);			\
				glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV1->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;										\
				UV1		= curFace->UV3;										\
				glColor3f(1.0f, 1.0f, 1.0f);								\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);			\
				glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV1->vals);			\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);			\
				glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV1->vals);			\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);			\
				glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV1->vals);			\
				glVertex3fv(curVert->vals);									\
			}																\
																			\
		glEnd();															\
	}	


#define RENDER_SHADE_LIST_TEXTURED_PASSLIGHTMAP_CLASSIC2					\
																			\
	/**** GOURAUD COLOR ****/												\
																			\
	if(shadeList->gour.size())												\
	{																		\
		glShadeModel(GL_SMOOTH);											\
		facelist = &(shadeList->gour);										\
																			\
		glBegin(GL_TRIANGLES);												\
		glActiveTextureARB( GL_TEXTURE0_ARB );								\
																			\
			for(i=0; i< facelist->size(); i++)								\
			{																\
				curFace = (*facelist)[i];									\
				vrtRef	= curFace->VertRef;									\
				UV		= curFace->UV3;										\
				UV1		= curFace->UV1;										\
				UV2		= curFace->UV2;										\
				alphaValue = 1.0 - curFace->GetMaterial()->alpha ;				\
					/* Vertex number 2 */									\
					curVert = &(Verts[*vrtRef]);								\
					glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV->vals);								\
					glColor4f(curVert->color1.x,curVert->color1.y,curVert->color1.z,alphaValue);				\
					glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV2->vals);								\
					glVertex3fv(curVert->vals);					\
					vrtRef++;												\
					UV++;													\
					UV1++;													\
					UV2++;													\
																			\
					/* Vertex number 2 */									\
					curVert = &(Verts[*vrtRef]);								\
					glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV->vals);								\
					glColor4f(curVert->color1.x,curVert->color1.y,curVert->color1.z,alphaValue);				\
					glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV2->vals);								\
					glVertex3fv(curVert->vals);					\
					vrtRef++;												\
					UV++;													\
					UV1++;													\
					UV2++;													\
																			\
					/* Vertex number 2 */									\
					curVert = &(Verts[*vrtRef]);								\
					glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV->vals);								\
					glColor4f(curVert->color1.x,curVert->color1.y,curVert->color1.z,alphaValue);				\
					glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV2->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->UV3;										\
				UV1		= curFace->UV1;										\
				UV2		= curFace->UV2;										\
				alphaValue = 1.0 - curFace->GetMaterial()->alpha ;\
				glColor4f(curFace->GetMaterial()->color1.x,curFace->GetMaterial()->color1.y,curFace->GetMaterial()->color1.z,alphaValue);			\
					/* Vertex number 2 */									\
					curVert = &(Verts[*vrtRef]);								\
					glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV2->vals);								\
					glVertex3fv(curVert->vals);					\
					vrtRef++;												\
					UV++;													\
					UV1++;													\
					UV2++;													\
																			\
					/* Vertex number 2 */									\
					curVert = &(Verts[*vrtRef]);								\
					glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV2->vals);								\
					glVertex3fv(curVert->vals);					\
					vrtRef++;												\
					UV++;													\
					UV1++;													\
					UV2++;													\
																			\
					/* Vertex number 2 */									\
					curVert = &(Verts[*vrtRef]);								\
					glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV2->vals);								\
					glVertex3fv(curVert->vals);					\
			}																\
																			\
			/** Default color **/											\
			facelist = &(shadeList->no);									\
																			\
			for(i=0; i< facelist->size(); i++)								\
			{																\
				curFace = (*facelist)[i];									\
				vrtRef	= curFace->VertRef;									\
				UV		= curFace->UV3;										\
				UV1		= curFace->UV1;										\
				UV2		= curFace->UV2;										\
				alphaValue = 1.0 - curFace->GetMaterial()->alpha ;\
				glColor4f(1.0f, 1.0f, 1.0f,alphaValue);								\
																			\
					/* Vertex number 2 */									\
					curVert = &(Verts[*vrtRef]);								\
					glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV2->vals);								\
					glVertex3fv(curVert->vals);					\
					vrtRef++;												\
					UV++;													\
					UV1++;													\
					UV2++;													\
																			\
					/* Vertex number 2 */									\
					curVert = &(Verts[*vrtRef]);								\
					glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV2->vals);								\
					glVertex3fv(curVert->vals);					\
					vrtRef++;												\
					UV++;													\
					UV1++;													\
					UV2++;													\
																			\
					/* Vertex number 2 */									\
					curVert = &(Verts[*vrtRef]);								\
					glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE2_ARB,UV->vals);								\
					glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV2->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);
	
	glActiveTextureARB(GL_TEXTURE2_ARB);
	glDisable(GL_TEXTURE_2D);
	glActiveTextureARB(GL_TEXTURE1_ARB);
	glDisable(GL_TEXTURE_2D);
	glActiveTextureARB(GL_TEXTURE0_ARB);
	glDisable(GL_TEXTURE_2D);
	

	// ************* 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->PutGLMultiparams0();

		///////////////////////////////////////////
		///				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->PutGLMultiparams0();


			///////////////////////////////////////////
			///				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->PutGLMultiparams0();

			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();



			glActiveTextureARB(GL_TEXTURE2_ARB);
			glDisable(GL_TEXTURE_2D);
			glActiveTextureARB(GL_TEXTURE1_ARB);
			glDisable(GL_TEXTURE_2D);
			glActiveTextureARB(GL_TEXTURE0_ARB);
			glDisable(GL_TEXTURE_2D);
}





#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;										\
				UV1		= curFace->UV1;										\
				alpha	= curFace->GetMaterial()->alpha;					\
				curFace->GetMaterial()->GetTexture1()->PutGLMultiparams0() ;\
				glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);\
				glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);						\
				glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);						\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				color	= &(curVert->color2);								\
				glColor4f(color->x, color->y, color->z, alpha);				\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);									\
				glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 1 */										\
				curVert = &(Verts[*vrtRef]);								\
				color	= &(curVert->color2);								\
				glColor4f(color->x, color->y, color->z, alpha);				\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);									\
				glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 2 */										\
				curVert = &(Verts[*vrtRef]);								\
				color	= &(curVert->color2);								\
				glColor4f(color->x, color->y, color->z, alpha);				\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);									\
				glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,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;										\
				UV1		= curFace->UV1;										\
				color	= &(curFace->GetMaterial()->color2);				\
				curFace->GetMaterial()->GetTexture1()->PutGLMultiparams0() ;\
				glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);\
				glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);						\
				glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);						\
				glColor4f(color->x, color->y, color->z, curFace->GetMaterial()->alpha);		\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);									\
				glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);									\
				glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);									\
				glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,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;										\
				UV1		= curFace->UV1;										\
				color	= &(curFace->GetMaterial()->color);					\
				curFace->GetMaterial()->GetTexture1()->PutGLMultiparams0() ;\
				glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);\
				glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);						\
				glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);						\
				glColor4f(1.0f, 1.0f, 1.0f, curFace->GetMaterial()->alpha);	\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);									\
				glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);									\
				glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
				UV1++;														\
																			\
				/* Vertex number 0 */										\
				curVert = &(Verts[*vrtRef]);								\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV1->vals);									\
				glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,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;
	ZUV				*UV1;
	int				*vrtRef;
	
	ZTexture		*curTex;

	float			alpha;

	FacesBySHADE	*shadeList;


	// Compile the new display list
	glNewList(Pass2ListID, GL_COMPILE);

	glActiveTextureARB(GL_TEXTURE0_ARB);
	glDisable(GL_TEXTURE_2D);
	glActiveTextureARB(GL_TEXTURE1_ARB);
	glDisable(GL_TEXTURE_2D);
	
	

	// --------------------------------------------------------
	// ------------- Treatment by type of texture -------------
	// --------------------------------------------------------

	glEnable(GL_TEXTURE_2D);

	for(j=0; j<FacesTex2.size(); j++)
	{

		curTex = FacesTex2[j].tex;
		curTex->PutGLMultiparams1();

		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
		

		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
		}

			glActiveTextureARB(GL_TEXTURE2_ARB);
			glDisable(GL_TEXTURE_2D);
			glActiveTextureARB(GL_TEXTURE1_ARB);
			glDisable(GL_TEXTURE_2D);
			glActiveTextureARB(GL_TEXTURE0_ARB);
			glDisable(GL_TEXTURE_2D);
	}

			

	
	glEndList();

}


///////////////////////////////////////////////////////////////////////////////////////////////////
/// Create a display list for light rendering (CLASSIC mode)									///
///////////////////////////////////////////////////////////////////////////////////////////////////

void ZMesh::CreateListPassLightMap()
{
	
	int				i, j;
	FaceList		*facelist;
	ZVert			*curVert;
	ZVector3		*color;
	ZTexture		*curTex;
	float			alpha;
	ZFace			*curFace;
	ZUV				*UV;
	ZUV				*UV1;
	ZUV				*UV2;
	int				*vrtRef;
	float			alphaValue ;
	ZTexture		*curLightMap;
	ZTexture		*curTex1;
	ZTexture		*curTex2;
	int				nbVert;
	int				ref;
	ZObject			*pere;
	FacesBySHADE	*shadeList;

	// Compile the new display list
	glNewList(PassLightMapListID, GL_COMPILE);

	glActiveTextureARB(GL_TEXTURE2_ARB);
	glDisable(GL_TEXTURE_2D);
	glActiveTextureARB(GL_TEXTURE1_ARB);
	glDisable(GL_TEXTURE_2D);
	glActiveTextureARB(GL_TEXTURE0_ARB);
	glDisable(GL_TEXTURE_2D);

	for(j=0; j<FacesLightMap.size(); j++)
	{	
		curLightMap = FacesLightMap[j].lightMap;
		curTex1 = FacesLightMap[j].tex ;
		curTex2 = FacesLightMap[j].tex2 ;

		if(curTex1 && (!curTex2 || FacesLightMap[j].multi == false) ) 
		{
				curLightMap->PutGLMultiparams2();
				curTex1->PutGLMultiparams0() ;
			///////////////////////////////////////////
			///				clamp u v				///
			///////////////////////////////////////////

			shadeList = &FacesLightMap[j].ClampUV;

			if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
			{
				if(FacesLightMap[j].env)
				{
					//$LB (02/11/2004)
					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);
				}
				else
				{
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
				}
				RENDER_SHADE_LIST_TEXTURED_PASSLIGHTMAP_CLASSIC1
			}

		    glDisable(GL_TEXTURE_GEN_S);
			glDisable(GL_TEXTURE_GEN_T);

			///////////////////////////////////////////
			///				clamp u 				///
			///////////////////////////////////////////
			
			shadeList = &FacesLightMap[j].ClampU;

			if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
			{
				if(FacesLightMap[j].env)
				{
					//$LB (02/11/2004)
					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);
				}
				else
				{
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
				}

				RENDER_SHADE_LIST_TEXTURED_PASSLIGHTMAP_CLASSIC1
			}

		//	glDisable(GL_TEXTURE_GEN_S);
		//	glDisable(GL_TEXTURE_GEN_T);


			///////////////////////////////////////////
			///				clamp V 				///
			///////////////////////////////////////////
			
			shadeList = &FacesLightMap[j].ClampV;

			if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
			{
				if(FacesLightMap[j].env)
				{
					//$LB (02/11/2004)
					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);
				}
				else
				{
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
				}
			
				RENDER_SHADE_LIST_TEXTURED_PASSLIGHTMAP_CLASSIC1
			}
		//	glDisable(GL_TEXTURE_GEN_S);
		//	glDisable(GL_TEXTURE_GEN_T);

			///////////////////////////////////////////
			///				No clamp  				///
			///////////////////////////////////////////
			
			shadeList = &FacesLightMap[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);
				if(FacesLightMap[j].env)
				{
					glEnable(GL_TEXTURE_GEN_S);
					glEnable(GL_TEXTURE_GEN_T);
				}
				
				RENDER_SHADE_LIST_TEXTURED_PASSLIGHTMAP_CLASSIC1
			}
		//	glDisable(GL_TEXTURE_GEN_S);
		//	glDisable(GL_TEXTURE_GEN_T);
			glActiveTextureARB(GL_TEXTURE0_ARB);
			glDisable(GL_TEXTURE_2D);

			glActiveTextureARB(GL_TEXTURE1_ARB);
			glDisable(GL_TEXTURE_2D);
		}
		else
		if(curTex1 && curTex2) 
		{
			
				
				curTex1->PutGLMultiparams0() ;
				//glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

				curTex2->PutGLMultiparams1();
				
				glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
				glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB );

				glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
				glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );

				glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
				glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );

				glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PRIMARY_COLOR_ARB );
				glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA );
				
				curLightMap->PutGLMultiparams2() ;
				

			///////////////////////////////////////////
			///				clamp u v				///
			///////////////////////////////////////////

			shadeList = &FacesLightMap[j].ClampUV;

			if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
			{
				if(FacesLightMap[j].env)
				{
					//$LB (02/11/2004)
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

					glActiveTextureARB (GL_TEXTURE0_ARB);
					glEnable(GL_TEXTURE_GEN_S);
					glEnable(GL_TEXTURE_GEN_T);
				}
				else
				{
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
				}
				RENDER_SHADE_LIST_TEXTURED_PASSLIGHTMAP_CLASSIC2
			}
			glDisable(GL_TEXTURE_GEN_S);
			glDisable(GL_TEXTURE_GEN_T);

			///////////////////////////////////////////
			///				clamp u 				///
			///////////////////////////////////////////
			
			shadeList = &FacesLightMap[j].ClampU;

			if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
			{
				if(FacesLightMap[j].env)
				{
					//$LB (02/11/2004)
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

					glActiveTextureARB (GL_TEXTURE0_ARB);
					glEnable(GL_TEXTURE_GEN_S);
					glEnable(GL_TEXTURE_GEN_T);
				}
				else
				{
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
				}
				RENDER_SHADE_LIST_TEXTURED_PASSLIGHTMAP_CLASSIC2
			}

		//	glDisable(GL_TEXTURE_GEN_S);
		//	glDisable(GL_TEXTURE_GEN_T);


			///////////////////////////////////////////
			///				clamp V 				///
			///////////////////////////////////////////
			
			shadeList = &FacesLightMap[j].ClampV;

			if(shadeList->flat.size() || shadeList->gour.size() || shadeList->no.size())
			{
				if(FacesLightMap[j].env)
				{
					//$LB (02/11/2004)
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

					glActiveTextureARB (GL_TEXTURE0_ARB);
					glEnable(GL_TEXTURE_GEN_S);
					glEnable(GL_TEXTURE_GEN_T);
				}
				else
				{
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
				}
				RENDER_SHADE_LIST_TEXTURED_PASSLIGHTMAP_CLASSIC2
			}

		//	glDisable(GL_TEXTURE_GEN_S);
		//	glDisable(GL_TEXTURE_GEN_T);

			///////////////////////////////////////////
			///				No clamp  				///
			///////////////////////////////////////////
			
			shadeList = &FacesLightMap[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);
				if(FacesLightMap[j].env)
				{
					glActiveTextureARB (GL_TEXTURE0_ARB);
					glEnable(GL_TEXTURE_GEN_S);
					glEnable(GL_TEXTURE_GEN_T);
				}

				RENDER_SHADE_LIST_TEXTURED_PASSLIGHTMAP_CLASSIC2
			}

		//	glDisable(GL_TEXTURE_GEN_S);
		//	glDisable(GL_TEXTURE_GEN_T);

			glActiveTextureARB(GL_TEXTURE0_ARB);
			glDisable(GL_TEXTURE_2D);

			glActiveTextureARB(GL_TEXTURE1_ARB);
			glDisable(GL_TEXTURE_2D);

			glActiveTextureARB(GL_TEXTURE2_ARB);
			glDisable(GL_TEXTURE_2D);
		}
		
			glActiveTextureARB(GL_TEXTURE2_ARB);
			glDisable(GL_TEXTURE_2D);
			glActiveTextureARB(GL_TEXTURE1_ARB);
			glDisable(GL_TEXTURE_2D);
			glActiveTextureARB(GL_TEXTURE0_ARB);
			glDisable(GL_TEXTURE_2D);
			

			
}
		//	glDisable(GL_TEXTURE_GEN_S);
		//	glDisable(GL_TEXTURE_GEN_T);
	

        	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();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////     Mise en place du shader gèrant le skinning et la déformation de mesh ////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* $MS : Modification Shader pour chipset graphique */
void ZMesh::SetskinningShader()
{
/* MS : Dynamically construct shader program */
	string v,f,v1,v2,v3 ;
	std::ostringstream oss;

    
	v1 = " struct appdata {float3 Position   : POSITION;    float3 Normal     : NORMAL;    float3 Color      : DIFFUSE;    float2 TexCoord0  : TEXCOORD0;    float3 S          : TEXCOORD1;    float3 T          : TEXCOORD2;    float3 SxT        : TEXCOORD3;    float4 Weights    : TEXCOORD4;    float4 Indices    : TEXCOORD5;};struct vpconn {    float4 HPosition : POSITION;    float4 TexCoord0 : TEXCOORD0;    float4 Color0    : COLOR0;};vpconn main(appdata IN,uniform float4x4 WorldViewProj,uniform float4x4 ModelViewProj,uniform float4x4 ModelViewInverseProj,uniform float4x4 AvaViewProj,uniform float3x4 Bones[";
	oss << numberOfBones;
    v2 = oss.str();
	v3 = "],uniform float[7] attenuate_const,uniform float3 ambiant[7],uniform float3 diffuse[7],uniform float3 specular[7]){    vpconn OUT;    float4 tempPos = float4( 0.0, 0.0, 0.0, 0.0 );    tempPos.xyz = IN.Position.xyz;      tempPos.w = 1.0;    float i = IN.Indices.x;    float3x3 m;    m[0] = Bones[i][0].xyz;    m[1] = Bones[i][1].xyz;    m[2] = Bones[i][2].xyz;    float3 pos0 = mul(Bones[i], tempPos);    float3 normal0 = mul(m, IN.Normal);    i = IN.Indices.y;    m[0] = Bones[i][0].xyz;    m[1] = Bones[i][1].xyz;    m[2] = Bones[i][2].xyz;    float3 pos1 = mul(Bones[i], tempPos);    float3 normal1 = mul(m, IN.Normal);    float3 finalNormal = normalize(normal0 * IN.Weights.x + normal1 * IN.Weights.y);    float3 finalPos = float3( 0.0, 0.0, 0.0);    finalPos = (pos0 * IN.Weights.x) + (pos1 * IN.Weights.y);    OUT.TexCoord0.x = OUT.TexCoord0.y = 0.0 ;    OUT.TexCoord0.xy = IN.TexCoord0.xy;    float4 tempPos2 = float4( 0.0, 0.0, 0.0, 0.0 );    tempPos2.x = finalPos.x;    tempPos2.y = finalPos.y;    tempPos2.z = finalPos.z;    tempPos2.w = 1.0;    tempPos2 = mul(tempPos2,ModelViewProj) ;    tempPos2 = mul(WorldViewProj, tempPos2);    OUT.HPosition = tempPos2 ;     OUT.Color0.xyz = IN.Color.xyz ;    /*OUT.Color0.xyz = ambiant[0].xyz + ambiant[1].xyz + ambiant[2].xyz + ambiant[3].xyz + ambiant[4].xyz + ambiant[5].xyz + ambiant[6].xyz + 0.3;  */  OUT.Color0.w = 0.0 ;  return OUT;}";
	v = v1 + v2 + v3 ;
	f = "struct FragmentIn{ float4 color      : COLOR;   float2 texCoord   : TEXCOORD0;};struct FragmentOut{   float4 color      : COLOR;};FragmentOut main(FragmentIn In, uniform sampler2D decal){   FragmentOut Out;   Out.color.x = 0.0 ;   Out.color.y = 0.0 ;   Out.color.z = 0.0 ;   Out.color.w = 0.0 ;   Out.color = tex2D(decal, In.texCoord) ;  Out.color *= In.color;   return Out;}";
  // First determine which vertex shader profile we will use, this will basically be
   // the first one we support.
   cgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
   cgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);

   if(cgVertexProfile == CG_PROFILE_UNKNOWN || cgVertexProfile == CG_INVALID_ENUMERANT_ERROR)
      {
//         MessageBox(NULL,"Hardware does not support vertex shaders!", "Error",MB_OK);
      }

   if(cgFragmentProfile == CG_PROFILE_UNKNOWN || cgFragmentProfile == CG_INVALID_ENUMERANT_ERROR)
      {
 //        MessageBox(NULL,"Hardware does not support fragment shaders!", "Error",MB_OK);
      }
  
   // Create our context for cg.
   cgContext = cgCreateContext();
   // Create the vertex shader.
    // cgVertexProgram = cgCreateProgramFromFile(cgContext, CG_SOURCE, "Cg/ShaderVertexSkinning.cg",cgVertexProfile, "main", NULL);
     cgVertexProgram = cgCreateProgram(cgContext, CG_SOURCE, v.c_str(),cgVertexProfile, "main", NULL);
   // Create the fragment shader.
   //  cgFragmentProgram = cgCreateProgramFromFile(cgContext, CG_SOURCE, "Cg/ShaderFragmentSkinning.cg",cgFragmentProfile, "main", NULL);
     cgFragmentProgram = cgCreateProgram(cgContext, CG_SOURCE, f.c_str(),cgFragmentProfile, "main", NULL);

   // Error checking to see if the shaders loaded.
   if(!cgVertexProgram)
      {
         MessageBox(NULL, "Error creating vertex shader!", "Error",MB_OK);
      }

   if(!cgFragmentProgram)
      {
        MessageBox(NULL, "Error creating fragment shader!", "Error",MB_OK);
   }

   // Load the vertex/fragment shaders into OpenGL.
   cgGLLoadProgram(cgVertexProgram);
   cgGLLoadProgram(cgFragmentProgram);

}


void ZMesh::DestroySkinningShader()
{
	//cgGLDisableTextureParameter(cgTexture) ;
	//cgDestroyProgram(cgVertexProgram);
	//cgDestroyProgram(cgFragmentProgram);
}


void  ZMesh::worldDebug(ZTexture *tex)
{
		MMechostr(1,"currentMesh name: %s\n",this->name.c_str()) ;
		MMechostr(1,"current Tex: %s\n",tex->name.c_str()) ;
}



#define RENDER_SHADE_LIST_TEXTURED_AVATAR									\
																			\
	/* Gouraud */															\
																			\
	if(shadeList->flat.size())												\
	{																		\
		glShadeModel(GL_SMOOTH);											\
		facelist = &(shadeList->flat);										\
																			\
		glBegin(GL_TRIANGLES);												\
																			\
			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]);								\
				cgGLSetParameter4f(Indices,curVert->ID1,curVert->ID2,0.0,0.0) ;\
				cgGLSetParameter4f(Weights,curVert->weight1,curVert->weight2,0.0,0.0) ;\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 1 */										\
				curVert = &(Verts[*vrtRef]);								\
				cgGLSetParameter4f(Indices,curVert->ID1,curVert->ID2,0.0,0.0) ;\
				cgGLSetParameter4f(Weights,curVert->weight1,curVert->weight2,0.0,0.0) ;\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
				vrtRef++;													\
				UV++;														\
																			\
				/* Vertex number 2 */										\
				curVert = &(Verts[*vrtRef]);								\
				cgGLSetParameter4f(Indices,curVert->ID1,curVert->ID2,0.0,0.0) ;\
				cgGLSetParameter4f(Weights,curVert->weight1,curVert->weight2,0.0,0.0) ;\
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,UV->vals);									\
				glVertex3fv(curVert->vals);									\
			}																\
																			\
		glEnd();															\
	}																		\
																			\
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Create a display list for Shader Skinning rendering (CLASSIC mode)									///
///////////////////////////////////////////////////////////////////////////////////////////////////
/* $MS : Display list for optimisation of avatar skinning */
void ZMesh::CreateListPassSkinning()
{
		int				i, j;

	FaceList		*facelist;

	ZFace			*curFace;
	ZVert			*curVert;
	int				*vrtRef;
	FacesBySHADE	*shadeList;
	ZTexture		*curTex;
	ZUV				*UV;
	
	// Compile the display list
	glNewList(PassSkinningListID, GL_COMPILE);
	


	// --------------------------------------------------------
	// ------------- Treatment by type of texture -------------
	// --------------------------------------------------------

	glEnable(GL_TEXTURE_2D);
	glDisable(GL_BLEND);
	glDisable(GL_ALPHA_TEST);

	//cgTexture    = cgGetNamedParameter(cgFragmentProgram, "decal");

	for(j=0; j<FacesTex1.size(); j++)
	{
		curTex = FacesTex1[j].tex;
		curTex->PutGLMultiparams0();
		//cgGLSetTextureParameter( cgTexture, curTex->texID );		
		//cgGLEnableTextureParameter( cgTexture );					


		///////////////////////////////////////////
		///				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_AVATAR
		}

		///////////////////////////////////////////
		///				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_AVATAR
		}

		///////////////////////////////////////////
		///				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_AVATAR
		}

		///////////////////////////////////////////
		///				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_AVATAR
		}

	}
	
glEndList();
}




///////////////////////////////////////////////////////////////////////////
/// General function of display lists									///
///////////////////////////////////////////////////////////////////////////
void ZMesh::CreateDisplayList()
{
	if(Pass1ListID != -1)		glDeleteLists(Pass1ListID, 1);
	if(Pass2ListID != -1)		glDeleteLists(Pass2ListID, 1);
	if(PassLightMapListID != -1)		glDeleteLists(PassLightMapListID, 1);
	if(Pass3ListID != -1)		glDeleteLists(Pass3ListID, 1);
	if(Pass4ListID != -1)		glDeleteLists(Pass4ListID, 1);
	/* $MS : Delete Display list */
	if(PassSkinningListID != -1)		glDeleteLists(PassSkinningListID, 1);

	Pass1ListID		= glGenLists(1);
	Pass2ListID		= glGenLists(1);
	PassLightMapListID		= glGenLists(1);
	Pass3ListID		= glGenLists(1);
	Pass4ListID		= glGenLists(1);
	/* $MS : Delete Display list */
	PassSkinningListID		= glGenLists(1);

	CreateListPass1();
	CreateListPass2();
	CreateListPassLightMap();
	CreateListPass3();
	CreateListPass4();
	CreateListPassSkinning();
}




///////////////////////////////////////////////////////////////////////////
/// General function of display lists									///
///////////////////////////////////////////////////////////////////////////
void ZMesh::DeleteDisplayList()
{
	if(Pass1ListID != -1)		glDeleteLists(Pass1ListID, 1);
	if(Pass2ListID != -1)		glDeleteLists(Pass2ListID, 1);
	if(PassLightMapListID != -1)		glDeleteLists(PassLightMapListID, 1);
	if(Pass3ListID != -1)		glDeleteLists(Pass3ListID, 1);
	if(Pass4ListID != -1)		glDeleteLists(Pass4ListID, 1);
	/* $MS : Delete display list */
	if(PassSkinningListID != -1)		glDeleteLists(PassSkinningListID, 1);

	Pass1ListID		= -1;
	Pass2ListID		= -1;
	PassLightMapListID		= -1;
	Pass3ListID		= -1;
	Pass4ListID		= -1;
	/* $MS : Pass Skinning display list delete */
	PassSkinningListID		= -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;
	}
}




