Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Arbol.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Arbol.cpp	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Arbol.cpp	(revision 830)
@@ -0,0 +1,645 @@
+#include <GL\glut.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "Arbol.h"
+#include "../defs.h"
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Void constructor
+// Parameters --> None
+//--------------------------------------------------------------------------------------------------------------------------------
+/*Arbol::Arbol(void):  Vertices(NULL), Hojas(NULL)
+{
+	cx = cy= cz=0;
+}*/
+//--------------------------------------------------------------------------------------------------------------------------------
+// Constructor with the name of a file cotaining the data
+//--------------------------------------------------------------------------------------------------------------------------------
+Arbol::Arbol (const char * arbol, const char* hojas, const char* simplifi, Geometry::CREATEVERTEXDATAFUNC vdfun, Geometry::CREATEINDEXDATAFUNC idfun): 
+create_vertex_data_func(vdfun==NULL?Geometry::DefaultVertexDataCreator:vdfun),
+create_index_data_func(idfun==NULL?Geometry::DefaultIndexDataCreator:idfun),
+vertexdata(NULL), Hojas(NULL), MinDet(NULL)
+{	
+	cx = cy= cz= 0;
+	ReadFromFile (arbol, hojas, simplifi);
+
+	// esto no sé si devería haber akí
+	indexdata->SetNumValidIndices(0);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Destructor. We must deallocate the memory allocated for pointers to vertices and edges
+//--------------------------------------------------------------------------------------------------------------------------------
+Arbol::~Arbol (void)
+{
+	if (vertexdata) delete vertexdata;
+	if (indexdata) delete indexdata;
+	delete Hojas;
+	delete MinDet;
+//	delete [] normales_vert;
+}
+
+
+//
+//
+//--------------------------------------------------------------------------------------------------------------------------------
+// leer informacion desde el fichero
+//--------------------------------------------------------------------------------------------------------------------------------
+void Arbol::ReadFromFile ( const char * arbol, const char* hojas, const char* simpli/*, char* tronco*/) // Reads a obj-model from a file
+{
+	    
+	//VERTICES
+	if ((TotVerts=LeeVertices(arbol))==0) ThrowFileNotFoundError((const char*)arbol);
+	if ((nHojas = LeoHojas (hojas))==0) ThrowFileNotFoundError((const char*)hojas);
+//	TotTronco = LeoTronco (tronco);
+//	CalculaNormalesVertice();	
+	if ((TotHojas = LeoHojasSimpl(simpli))==0) ThrowFileNotFoundError((const char*)simpli);	
+	RellenoRaiz();
+
+	CalculaTexCoordsYNorms();
+}
+
+
+#include "TMatrix.h"
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Procesar línea para extraer los VERTICES DE VERTICES.OBJ
+//--------------------------------------------------------------------------------------------------------------------------------
+int Arbol::LeeVertices ( const char *  arbol)
+
+{
+		FILE* fp_origen;
+		char linea[256], str[20];
+		float x,y,z;
+		int countv=0;
+		bool fin_vertices = false;
+
+/*		TMatrix rot90mat;
+		rot90mat.RotateX(-90);
+*/		
+		//cuento todos los vertices, y relleno la estructura
+		if ((fp_origen = fopen (arbol, "r")) == NULL)
+		{
+			printf ("No he podido abrir el fichero %s\n", arbol);
+			return 0;
+		}
+		else
+		{
+			while ((fgets (linea, 255, fp_origen) != NULL) && (fin_vertices == false))
+		
+				
+				switch (linea[0])
+				{
+					case '#':
+						switch ( linea[2])
+						{
+						case 'v':
+							sscanf(linea,"# %s %lu",  str, &countv);
+							if ( countv > 0){
+									//Vertices  = new Point3D[2*countv];
+									//tex_coords=new float[countv*2];
+									vertexdata = create_vertex_data_func(2*countv);
+									Hojas = new Hoja[countv*2];
+									indexdata = create_index_data_func(countv*2*3); // 3 indices x 2 triangulos x hoja
+									vertexdata->Begin();
+									//para impostores
+
+							}
+							countv=0;
+							break;
+						
+						default:
+							break;
+
+						}
+						break;
+					case 'v':
+						switch (linea[1])
+						{
+							case ' ':
+								{
+							sscanf (linea, "v %f %f %f ", &x, &y, &z);
+							//Vertices[countv].Update( x, y, z); para girarlo
+							//Vertices[countv].Update( x, z, y);
+
+//							Vector rotv(x,y,z);
+//							rotv = rot90mat * rotv;
+							
+							vertexdata->SetVertexCoord(countv,x,z,-y);
+							
+							countv++;
+								break;
+								}
+							case 't':
+							// PASAMOS DE ESTO: LAS COORDENADAS DE TEXTURA DE LAS HOJAS SE CALCULAN A MANO Y LAS DEL TRONCO NO SE NECESITAN AKI
+							sscanf (linea, "vt %f %f", &x, &y);
+							//printf ("%f %f:%s", x, y,linea);
+//							tex_coords[countv*2]=x;
+//							tex_coords[countv*2+1]=y;
+							//vertexdata->Begin();
+//							vertexdata->SetVertexTexCoord(countv-1,x,y); // -1 porque al cargar el vertice antes se incrementa countv
+							//vertexdata->End();
+
+								break;
+
+							default :
+								break;
+						}
+						break;
+
+
+					default:
+						break;
+	
+				}
+
+		fclose (fp_origen);
+		}
+
+		vertexdata->End();
+		return ( countv);
+
+		
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Calcular las normales de las hojas
+//--------------------------------------------------------------------------------------------------------------------------------
+
+void Arbol::GetNormalH (Hoja &aHoja)
+{
+
+	float onex, oney, onez;
+	float twox, twoy, twoz;
+	float threex, threey, threez;
+
+/*	Vertices[aHoja.Vert_Hoja[0]].GetCoordinates (onex, oney, onez);
+	Vertices[aHoja.Vert_Hoja[1]].GetCoordinates(twox, twoy, twoz);
+	Vertices[aHoja.Vert_Hoja[2]].GetCoordinates (threex, threey, threez);*/
+
+	vertexdata->GetVertexCoord(aHoja.Vert_Hoja[0],onex,oney,onez);
+	vertexdata->GetVertexCoord(aHoja.Vert_Hoja[1],twox,twoy,twoz);
+	vertexdata->GetVertexCoord(aHoja.Vert_Hoja[2],threex,threey,threez);
+
+	float v1[3]={twox-onex,twoy-oney,twoz-onez};
+	float v2[3]={threex-onex,threey-oney,threez-onez};
+
+	Normalize(v1,v1);
+	Normalize(v2,v2);
+	
+//	aHoja.Normal[0] = (twoz-onez)*(threey-oney) - (twoy-oney)*(threez-onez);
+//	aHoja.Normal[1] = (twox-onex)*(threez-onez) - (threex-onex)*(twoz-onez);
+//	aHoja.Normal[2] = (threex-onex)*(twoy-oney) - (twox-onex)*(threey-oney);
+
+	CrossProduct(v1,v2,aHoja.Normal);
+
+	
+}
+
+
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Calcular las normales del tronco
+//--------------------------------------------------------------------------------------------------------------------------------
+
+/*void Arbol::GetNormalT (Tronco &aTronco)
+{
+
+	float onex, oney, onez;
+	float twox, twoy, twoz;
+	float threex, threey, threez;
+
+	Vertices[aTronco.Vert_Tronco[0]].GetCoordinates (onex, oney, onez);
+	Vertices[aTronco.Vert_Tronco[1]].GetCoordinates(twox, twoy, twoz);
+	Vertices[aTronco.Vert_Tronco[2]].GetCoordinates (threex, threey, threez);
+	
+//	aTronco.Normal[0] = (twoz-onez)*(threey-oney) - (twoy-oney)*(threez-onez);
+//	aTronco.Normal[1] = (twox-onex)*(threez-onez) - (threex-onex)*(twoz-onez);
+//	aTronco.Normal[2] = (threex-onex)*(twoy-oney) - (twox-onex)*(threey-oney);
+
+	
+}
+*/
+
+void Arbol::CrossProduct(const float *v1, const float *v2, float *res)
+{
+	res[0] = v1[1]*v2[2] - v1[2]*v2[1];
+	res[1] = v1[2]*v2[0] - v1[0]*v2[2];
+	res[2] = v1[0]*v2[1] - v1[1]*v2[0];
+}
+
+void Arbol::Normalize(const float *v, float *res)
+{
+	float module=sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+	res[0]=v[0]/module;
+	res[1]=v[1]/module;
+	res[2]=v[2]/module;
+}
+
+/*void Arbol::CalculaNormalesVertice(void)
+{
+	int l;
+	normales_vert = new float[TotVerts*3];
+	unsigned int i,j;
+	float onex, oney, onez;
+	float twox, twoy, twoz;
+	float threex, threey, threez;
+	unsigned int iv[3];
+
+
+	for (i=0; i<TotVerts; i++)
+	{
+		normales_vert[i*3+0] = 0.0f;
+		normales_vert[i*3+1] = 0.0f;
+		normales_vert[i*3+2] = 0.0f;
+	}
+
+	
+	for (i=0; i<TotTronco; i++)
+	{
+		//unsigned int iv[3] = { Troncos[i].Vert_Tronco[0], Troncos[i].Vert_Tronco[1], Troncos[i].Vert_Tronco[3] };
+		iv[0]=Troncos[i].Vert_Tronco[0];
+		iv[1]=Troncos[i].Vert_Tronco[1];
+		iv[2]=Troncos[i].Vert_Tronco[2];
+
+		float auxnormal[3]={0.0f, 0.0f, 0.0f};
+
+//		if (iv[0] != iv[1] && iv[0] != iv[2] && iv[1] != iv[2])
+//		{
+
+			Vertices[iv[0]].GetCoordinates (onex, oney, onez);
+			Vertices[iv[1]].GetCoordinates(twox, twoy, twoz);
+			Vertices[iv[2]].GetCoordinates (threex, threey, threez);
+
+			float vd1[3] = {	twox - onex, 
+								twoy - oney, 
+								twoz - onez };
+
+			float vd2[3] = {	threex - onex, 
+								threey - oney, 						
+								threez - onez };
+
+			Normalize(vd1,vd1);
+			Normalize(vd2,vd2);
+//			if (i%2)
+				CrossProduct(vd2,vd1,auxnormal);
+//			else
+//				CrossProduct(vd1,vd2,auxnormal);
+
+//		}
+
+		for (j=0; j<3; j++)
+		{
+			normales_vert[iv[j]*3+0] += auxnormal[0];
+			normales_vert[iv[j]*3+1] += auxnormal[1];
+			normales_vert[iv[j]*3+2] += auxnormal[2];
+		}
+	}
+
+		
+	for (i=0; i<TotVerts; i++)
+	{
+		if ((normales_vert[i*3]!=0.0)||(normales_vert[i*3+1]!=0.0)||(normales_vert[i*3+2]!=0.0))
+			Normalize(normales_vert+i*3, normales_vert+i*3);
+		
+	}
+
+	
+	for (i=0; i<TotTronco; i++)
+	{
+		iv[0]=Troncos[i].Vert_Tronco[0];
+		iv[1]=Troncos[i].Vert_Tronco[1];
+		iv[2]=Troncos[i].Vert_Tronco[2];
+
+
+		Troncos[i].Normal[0][0]=normales_vert[iv[0]*3];
+		Troncos[i].Normal[0][1]=normales_vert[iv[0]*3+1];
+		Troncos[i].Normal[0][2]=normales_vert[iv[0]*3+2];
+		Troncos[i].Normal[1][0]=normales_vert[iv[1]*3];
+		Troncos[i].Normal[1][1]=normales_vert[iv[1]*3+1];
+		Troncos[i].Normal[1][2]=normales_vert[iv[1]*3+2];
+		Troncos[i].Normal[2][0]=normales_vert[iv[2]*3];
+		Troncos[i].Normal[2][1]=normales_vert[iv[2]*3+1];
+		Troncos[i].Normal[2][2]=normales_vert[iv[2]*3+2];
+	}
+
+	delete [] normales_vert;
+
+}*/
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Procesar línea para extraer las HOJAS DE HOJAS.OBJ
+//--------------------------------------------------------------------------------------------------------------------------------
+
+  int Arbol::LeoHojas (const char* hojas)
+{
+	FILE* fp_hojas;
+	char linea[256];
+
+	int v1, v2, v3, h=0;
+	
+
+
+	if ((fp_hojas = fopen (hojas, "r")) == NULL)
+	{
+			printf ("No he podido abrir el fichero %s\n", hojas);
+			return 0;
+	}		
+	else
+	{
+
+
+		while (fgets (linea, 255, fp_hojas) != NULL)
+		
+			switch (linea[0])
+			{
+				case 'H':
+				
+					fgets (linea, 255, fp_hojas);
+					sscanf(linea, "f %lu %lu %lu", &v1, &v2, &v3);
+
+
+					Hojas[h].Vert_Hoja[0]=(v1-1);
+					Hojas[h].Vert_Hoja[1]=(v2-1);
+					Hojas[h].Vert_Hoja[2]=(v3-1);
+					Hojas[h].visible = 0;
+
+					
+					fgets (linea, 255, fp_hojas);
+					sscanf(linea, "f %lu %lu %lu", &v1, &v2, &v3);
+					Hojas[h].Vert_Hoja[3]=(v3-1);
+
+					GetNormalH ( Hojas[h]);
+
+					h++;
+					break;
+					
+				default :
+					printf( "Hay un error al leer las hojas\n");
+					break;
+	
+			}
+		
+	}
+
+	return (h);	
+}
+
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Procesar línea para extraer los triangulos del tronco de TRONCO.OBJ
+//--------------------------------------------------------------------------------------------------------------------------------
+/*
+  int Arbol::LeoTronco (char* tronco)
+{
+	FILE* fp_tronco;
+	char linea[256];
+    int v1, v2, v3, t=0;
+	
+
+
+	if ((fp_tronco = fopen (tronco, "r")) == NULL)
+			printf ("No he podido abrir el fichero %s\n", tronco);
+		
+	else
+	{
+
+		while (fgets (linea, 255, fp_tronco) != NULL)
+		
+		{
+			sscanf(linea, "f %lu %lu %lu", &v1, &v2, &v3);
+
+			Troncos[t].Vert_Tronco[0]=(v1-1);
+			Troncos[t].Vert_Tronco[1]=(v2-1);
+			Troncos[t].Vert_Tronco[2]=(v3-1);
+
+			GetNormalT (Troncos[t]);
+			t++;
+		
+		}
+		
+			fclose(fp_tronco);
+	}
+	return (t);
+}
+*/
+//---------------------------------------------------------------------------------------------------------------------
+// Procesar línea para extraer las HOJAS DE SIMPLIFICA.OBJ
+//---------------------------------------------------------------------------------------------------------------------
+
+  int Arbol::LeoHojasSimpl (const char* simplifica)
+{
+	FILE* fp_simpli;
+	char linea[256], str[10];;
+	int v0, v1, v2, v3, tn, tv1,tv2, e=0;
+	float xc,yc, zc;
+	float xmax, xmin, ymax, ymin, zmax, zmin;
+
+
+	if ((fp_simpli = fopen (simplifica, "r")) == NULL)
+	{
+			printf ("No he podido abrir el fichero %s\n", simplifica);
+			return 0;
+	}
+		
+	else
+	{
+
+		while (fgets (linea, 255, fp_simpli) != NULL)
+		{
+			switch (linea[0])
+			{
+
+			case 'C' :
+				sscanf(linea, "%s %f %f %f ", &str, &xc, &yc, &zc );
+				cx = xc;
+				cy = zc;
+				cz = yc;
+			
+				break;
+
+			//para almacenar la caja envolvente también cambio las componentes y y z
+			case 'x' :
+				sscanf(linea, "%s %f %f", &str, &xmax, &xmin );
+				break;
+
+			case 'y' :
+				sscanf(linea, "%s %f %f", &str, &zmax, &zmin );
+				break;
+
+			case 'z' :
+				sscanf(linea, "%s %f %f", &str, &ymax, &ymin );
+				rad = (float)(sqrt ((xmax-cx)*(xmax-cx)+ (ymax-cy)*(ymax-cy)+ (zmax-cz)*(zmax-cz)))-3;
+
+				break;
+
+
+
+			case 'N':
+			
+				//N 446 Ver 10176 10178 10169 10171  Tv 156 154 E 2
+	
+				sscanf(linea, "%s %lu %s %lu %lu  %lu %lu %s %lu %lu %s %i", 
+					&str, &tn, &str, &v0, &v1, &v2, &v3, &str, &tv1, &tv2, &str, &e );
+				Hojas[tn].Vert_Hoja[0] = v0;
+				Hojas[tn].Vert_Hoja[1] = v1;
+				Hojas[tn].Vert_Hoja[2] = v2;
+				Hojas[tn].Vert_Hoja[3] = v3;
+
+				Hojas[tn].visible = 0;
+
+				GetNormalH  (Hojas[tn]);
+	
+				Hojas[tn].hijoi= tv1;
+				Hojas[tn].hijod= tv2;
+
+				Hojas[tv1].padre = tn;
+				Hojas[tv2].padre = tn;
+
+				break;
+
+			default:
+				break;
+
+			}
+		}
+
+	}
+
+		
+	return (tn);
+}
+
+ 
+//--------------------------------------------------------------------------------------------------------------------------------
+// relleno la lista de las hojas con el menor detalle para hacer el culling
+// cada hoja ahora tiene un índice a la hoja raíz de su árbol
+//--------------------------------------------------------------------------------------------------------------------------------
+
+void Arbol::RellenoRaiz (void)
+{
+	int i,j, k, t, cont;
+	bool esta, fin;
+
+	i=0;
+	k=-1;
+	cont =-1;
+
+	MinDet  = new Activas[nHojas*2];
+	
+	while (i<TotHojas)
+	{
+		j=i;
+		while (Hojas[j].padre != -1) j= Hojas[j].padre;
+		Hojas[i].raiz = j;
+
+
+		// para la estructura MinDet
+		if ( k == -1){
+			k++;
+			MinDet[k].indice = j;
+			cont =k;
+		}
+		else
+		{
+			t = 0;
+			esta = false;
+			fin = false;
+
+			while (( fin == false) && (esta == false))
+			{	if ( MinDet[t].indice == j) esta = true;
+					else t++;
+				if (MinDet[t].indice == -1) fin = true;
+			}
+
+			if ( esta == false) //añado al final
+			{
+				cont++;
+				MinDet[cont].indice = j;
+			}
+		}
+
+	i++;
+	}	
+
+	minHojas = cont;
+
+}
+
+void Arbol::CalculaTexCoordsYNorms(void)
+{	
+	vertexdata->Begin();
+	for (unsigned int i=0; i<nHojas; i++)
+	{	
+		const float* lanormal = Hojas[i].Normal;
+		vertexdata->SetVertexNormal(Hojas[i].Vert_Hoja[0], lanormal[0], lanormal[1], lanormal[2]);
+		vertexdata->SetVertexTexCoord(Hojas[i].Vert_Hoja[0], 0.0f, 1.0f);
+
+		vertexdata->SetVertexNormal(Hojas[i].Vert_Hoja[1], lanormal[0], lanormal[1], lanormal[2]);
+		vertexdata->SetVertexTexCoord(Hojas[i].Vert_Hoja[1], 0.0f, 0.0f);
+
+		vertexdata->SetVertexNormal(Hojas[i].Vert_Hoja[2], lanormal[0], lanormal[1], lanormal[2]);
+		vertexdata->SetVertexTexCoord(Hojas[i].Vert_Hoja[2], 1.0f, 1.0f);
+
+		vertexdata->SetVertexNormal(Hojas[i].Vert_Hoja[3], lanormal[0], lanormal[1], lanormal[2]);
+		vertexdata->SetVertexTexCoord(Hojas[i].Vert_Hoja[3], 1.0f, 0.0f);
+
+
+/*		MiArbol->Vertices[aHoja.Vert_Hoja[1]].GetCoordinates (a,b,c);
+		glTexCoord2f ( 0.0, 1.0);
+		glVertex3f (a,b,c);
+	
+		MiArbol->Vertices[aHoja.Vert_Hoja[2]].GetCoordinates (a,b,c);
+		glTexCoord2f ( 1.0, 0.0);
+		glVertex3f (a,b,c);
+
+		MiArbol->Vertices[aHoja.Vert_Hoja[3]].GetCoordinates (a,b,c);
+		glTexCoord2f ( 1.0, 1.0);
+		glVertex3f (a,b,c);*/
+	}
+	vertexdata->End();
+}
+
+Arbol::Arbol(Arbol *ar)
+{
+	nHojas=ar->nHojas;
+	MinDet  = new Activas[nHojas*2];
+//	for (unsigned int i=0; i<nHojas*2; i++)
+//		MinDet[i]=ar->MinDet[i];
+	memcpy(MinDet,ar->MinDet,sizeof(Activas)*nHojas*2);
+	TotHojas=ar->TotHojas;
+	cx=ar->cx;
+	cy=ar->cy;
+	cz=ar->cz;
+	rad=ar->rad;
+	minHojas=ar->minHojas;
+	TotVerts=ar->TotVerts;
+
+	create_vertex_data_func=ar->create_vertex_data_func;
+	create_index_data_func=ar->create_index_data_func;
+	vertexdata=create_vertex_data_func(ar->vertexdata->GetNumVertices());
+	vertexdata->Begin(); 
+	for (unsigned int i=0; i<vertexdata->GetNumVertices(); i++) 
+	{
+		float va,vb,vc;
+		ar->vertexdata->GetVertexCoord(i,va,vb,vc);
+		vertexdata->SetVertexCoord(i,va,vb,vc);
+		ar->vertexdata->GetVertexNormal(i,va,vb,vc);
+		vertexdata->SetVertexNormal(i,va,vb,vc);
+	}
+	vertexdata->End();
+	indexdata=create_index_data_func(ar->indexdata->GetNumMaxIndices());
+	indexdata->Begin(); 
+	for (unsigned int i=0; i<indexdata->GetNumMaxIndices(); i++) 
+		indexdata->SetIndex(i,ar->indexdata->GetIndex(i));
+	indexdata->End();
+
+	Hojas=new Hoja[vertexdata->GetNumVertices()];
+//	for (unsigned int i=0; i<vertexdata->GetNumVertices(); i++) 
+//		Hojas[i]=ar->Hojas[i];
+	memcpy(Hojas,ar->Hojas,sizeof(Hoja)*vertexdata->GetNumVertices());
+
+	// esto no sé si devería haber akí
+	indexdata->SetNumValidIndices(0);
+}
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/activas.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/activas.h	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/activas.h	(revision 830)
@@ -0,0 +1,19 @@
+#ifndef ACTIVAS
+#define ACTIVAS
+
+
+class Activas
+{
+	public :
+		// Variable members
+    	int  indice;// Array of pointers to vertices
+		int  prev;
+		int  next;
+		
+	public :
+		// Constructors
+		Activas (void); // Void constructor
+		virtual ~Activas (void); // Destructor
+};
+
+#endif
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Point3D.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Point3D.cpp	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Point3D.cpp	(revision 830)
@@ -0,0 +1,161 @@
+#include <math.h> // Necesaria para el cálculo de raices cuadradas.
+#include "Point3D.h"
+
+
+//---------------------------------------------------------------------------------------------------
+// Constructor de copia sin parámetros
+//---------------------------------------------------------------------------------------------------
+Point3D::Point3D (void)
+{
+	coords[0] = coords[1] = coords[2] = 0.0f;
+}
+
+
+//---------------------------------------------------------------------------------------------------
+// Constructor con tres parámetros
+// Parámetros --> x, y, z son las coordenadas del punto en 3D
+//---------------------------------------------------------------------------------------------------
+Point3D::Point3D (float x, float y, float z)
+{
+	coords[0] = x;
+	coords[1] = y;
+	coords[2] = z;
+}
+
+
+//---------------------------------------------------------------------------------------------------
+// Constructor de copia
+// Parámetros --> p es el punto con el se hace la copia
+//---------------------------------------------------------------------------------------------------
+Point3D::Point3D (const Point3D & p)
+{
+	coords[0] = p.coords[0];
+	coords[1] = p.coords[1];
+	coords[2] = p.coords[2];
+}
+
+
+//---------------------------------------------------------------------------------------------------
+// Operador de asignación
+// Parámetros --> p es el punto con los datos a copiar
+// Salida --> Se devuelve una referencia al punto al que se acaban de copiar los datos
+//---------------------------------------------------------------------------------------------------
+Point3D & Point3D::operator = (const Point3D & p)
+{
+	coords[0] = p.coords[0];
+	coords[1] = p.coords[1];
+	coords[2] = p.coords[2];
+
+	return *this;
+}
+
+
+//---------------------------------------------------------------------------------------------------
+// Operador de comparación
+// Parámetros const Point3D& p : Punto con el que se está comparando
+// Salida --> 'true' si los puntos son iguales
+//			  'false' en caso contrario
+//---------------------------------------------------------------------------------------------------
+bool Point3D::operator == (const Point3D & p) const
+{
+	if (coords[0] == p.coords[0] &&
+		coords[1] == p.coords[1] &&
+		coords[2] == p.coords[2])
+		return true;
+
+	return false;
+}
+
+
+//---------------------------------------------------------------------------------------------------
+// Operador diferencia
+// Parámetros --> p es el punto con el que se compara el actual
+// Salida si son distintos 'true' en caso contrario 'false'
+//---------------------------------------------------------------------------------------------------
+bool Point3D::operator != (const Point3D & p) const
+{
+	return (coords[0] != p.coords[0] ||
+			coords[1] != p.coords[1] ||
+			coords[2] != p.coords[2]);
+}
+
+
+//---------------------------------------------------------------------------------------------------
+// Para actualizar las componentes del punto
+// Parámetros --> const float a, const float b, const float c : las nuevas coordenadas del punto
+//---------------------------------------------------------------------------------------------------
+bool Point3D::Update (const float a, const float b, const float c)
+{
+	coords[0] = a;
+	coords[1] = b;
+	coords[2] = c;
+
+	return true;
+}
+
+
+
+bool Point3D::Update (const Point3D& unPunto)
+{
+	*this = unPunto;
+
+	return true;
+}
+
+
+//---------------------------------------------------------------------------------------------------
+// Returns the point coordinates 
+// Parameters --> float& a, float& b, float& c : References that recieve the coordinates
+// Return --> None
+//---------------------------------------------------------------------------------------------------
+void Point3D::GetCoordinates (float& a, float& b, float& c) const
+{
+	a = coords[0];
+	b = coords[1];
+	c = coords[2];
+}
+
+//---------------------------------------------------------------------------------------------------
+// Actualiza las coordenadas
+// Parameters --> float a, float b, float c : Lo que se van a incrementar
+//							las coordenadas del punto
+// Return --> None
+//---------------------------------------------------------------------------------------------------
+void Point3D::Actualiza (float a, float b, float c) 
+{
+	coords[0] = coords[0] + a;
+	coords[1] = coords[1] + b;
+	coords[2] = coords[2] + c;
+}
+
+
+
+//---------------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------------
+const float * const Point3D::GetCoordinates (void) const
+{
+	return coords;
+}
+
+
+//---------------------------------------------------------------------------------------------------
+// Calcula la distancia euclidea entre dos puntos
+// Parámetros --> p es el punto hasta el que se calcula la distancia desde este
+// Salida la distancia entre los puntos como un float
+//---------------------------------------------------------------------------------------------------
+float Point3D::Distance (const Point3D & p) const
+{
+	return ((float)sqrt ((coords[0]-p.coords[0])*(coords[0]-p.coords[0])+
+						 (coords[1]-p.coords[1])*(coords[1]-p.coords[1])+
+						 (coords[2]-p.coords[2])*(coords[2]-p.coords[2])));
+}
+
+
+//---------------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------------
+std::ostream& operator << (std::ostream& os, Point3D & p)
+{
+	os << '(' << p.coords[0] << ',' << p.coords[1] << ',' << p.coords[2] << ")\n";
+
+	return os;
+}
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Hoja.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Hoja.cpp	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Hoja.cpp	(revision 830)
@@ -0,0 +1,55 @@
+#include <GL\glut.h>
+#include "Hoja.h"
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Void constructor
+// Parameters --> None
+//--------------------------------------------------------------------------------------------------------------------------------
+Hoja::Hoja(void) 
+{
+	
+	Vert_Hoja[0] = Vert_Hoja[1] = Vert_Hoja[2] = Vert_Hoja[3] = 0;
+	Normal[0] = Normal[1] = Normal[2] = 0;
+	padre=-1;
+	Cuantas_hojas = 1;
+	hijoi = hijod = -1;
+	raiz= visible= -1;
+//	prev = next = -1;
+	
+		
+}
+
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Copy constructor
+// Parameters --> const Hoja& aHoja : The Hoja to copy
+//--------------------------------------------------------------------------------------------------------------------------------
+Hoja::Hoja (const Hoja& aHoja)
+{
+
+
+	Cuantas_hojas = aHoja.Cuantas_hojas;;
+	padre = aHoja.padre;
+	hijoi = aHoja.hijoi;
+	hijod = aHoja.hijod;
+	visible = aHoja.visible;
+	raiz = aHoja.raiz;
+	
+	for (int i = 0L; i < 4; i++)
+		Vert_Hoja[i] = aHoja.Vert_Hoja[i]; 
+	for ( i = 0L; i < 3; i++)
+		Normal[i] = aHoja.Normal[i]; 
+	
+
+}
+
+
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Destructor. We must deallocate the memory allocated for pointers to Vert_Hoja and edges
+//--------------------------------------------------------------------------------------------------------------------------------
+Hoja::~Hoja (void)
+{
+}
+
+
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/arbol.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/arbol.h	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/arbol.h	(revision 830)
@@ -0,0 +1,62 @@
+#ifndef ARBOL_H
+#define ARBOL_H 
+
+
+#include "Hoja.h"
+#include "vertexdata.h"
+#include "Point3D.h"
+#include "Activas.h"
+
+
+
+class Arbol
+{
+	private:
+		Geometry::CREATEVERTEXDATAFUNC create_vertex_data_func;		
+		Geometry::CREATEINDEXDATAFUNC create_index_data_func;
+
+	public :
+	// Variable members
+		
+		Geometry::VertexData *vertexdata;
+		Geometry::IndexData *indexdata;
+
+		Hoja   *Hojas;
+		Activas  *MinDet; // primera hoja activa
+		int nHojas;
+		int TotHojas;
+		
+		float cx,cy,cz; //centro de la copa// para los impostores y resolucion variable
+		float rad; //radio de la esfera envolvente
+		int minHojas;
+
+//		float *normales_vert;
+//		float *normales_vert2;
+//		float *tex_coords;
+		int TotVerts;
+
+	public :
+		Arbol (const char *, const char *, const char*, Geometry::CREATEVERTEXDATAFUNC vdfun=NULL, Geometry::CREATEINDEXDATAFUNC idfun=NULL); // Constructor with the name of a file cotaining the data
+		Arbol (Arbol *a);
+		virtual ~Arbol (void); // Destructor
+		
+		// Montan la estructura
+		void ReadFromFile (const char *, const char*, const char*/*, char**/); // Reads a obj-model from a file
+		int LeeVertices ( const char * );
+		int LeoHojas( const char *);
+//		int LeoTronco( char *);
+		int LeoHojasSimpl( const char*);
+		void RellenoRaiz (void);
+
+		void GetNormalH (Hoja&);
+//		void GetNormalT(Tronco&);
+
+		void CrossProduct(const float *v1, const float *v2, float *res);
+		void Normalize(const float *v, float *res);
+//		void CalculaNormalesVertice(void);
+		void CalculaTexCoordsYNorms(void);
+        
+		
+};
+
+#endif
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Point3D.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Point3D.h	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Point3D.h	(revision 830)
@@ -0,0 +1,36 @@
+#ifndef POINT3D_H
+#define POINT3D_H
+
+
+
+#include <iostream>
+
+
+
+class Point3D
+{
+	protected:
+		float coords[3]; // Las tres coordenadas de un punto en 3D
+
+	public:
+		Point3D (void); // Constructor sin parámetros
+		Point3D (float, float, float); // Constructor con parámetros
+		Point3D (const Point3D&); // Constructor de copia
+		Point3D & operator = (const Point3D &); // Operador de asignación
+		bool operator == (const Point3D &) const; // Operador de comparación
+		bool operator != (const Point3D &) const; // Operador distinto de
+		bool Update (const float, const float, const float); // Actualiza las coordenadas del punto
+		bool Update (const Point3D&); // Actualiza con los datos de otro punto
+		void GetCoordinates (float&, float&, float&) const;
+		void Actualiza (float, float, float);
+		const float * const GetCoordinates (void) const;
+		float Distance (const Point3D &) const; // Distancia entre dos puntos
+		// A partir de aqui las funciones son relevantes solo para depuración de código
+		friend std::ostream& operator << (std::ostream& os, Point3D&); // Para salida por consola
+
+};
+
+//#define Vertex Point3D
+
+
+#endif
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/tlista.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/tlista.h	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/tlista.h	(revision 830)
@@ -0,0 +1,709 @@
+#ifndef TLISTA_H
+#define TLISTA_H
+
+
+
+#include <iostream>
+
+
+
+template<class T>
+struct dato_enlazado
+{
+	T dato; // El dato como tipo abstracto
+	float prioridad; // Por si queremos ordenar la lista con prioridad
+	dato_enlazado * sig; // Puntero al siguient
+	dato_enlazado (void); // Constructor por defecto
+	dato_enlazado (const T& a); // Constructor de copia
+	dato_enlazado (const T& a, const float); // Constructor de copia
+	dato_enlazado& operator =(const dato_enlazado& d); // Operador de asignación
+	bool operator ==(const dato_enlazado& d) const; // Operador de igualdad
+	bool operator !=(const dato_enlazado& d) const; // Operador de desigualdad
+	//friend ostream& operator << (ostream& os, T& d);
+};
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// NO LA BORRO PORQUE ES INTERESANTE
+//------------------------------------------------------------------------------------------------------------------------------
+/*template<class T>
+ostream& operator << (ostream& os, T& d)
+{
+	os << d.dato;
+
+	return os;
+}*/
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Constructor por defecto, inicializa el siguiente a nulo
+// Parámetros : ninguno
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+dato_enlazado<T>::dato_enlazado (void) : sig(NULL), prioridad(0.0f)
+{
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Constructor de copia
+// Parámetros : T& a --> Referencia constante al dato a copiar
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+dato_enlazado<T>::dato_enlazado (const T& a) : dato(a), sig(NULL)
+{
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Constructor con dato de prioridad
+// Parámetros : T& a --> Referencia constante al dato a copiar
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+dato_enlazado<T>::dato_enlazado (const T& a, const float prior) : dato(a), sig(NULL), prioridad(prior)
+{
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Operador de asignación
+// Parámetros : const dato_enlazado& d --> Referencia constante al dato que se va a copiar
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+dato_enlazado<T>& dato_enlazado<T>::operator =(const dato_enlazado& d)
+{
+	dato = d.dato;
+	sig = NULL;
+	return *this;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Operador de igualdad, devuelve true si los datos son iguales y false en caso contrario
+// Parámetros : const dato_enlazado& d
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool dato_enlazado<T>::operator ==(const dato_enlazado<T>& d) const
+{
+	return dato == d.dato;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Operador de desigualdad, devuelve true si los datos son distintos y false si son iguales
+// Parámetros : const dato_enlazado
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool dato_enlazado<T>::operator !=(const dato_enlazado<T>& d) const
+{
+	return dato != d.dato;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T> class iterador_lista;
+template<class T> class iterador_prioridad;
+//------------------------------------------------------------------------------------------------------------------------------
+
+template<class T>
+class lista
+{
+	protected :
+		float Prioridad (const unsigned long); // Devuelve la prioridad del elemento seleccionado
+	public :
+	dato_enlazado<T> *cab;
+	//dato_enlazado<T> *cola;
+	dato_enlazado<T> *selec; // Puntero al dato actualmente 'encontrado', 
+							 // aumenta la eficiencia en la busqueda de datos consecutivos
+	dato_enlazado<T> *cola; // Esto es temporal, hay que borrarlo
+	
+public:
+	lista (void); // Constructor vacio
+	virtual ~lista (void); // Destructor
+	lista (lista<T>&); // Constructor de copia
+	bool operator == (lista<T>&) const; // Operador de comparación
+	bool operator != (lista<T>&) const; // Idem
+	virtual bool Inserta (const T& a); // Inserta un dato en la lista
+	virtual bool InsertaPrioridad (const T&, const float, const bool); // Inserta manteniendo orden
+	virtual bool Busca (const T& a);
+	virtual bool Borra (const T& a);   // Borra a si existe
+	virtual bool BorraLista (void);   // Borra todos los elementos de la lista
+	virtual bool Cab (void); // Situa el seleccionado al principio de la lista
+	virtual bool Sig (void);
+	virtual T GetCab (void); // Extrae la cabeza de la lista
+	virtual T GetCola (void);
+	virtual bool BorraCola (void); //borra la cola
+	virtual unsigned long NDatos (void) const; // Devuelve el número de datos en la lista
+	virtual unsigned long NPrioridadDatos (void) const; //
+	friend class iterador_lista<T>;
+	friend class iterador_prioridad<T>;
+	// A partir de aqui las funciones son sólo para depurar el código
+	friend std::ostream& operator << (std::ostream& os, lista<T>& d);
+};
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// PARA DEPURAR EL CÓDIGO, PERO ES INTERESANTE
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+std::ostream& operator << (std::ostream& os, lista<T>& l)
+{
+	dato_enlazado<T> * tmp = l.cab;
+
+	while (tmp)
+	{
+		cout << (*tmp).dato;
+		tmp = tmp->sig;
+	}
+
+	return os;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Constructor por defecto
+// Parámetros : Ninguno
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+lista<T>::lista (void) : cab(NULL), selec(NULL), cola(NULL)
+{
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Constructor de copia
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+lista<T>::lista (lista<T>& l) : cab(NULL), selec(NULL), cola(NULL)
+{
+	dato_enlazado<T> *tmp = l.cab;
+	dato_enlazado<T> *nuevo; // Apuntador a la memoria que se va a reservar
+
+	while (tmp != NULL)
+	{
+		nuevo = new dato_enlazado<T> (*tmp); // Reservo espacio para el nuevo dato
+		if (cola == NULL) cola = nuevo;
+		nuevo->sig = cab; // El siguiente del nuevo dato será la cabeza de la lista	
+		selec = cab = nuevo; // Ahora hago apuntar la cabeza al nuevo dato
+
+		tmp = tmp->sig;
+	}
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Destructor por defecto
+// Parámetros : Ninguno
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+lista<T>::~lista (void)
+{
+	//BorraLista ();
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Operador de comparación. Dos listas son iguales si contienen los mismos elementos aunque no estén en el mismo orden
+// Parámetros --> const lista<T>& l : Lista con la que se compara
+// Salida --> 'true' si las dos listas contienen los mismos elementos
+//			  'false' en cualquier otro caso
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool lista<T>::operator == (lista<T>& l) const
+{
+	if (NDatos () != l.NDatos ()) return false; // Si no tienen el mismo número de datos no pueden ser iguales
+
+	//lista<T> tmp = *this;
+	lista<T> tmpl = l;
+	//iterador_lista<T> iterador (tmp); // Creo un iterador sobre esta lista
+	//T* dato;
+
+	//while (dato = iterador ())
+		//if (!tmpl.Busca(*dato)) return false; // Si uno de los datos de la primera lista no lo encuentro en la segunda no son iguales
+
+	dato_enlazado<T> *tmpd = cab;
+
+	while (tmpd != NULL)
+	{
+		if (tmpl.Busca (tmpd->dato) == false) return false;
+		tmpd = tmpd->sig;
+	}
+
+	return true; // si todos los de la primera están en la segunda y tienen el mismo tamaño es que son iguales
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Operador de desigualdad
+// Parámetros --> const lista<T>& l : Lista con la que se compara
+// Salida --> 'true' si las listas son distintas
+//			  'false' en caso contrario
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool lista<T>::operator != (lista<T>& l) const
+{
+	if (*this == l) return false;
+
+	return true;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Devuelve la prioridad en la posición i-ésima
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+float lista<T>::Prioridad (const unsigned long i)
+{
+	unsigned long cont = 0L; // Inicializo el contador de posiciones
+
+	selec = cab; //Inicio la búsqueda desde la cabeza
+	while (i != cont && selec != NULL) // Mientras no haya encontrado la posición y me queden elementos
+	{
+		selec = selec->sig; // Paso al siguiente
+		cont++; // e incremento en uno el contador
+	}
+
+	return selec->prioridad;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Inserta un nuevo elemento en la lista. El nuevo elemento se inserta en la cabeza
+// Parámetros : a --> el dato que hay que añadir a la lista
+// Salida : 'true' si el dato se ha podido insertar en la lista
+//			'false' en caso contrario
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool lista<T>::Inserta (const T& a)
+{
+	
+	if (cola == NULL)
+	{
+		selec = cab = cola = new dato_enlazado<T> (a);
+		return true;
+	}
+	else
+	{
+		if (!(cola->sig = new dato_enlazado<T> (a))) // Reservo espacio para el nuevo dato
+			return false;
+		else
+		{
+			cola = cola->sig;
+			selec = cola; // Ahora hago apuntar la cabeza al nuevo dato
+			return true;
+		}
+	}
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Inserta manteniendo orden
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool lista<T>::InsertaPrioridad (const T& a, const float prior, const bool borra)
+{
+	dato_enlazado<T>* tmp = cola;
+
+	selec = new dato_enlazado<T> (a, prior); // Creo el nodo a insertar
+
+	if (cab == NULL) // No hay ningún dato en la lista
+	{
+		cab = cola = selec;
+		return true;
+	}
+	// Tengo mas de uno en la lista y el que voy a insertar es el menor
+	if (cola->prioridad >= prior)
+	{
+		if (cola->dato != a)
+		{
+			selec->sig = cola;
+			cola = selec;
+		}
+		else if (cola->dato == a && borra)
+		{
+			dato_enlazado<T>* tmp_selec = cola;
+			cola = cola->sig;
+			delete tmp_selec;
+		}
+		else delete selec;
+		return true;
+	}
+	else
+	{
+		while (tmp != cab) // Mientras no llegue a la cabeza
+		{
+			if (tmp->sig->prioridad >= prior) // inserto antes de tmp->sig
+			{
+				if (a != tmp->sig->dato) // Si no está ya presente en la lista
+				{
+					selec->sig = tmp->sig; // lo inserto
+					tmp->sig = selec;
+				}
+				else if (a == tmp->sig->dato && borra) // Si hay que borrarlo
+				{
+					dato_enlazado<T>* tmp_selec = tmp->sig;
+					if (tmp->sig == cab) cab = tmp;
+					tmp->sig = tmp->sig->sig;
+					delete tmp_selec;
+				}
+				else // si está presente
+				{
+					delete selec; // Libero la memoria que había reservado
+				}
+				return true;
+			}
+			tmp = tmp->sig;
+		}
+		if ((tmp == cab) && (a != cab->dato)) // Si llego a la cabeza sin encontrar ninguno en la lista con prioridad mayor
+		{				// es porque el que voy a insertar tiene la mayor prioridad
+			cab->sig = selec;
+			cab = selec;
+			return true;
+		}
+		else
+		{
+			delete selec;
+			selec = cab;
+		}
+	}
+	return false;
+}
+
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Busca un elemento en la lista y deja el puntero selec apuntando a él si lo encuentra
+// Parámetros : const T& a --> Referencia al dato que se está buscando
+// Salida : true si el dato efectivamente es encontrado
+//			false si el dato no está en la lista
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool lista<T>::Busca (const T& a)
+{
+	dato_enlazado<T> *tmp; // Puntero de reserva
+
+	if (!cab) return false; // Si no hay ningún dato no hay donde buscar
+
+	if (selec && selec->dato != a)
+	{
+		tmp = selec; // Me guardo el actualmente seleccionado
+		selec = selec->sig; // Iniciaré la búsqueda a partir del dato siguiente
+	}
+	else
+	{
+		selec = cab; // Iniciaré la busqueda desde la cabeza si no
+		//tmp = NULL;
+	}
+
+	while (selec != NULL && selec->dato != a)
+		selec = selec->sig; // lo busco a partir de la posición original hacia el final
+
+	if (!selec) // Si antes habia uno seleccionado
+	{
+		selec = cab; // Iniciaré la búsqueda desde la cabeza
+		while (selec != tmp && selec->dato != a) selec = selec->sig;
+	}
+	
+	if (selec && selec->dato == a) return true;
+	return false;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Borra el elemento indicado de la lista
+// Parámetros : const T& a --> Referencia al elemento a borrar
+// Salida --> true si el elemento ha sido encontrado y borrado
+//			  false si no se ha encontrado el elemento
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool lista<T>::Borra (const T& a)
+{
+	dato_enlazado<T> *tmp = cab; // Me guardo la posición de lo que quiero borrar
+
+	if (!Busca (a)) return false; // Si no lo encuentra devuelve false
+
+	if (selec == cab) // Si lo que quiero borrar es la cabeza
+	{
+		cab = cab->sig; // Adelanto la cabeza
+		delete selec; // Borro el dato
+		selec = cab; // Hago apuntar el actual a la nueva cabeza
+	}
+	else
+	{
+		while (tmp->sig->dato != a) tmp = tmp->sig; // Encuentro el anterior al que quiero borrar
+		if (tmp->sig == cola) cola = tmp;
+
+		tmp->sig = selec->sig; // Saco el que voy a borrar fuera de la lista
+		delete selec; // Borro el dato
+		if (!(selec = tmp->sig)) selec = cab; // Si al avanzar el seleccionado llego al final, inicio desde la cabeza
+	}
+
+	return true;
+}
+
+
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Elimina todos los elementos de lista
+// Parámetros : ninguno
+// Salida : Si la lista ha sido efectivamente borrada true
+//			false en caso contrario
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool lista<T>::BorraLista (void)
+{
+	while (cab)
+	{
+		selec = cab;
+		if (!Borra (selec->dato)) return false; // Borro siempre la cabeza
+	}
+	return true;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Coloca el seleccionado al inicio de la lista
+// Parémetros --> ninguno
+// Salida --> 'true' si efectivamente se ha colocado al inicio de la lista
+//			  'false' si ha habido algún error y el seleccionado no apunta al inicio de la lista
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool lista<T>::Cab (void)
+{
+	if (cab)
+	{
+		selec = cab;
+		return true;
+	}
+	return false;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Avanza el seleccionado hasta la siguiente posición, el siguiente del último es de nuevo la cabeza
+// Parámetros : ninguno
+// Salida : 'true' si se inicia desde la cabeza al avanzar
+//			'false' en cualquier otro caso
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool lista<T>::Sig (void)
+{
+	if (!(selec = selec->sig))
+	{
+		selec = cab; // Avanzo el seleccionado hasta el siguiente, y si me paso, lo llevo
+		return true; // de nuevo a la cabeza
+	}
+	return false;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Extrae la cabeza de la lista
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+T lista<T>::GetCab (void)
+{
+	if (cab->dato == NULL) return NULL; // Si no hay nada en la lista devuelve NULL
+	
+		else	return cab->dato;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Extrae la cola de la lista  ///ACABAAAR melon
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+T lista<T>::GetCola (void)
+{
+	
+	if (cola->dato == NULL) return NULL; // Si no hay nada en la lista devuelve NULL
+	
+		else	return cola->dato;
+	
+}
+//------------------------------------------------------------------------------------------------------------------------------
+// Extrae y borra la cola de la lista
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+bool lista<T>::BorraCola (void)
+{
+	/*dato_enlazado<T>* tmp = cab; // Nos situamos incialmente en la cabeza
+
+
+	if (cab == NULL) return false; // Si no hay nada en la lista devuelve NULL
+	if (cab == cola) // Si solo tenemos un elemento
+	{
+		delete cab;
+		cab = cola = selec = NULL;
+		return true;
+	}
+	else
+	{
+		while (tmp->sig != cola)
+			tmp = tmp->sig;
+		delete cola;
+		cola = tmp;
+		cola->sig = NULL;
+		selec = cab;
+		return true;
+	}*/
+	return Borra (cola->dato);
+}
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Devuelve el número de datos actuales en la lista
+// Parámetros --> Ninguno
+// Salida --> int : el número de datos en la lista
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+unsigned long lista<T>::NDatos (void) const
+{
+	unsigned long nDatos = 0; // Para contar el número de datos de la lista
+	/*lista<T> tmp = *this;
+	/iterador_lista<T>  iterador(tmp); // Creo un iterador sobre la lista
+	T * dato;
+
+	while (dato = iterador ())
+		nDatos++;*/
+
+	dato_enlazado<T> * tmp = cab;
+
+	while (tmp != NULL)
+	{
+		tmp = tmp->sig;
+		nDatos++;
+	}
+
+	return nDatos;
+}
+
+
+template<class T>
+unsigned long lista<T>::NPrioridadDatos (void) const
+{
+	unsigned nDatos = 0;
+
+	dato_enlazado<T>* tmp = cola;
+
+	while (tmp != NULL)
+	{
+		tmp = tmp->sig;
+		nDatos++;
+	}
+
+	return nDatos;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Esta es la clase iterador, recorre la lista desde la cabeza a la cola devolviendo punteros a los datos
+//------------------------------------------------------------------------------------------------------------------------------
+
+template<class T>
+class iterador_lista
+{
+	private:
+		dato_enlazado<T> *iterador; // Elemento de la lista a devolver
+		lista<T> *lista_iterada; // Puntero a la lista sobre la que se está iterando
+
+	public:
+		iterador_lista (lista<T>&); // Constructor con una lista
+		T * const operator () (void); // Operador de iteracion
+		T * const IteradorCircular (void); // Igual que el anterior, pero cuando llega al final, recomienza
+};
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Constructor con un lista
+// Parámetros --> lista<T>& l : Referencia a la lista sobre la que se iterará
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+iterador_lista<T>::iterador_lista (lista<T>& l) : lista_iterada (&l), iterador(l.cab)
+{
+	 // Hago que el primer elemento de iteración sea la cabeza
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Operador () que es el que hace las funciones de iterador
+// Párámetros --> Ninguno
+// Salida --> T * const : un puntero constante al elemento devuelto por el iterador
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+T * const iterador_lista<T>::operator () (void)
+{
+	T * tmp = &iterador->dato;
+
+	if (!iterador) iterador = lista_iterada->cab; // Si llegamos al final de la lista, dejamos el iterador 
+	else iterador = iterador->sig;					// al inicio de la lista.
+
+	return tmp;
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Igual que el anterior, pero cuando llega al final de la lista empieza desde el principio
+// Parametros --> Ninguno
+// Salida T * const : un puntero constante al elemento devuelto
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+T * const iterador_lista<T>::IteradorCircular (void)
+{
+	if (iterador == NULL) return NULL;
+	else
+	{
+		iterador = iterador->sig;
+		if (!iterador) iterador = lista_iterada->cab;
+
+		return &iterador->dato;
+	}
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+class iterador_prioridad
+{
+	private:
+		dato_enlazado<T> *iterador; // Elemento de la lista a devolver
+		lista<T> *lista_iterada; // Puntero a la lista sobre la que se está iterando
+
+	public:
+		iterador_prioridad (lista<T>&); // Constructor con una lista
+		T * const operator () (void); // Operador de iteracion
+};
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Constructor con un lista
+// Parámetros --> lista<T>& l : Referencia a la lista sobre la que se iterará
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+iterador_prioridad<T>::iterador_prioridad (lista<T>& l) : lista_iterada (&l), iterador(l.cola)
+{
+	 // Hago que el primer elemento de iteración sea la cabeza
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Operador () que es el que hace las funciones de iterador
+// Párámetros --> Ninguno
+// Salida --> T * const : un puntero constante al elemento devuelto por el iterador
+//------------------------------------------------------------------------------------------------------------------------------
+template<class T>
+T * const iterador_prioridad<T>::operator () (void)
+{
+	T * tmp = &iterador->dato;
+
+	if (!iterador) iterador = lista_iterada->cola; // Si llegamos al final de la lista, dejamos el iterador 
+	else iterador = iterador->sig;					// al inicio de la lista.
+
+	return tmp;
+}
+
+
+
+
+#endif
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/foliage.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/foliage.cpp	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/foliage.cpp	(revision 830)
@@ -0,0 +1,1033 @@
+//#include <GL\glut.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+//#include <vl\VLf.h>
+
+#include "Foliage.h"
+
+
+/******************************************   PANTALLA **************************************************/
+//--------------------------------------------------------------------------------------------------------------------------------
+// Void constructor
+// Parameters --> None
+//--------------------------------------------------------------------------------------------------------------------------------
+Foliage::Foliage(void):  MiArbol(NULL), Acth(NULL)
+{
+	 ppio= final = -1;
+}
+
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Constructor with the name of a file cotaining the data
+//--------------------------------------------------------------------------------------------------------------------------------
+Foliage::Foliage ( Arbol *Arbol1)
+{
+	int h=0;
+
+
+	MiArbol = Arbol1;
+
+	Acth  = new Activas[(MiArbol->nHojas)*8];
+
+	for ( h=0; h < MiArbol->nHojas; h++) {
+
+		Acth[h].indice = h;
+		if ( h != 0)
+		{
+			Acth[h].prev = (h-1);
+			Acth[h-1].next = h;
+		}
+
+	}
+				
+	ppio = 0;
+	final = (MiArbol->nHojas)-1;
+	nhactivas = MiArbol->nHojas;
+
+
+
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Destructor. We must deallocate the memory allocated for pointers to vertices and edges
+//--------------------------------------------------------------------------------------------------------------------------------
+Foliage::~Foliage (void)
+{
+	delete MiArbol;
+	delete Acth;
+}
+//
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Dibuja una hoja
+//--------------------------------------------------------------------------------------------------------------------------------
+				/*
+void Foliage::Dibuja_Hoja ( Hoja &aHoja)
+{
+	
+	float a,b,c;
+
+	glBegin (GL_TRIANGLE_STRIP);
+		glNormal3fv (aHoja.Normal);
+		MiArbol->Vertices[aHoja.Vert_Hoja[0]].GetCoordinates (a,b,c);
+		glTexCoord2f ( 0.0, 0.0);
+
+		glVertex3f (a,b,c);
+
+		MiArbol->Vertices[aHoja.Vert_Hoja[1]].GetCoordinates (a,b,c);
+		glTexCoord2f ( 0.0, 1.0);
+		glVertex3f (a,b,c);
+	
+		MiArbol->Vertices[aHoja.Vert_Hoja[2]].GetCoordinates (a,b,c);
+		glTexCoord2f ( 1.0, 0.0);
+		glVertex3f (a,b,c);
+
+		MiArbol->Vertices[aHoja.Vert_Hoja[3]].GetCoordinates (a,b,c);
+		glTexCoord2f ( 1.0, 1.0);
+		glVertex3f (a,b,c);
+
+	glEnd ();
+
+}
+
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Dibujar todas las hojas activas 
+//--------------------------------------------------------------------------------------------------------------------------------
+				
+int Foliage::DibujarHojas (float frustum[6][4], float zoom)
+{
+	int hojactiva, i;
+
+
+	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+
+	hojactiva = 0;
+	glBindTexture (GL_TEXTURE_2D,texName[0]);
+	glEnable(GL_ALPHA_TEST);
+
+	if ( zoom <75.0) 
+	//if ( false) 
+	{
+		//calculo el culling de las hojas de minimo detalle
+		Culling (frustum);
+		//printf ( "--------------------------->Entro en culling\n");
+
+		i= ppio; 
+		while ( i != -1)
+		{ 
+			if (MiArbol->Hojas[MiArbol->Hojas[i].raiz].visible == 1)
+			{
+				hojactiva ++;
+				Dibuja_Hoja (MiArbol->Hojas[i]);
+			}
+			i = Acth[i].next;
+		}
+	}
+	else
+	{
+		i= ppio; 
+    	while ( i != -1)
+		{ 
+			hojactiva ++;
+			Dibuja_Hoja (MiArbol->Hojas[i]);
+			i=Acth[i].next;
+		}
+
+	}
+
+
+
+	glDisable(GL_ALPHA_TEST);
+
+	return ( hojactiva);
+
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Dibujar media copa del arbol 
+// si el char c es 'f' dibuja la parte delantera
+// si es 'b' la parte trasera
+//--------------------------------------------------------------------------------------------------------------------------------
+				
+int Foliage::DibujaMediaCopa (  char c, float rva, float rvb,float rvc, float rvd, float radio)
+{
+	int hojactiva, i;
+//	int count, count2;
+
+	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+
+	hojactiva = 0;
+	glBindTexture (GL_TEXTURE_2D,texName[0]);
+	glEnable(GL_ALPHA_TEST);
+
+	i= ppio; 
+	if ( c == 'b')
+	{//count = 0;
+	while ( i != -1)
+	{  //count ++;
+			if ( Criterio (MiArbol->Hojas[i],'p', rva,rvb,rvc,rvd, radio) == false) //esta detras del plano
+		{
+			hojactiva ++;
+			Dibuja_Hoja (MiArbol->Hojas[i]);
+			}
+		i = Acth[i].next;
+
+	}
+//	printf ( " EN LA TRASERA chequeo %i hojas \n", count);
+	}
+	else
+	{// count2 = 0;
+
+		while ( i != -1)
+		{ //count2++;
+			if ( Criterio (MiArbol->Hojas[i],'p', rva,rvb,rvc,rvd, radio) == true) //esta detras del plano
+		{
+			hojactiva ++;
+			Dibuja_Hoja (MiArbol->Hojas[i]);
+			}
+		i = Acth[i].next;
+	}
+		//	printf ( " EN LA DELANTERA chequeo %i hojas \n", count2);
+
+	}
+	glDisable(GL_ALPHA_TEST);
+
+//	nhactivas = hojactiva;
+
+
+	return ( hojactiva);
+
+
+
+}
+
+
+
+//-------------------------------------------------------------------------------------------------------------------------
+// dibuja la esfera
+//-------------------------------------------------------------------------------------------------------------------------
+
+void Foliage::DibujaEsfera(float r)
+{
+
+	glPushMatrix();
+		glTranslated (0.0,MiArbol->cy, 0.0);
+		glColor3f(1.0, 0.0, 0.0);
+		glDisable(GL_LIGHTING);
+		glLineWidth(1.2);
+		glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+		glutSolidSphere ( r,20, 20);
+		glEnable(GL_LIGHTING);
+		glColor3f ( 1.0, 1.0, 1.0);
+	glPopMatrix();
+
+}
+
+/******************************************   CULLING **************************************************/
+//-------------------------------------------------------------------------------------------------------------------------
+// culling de las hojas de menor detalle
+//-------------------------------------------------------------------------------------------------------------------------
+
+void Foliage::Culling (float frustum[6][4])
+{
+	int i, j;
+
+	i = 0;
+	while ( MiArbol->MinDet[i].indice != -1)
+	{
+		j = MiArbol->MinDet[i].indice;
+		if (LeafinFrustum ( j, frustum) == true) {
+		//	printf("dentro %i y el padre es %i\n", j, MiArbol->Hojas[MiArbol->MinDet[i].indice].padre);
+			MiArbol->Hojas[j].visible = 1;
+		}
+		else  
+		{
+		//	printf("fuera %i\n", j);
+			MiArbol->Hojas[j].visible = 0;
+		}
+
+		i++;
+	}
+
+}
+
+
+//-------
+// si está en el frustrum --> true
+//	sino --> false
+//------------
+
+
+bool Foliage::LeafinFrustum ( int i, float frustum[6][4])
+{
+	float a,b,c, tmp,rad;
+	int j,p;
+	Vector v;
+
+	for (j =0; j<4; j++)
+	{
+//		MiArbol->Vertices[MiArbol->Hojas[i].Vert_Hoja[j]].GetCoordinates (a,b,c);
+		MiArbol->vertexdata->GetVertexCoord(MiArbol->Hojas[i].Vert_Hoja[j],a,b,c);
+		v[0]=a; v[1]=b;	v[2]=c; v[3]=1;
+
+		//  el punto resultante será
+		v = mat_aux*v;
+
+		for( p = 0; p < 5; p++ )
+		{ tmp = frustum[p][0] * v[0] + frustum[p][1] * v[1] + frustum[p][2] * v[2] + frustum[p][3];
+		  if ( tmp <= -2.0 )  return false;
+		}
+	}
+
+
+	return true;
+
+}
+
+
+/******************************************   CRITERIO **************************************************/
+
+
+
+//---------------------------------------------------------------------------------------------------------
+// es activo?
+//---------------------------------------------------------------------------------------------------------
+
+bool Foliage::EsActivo (  int num)
+{
+	return ( (Acth[num].prev != -1) || (Acth[num].next != -1));
+}
+
+
+
+
+//-------
+// si está delante devolverá 1. Si está detrás -1
+//------------
+
+int Foliage::DondeEsta (  float x, float y, float z, float rva, float rvb,float rvc, float rvd)
+{
+	// el plano sería pa x + pb y + pc z + pd = 0
+	float donde;
+	int   esta;
+
+	donde = (rva * x) + (rvb * y) + (rvc * z) + rvd;
+	
+	if ( donde <0) esta = -1;  //delante
+	 else if ( donde > 0) esta =1; //detrás
+			else esta = 0;
+
+			return esta;
+
+}
+
+
+
+//----------------------------
+// EXPLICACION DE LOS PARAMETROS::
+// ch --> criterio a aplicar:
+//			si es p --> plano
+//			si es d --> plano y esfera
+//			si es e --> esfera
+//DEVUELVE true cuando está en la zona de interes y debe estar a maximo detalle
+//----------------------------
+
+
+bool Foliage::Criterio ( Hoja &aHoja,  char ch, float rva, float rvb,float rvc, float rvd, float radio)
+{
+	float a,b,c; // coordenadas del primero de los vertices en la hoja
+	float d,e,f; // coords vertice 2
+	float g,h,i; // coords vertice 3
+	float j,k,l; // coords vertice 4
+	float dist;
+	bool inter=false, inter2=false;
+	float ccx, ccy, ccz;
+
+	
+
+//	MiArbol->Vertices[aHoja.Vert_Hoja[0]].GetCoordinates (a,b,c);
+	MiArbol->vertexdata->GetVertexCoord(aHoja.Vert_Hoja[0],a,b,c);
+
+	ccx = MiArbol->cx;
+	ccy = MiArbol->cy;
+	ccz = MiArbol->cz;
+
+
+	if ( (ch == 'p') || (ch == 'd'))
+	{
+	//plano siempre 
+	if (DondeEsta (a,b,c, rva,rvb,rvc,rvd) == 1)
+	{
+//		MiArbol->Vertices[aHoja.Vert_Hoja[1]].GetCoordinates (d,e,f);
+		MiArbol->vertexdata->GetVertexCoord(aHoja.Vert_Hoja[1],d,e,f);
+		if (DondeEsta (d,e,f, rva,rvb,rvc,rvd) == 1)
+		{
+//			MiArbol->Vertices[aHoja.Vert_Hoja[2]].GetCoordinates (g,h,i);
+			MiArbol->vertexdata->GetVertexCoord(aHoja.Vert_Hoja[2],g,h,i);
+			if (DondeEsta (g,h,i, rva,rvb,rvc,rvd) == 1)
+			{
+//				MiArbol->Vertices[aHoja.Vert_Hoja[3]].GetCoordinates (j,k,l);
+				MiArbol->vertexdata->GetVertexCoord(aHoja.Vert_Hoja[3],j,k,l);
+				if (DondeEsta (j,k,l, rva,rvb,rvc,rvd) == 1) inter = true;
+			}
+		}
+
+	}
+	
+
+	}
+	
+		
+	if (( ch == 'e') || (( ch == 'd') && (inter == true))) //CRITERIO DE LA ESFERA
+	{
+	
+	dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz));
+	if (dist >  radio)
+
+	{
+//		MiArbol->Vertices[aHoja.Vert_Hoja[1]].GetCoordinates (a,b,c);
+		MiArbol->vertexdata->GetVertexCoord(aHoja.Vert_Hoja[1],a,b,c);
+		dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz));
+
+		if (dist >  radio)
+		{
+//			MiArbol->Vertices[aHoja.Vert_Hoja[2]].GetCoordinates (a,b,c);
+			MiArbol->vertexdata->GetVertexCoord(aHoja.Vert_Hoja[2],a,b,c);
+			dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz));
+
+			if (dist >  radio)
+			{
+//				MiArbol->Vertices[aHoja.Vert_Hoja[3]].GetCoordinates (a,b,c);
+				MiArbol->vertexdata->GetVertexCoord(aHoja.Vert_Hoja[3],a,b,c);
+				dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz));
+
+				if (dist >  radio) inter2 = true;
+			}
+		}
+	}
+		inter =  inter2;
+	}
+
+
+	return inter;
+}
+
+
+
+
+
+/******************************************   RESOLUCIÓN VARIABLE **************************************************/
+
+//-----------------------------------------
+//
+//	RECORDAR!!!
+//		NO cumple el criterio ------------>  POCO  DETALLE ( COLAPSAR )
+//		SI cumple el criterio ------------>  MUCHO DETALLE ( SPLITEAR )
+//
+// el ch se le pasa a Criterio y es allí donde se evalua
+//	    e --> esfera
+//      p --> plano
+//      d --> los dos criterios
+//------------------------------------------
+
+int Foliage::ResolucionV (char ch, float rva, float rvb,float rvc, float rvd, float radio)
+{
+	bool lista=false;
+    int i, hpost, spli;
+	float renvol, centroz;
+	
+	i = ppio;
+	spli = -1;
+
+	renvol = MiArbol->rad;
+	centroz = MiArbol->cz;
+//	printf (" el centro en %f y el radio es de %f\n", centroz, renvol);
+
+// fijo el máximo del plano de RV
+
+	if (rvd < centroz -renvol )
+		  rvd = (centroz -renvol );
+	else if (rvd > centroz +renvol )
+		  rvd = (centroz +renvol );
+
+//	printf (" el plano está en %f\n", rvd);
+
+
+	//para que fije el valor máximo del radio
+
+	if  (( ch == 'e') || ( ch == 'd')) 
+	{	if (radio> renvol)	radio = renvol;
+		else if (radio <0)  radio =0.0;
+	}
+
+//	printf (" el radio vale %f\n", radio);
+	
+	//empieza a buscar las hojas activas
+
+	while ( i != -1){
+		
+		hpost = Acth[i].next;
+
+		//COLAPSAR
+
+		if (( Criterio ( MiArbol->Hojas[i], ch, rva,rvb,rvc,rvd, radio )== false) && (MiArbol->Hojas[i].padre != -1)) 
+		{
+			// SI ESTA FUESE LA HOJA IZQUIERDA Y LA DERECHA NO CUMPLE TAMPOCO EL CRITERIO
+			if ((MiArbol->Hojas[MiArbol->Hojas[i].padre].hijoi == i) &&
+				( Criterio (MiArbol->Hojas[MiArbol->Hojas[MiArbol->Hojas[i].padre].hijod] , ch, rva,rvb,rvc,rvd, radio )== false))
+			{	//hay que colapsar
+				if (EsActivo(MiArbol->Hojas[MiArbol->Hojas[i].padre].hijod) == false)
+					lista = Forzar_Colapse (MiArbol->Hojas[MiArbol->Hojas[i].padre].hijod, hpost, ch, rva,rvb,rvc,rvd, radio); // para activarla
+				else lista = true;
+									
+			}
+			else
+			// SI ESTA FUESE LA HOJA DERECHA Y LA IZQUIERDA NO CUMPLE TAMPOCO EL CRITERIO
+			if ((MiArbol->Hojas[MiArbol->Hojas[i].padre].hijod == i) &&
+				( Criterio (MiArbol->Hojas[MiArbol->Hojas[MiArbol->Hojas[i].padre].hijoi] , ch, rva,rvb,rvc,rvd, radio )== false))
+			{//hay que colapsar
+				if (EsActivo(MiArbol->Hojas[MiArbol->Hojas[i].padre].hijoi) == false)
+					 lista = Forzar_Colapse (MiArbol->Hojas[MiArbol->Hojas[i].padre].hijoi, hpost,  ch, rva,rvb,rvc,rvd, radio); // para activarla
+				else  lista = true;
+					
+			}
+			
+			 //estan activas preparadas para subir un nivel en la zona de no detalle.
+			
+			if ( lista == true)
+			{
+				lista = false;
+				
+					ColapsaHoja ( MiArbol->Hojas[i].padre, hpost);
+			}
+					
+		}
+    	i = hpost;
+
+	}
+	
+	//ahora veo lo de splitear
+	i = ppio;
+	spli = -1;
+
+	while ( i != -1){
+		hpost = Acth[i].next;
+		spli = Chequea_Split (i, ch, rva,rvb,rvc,rvd, radio);
+			if ( spli != -1) 
+				{	Forzar_Split ( spli, i, hpost);
+					spli = -1;
+				}
+			i = hpost;
+	}
+
+	return (1);
+		
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Colapsa dos hojas 
+//--------------------------------------------------------------------------------------------------------------------------------
+				
+void Foliage::ColapsaHoja (  int h,   int& post)
+{
+
+	//actualizo los punteros del ppio y del final, y post
+	while (( ppio == MiArbol->Hojas[h].hijoi) || ( ppio == MiArbol->Hojas[h].hijod))
+		ppio = Acth[ppio].next;
+	while (( final == MiArbol->Hojas[h].hijoi) || ( final == MiArbol->Hojas[h].hijod))
+		 final = Acth[final].prev; 
+
+	while (( post == MiArbol->Hojas[h].hijoi) || ( post == MiArbol->Hojas[h].hijod))
+		 post = Acth[post].next; 
+
+
+
+	//COLAPSAR = QUITO DOS DE ACTIVOS PONGO UNO A ACTIVO
+
+	if (Acth[MiArbol->Hojas[h].hijoi].next != -1)
+		Acth[Acth[MiArbol->Hojas[h].hijoi].next].prev = Acth[MiArbol->Hojas[h].hijoi].prev;
+	if (Acth[MiArbol->Hojas[h].hijoi].prev != -1)
+		Acth[Acth[MiArbol->Hojas[h].hijoi].prev].next = Acth[MiArbol->Hojas[h].hijoi].next;
+
+	if (Acth[MiArbol->Hojas[h].hijod].next != -1)
+		Acth[Acth[MiArbol->Hojas[h].hijod].next].prev = Acth[MiArbol->Hojas[h].hijod].prev;
+	if (Acth[MiArbol->Hojas[h].hijod].prev != -1)
+		Acth[Acth[MiArbol->Hojas[h].hijod].prev].next = Acth[MiArbol->Hojas[h].hijod].next;
+
+	
+	//  desconecto a los hijos
+	Acth[MiArbol->Hojas[h].hijoi].prev = -1;
+	Acth[MiArbol->Hojas[h].hijoi].next = -1;
+	Acth[MiArbol->Hojas[h].hijod].prev = -1;
+	Acth[MiArbol->Hojas[h].hijod].next = -1;
+
+	//añado al final
+	Acth[h].prev = final;
+	Acth[h].next = -1;
+	Acth[final].next = h;
+	final = h;
+
+	
+}
+
+
+
+
+//--------------------------------------------------------------------------------------------------
+// Forzar colapse 
+// la hoja que paso en el parametro hoja es la que quiero que se active al final
+//--------------------------------------------------------------------------------------------------
+
+
+bool Foliage::Forzar_Colapse(int hoja,  int &hpost,  char ch, float rva, float rvb,float rvc, float rvd, float radio)
+{
+	
+	int h;
+	lista <int> listah;
+	bool fin;
+
+	fin = false;
+	listah.Inserta (hoja); // Inserta un dato en la lista
+
+	while  (listah.NDatos () != 0) 
+	{
+		
+		h = listah.GetCola ();//coger la cola
+		if (MiArbol->Hojas[h].hijoi != -1) 
+
+		{ if (!EsActivo (MiArbol->Hojas[h].hijoi ))
+			listah.Inserta (MiArbol->Hojas[h].hijoi);
+			
+		  if ( (!EsActivo (MiArbol->Hojas[h].hijod)) )	
+			listah.Inserta (MiArbol->Hojas[h].hijod);
+		
+		  if (EsActivo (MiArbol->Hojas[h].hijoi) && EsActivo (MiArbol->Hojas[h].hijod )) 
+			  if((Criterio ( MiArbol->Hojas[MiArbol->Hojas[h].hijoi] ,ch, rva,rvb,rvc,rvd, radio )== false) &&
+				  (Criterio ( MiArbol->Hojas[MiArbol->Hojas[h].hijod], ch, rva,rvb,rvc,rvd, radio ) == false))
+			{
+		    	ColapsaHoja ( h, hpost);
+				listah.Borra(h);
+			}
+			  else fin = true;
+		}
+		else
+		{  fin = true;
+		   listah.Borra(h);
+		}
+
+		if ( fin == true )
+			while ( listah.NDatos () != 0)
+				listah.BorraCola();
+	
+	}
+
+	return (EsActivo (hoja));
+		
+}
+
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Splitea una hoja 
+//--------------------------------------------------------------------------------------------------------------------------------
+				
+void Foliage::SplitHoja (int h, int &post)
+{
+
+	// SPLITEAR: QUITO UNO, PONGO DOS
+	
+	if ( ppio == h) ppio = Acth[h].next;
+	if ( final == h) final = Acth[h].prev; 
+
+	// 1 enlazo los hijos 
+	Acth[MiArbol->Hojas[h].hijoi].next = MiArbol->Hojas[h].hijod;
+	Acth[MiArbol->Hojas[h].hijod].prev = MiArbol->Hojas[h].hijoi;
+	Acth[MiArbol->Hojas[h].hijod].next = -1;
+
+	//y desconecto al padre
+	if ( Acth[h].prev != -1)
+		Acth[Acth[h].prev].next = Acth[h].next;
+	if ( Acth[h].next != -1)
+		Acth[Acth[h].next].prev = Acth[h].prev;
+	Acth[h].prev = -1;
+	Acth[h].next = -1;
+	
+	//añado al final los hijos 
+	Acth[MiArbol->Hojas[h].hijoi].prev = final;
+	Acth[final].next = MiArbol->Hojas[h].hijoi;
+	final = MiArbol->Hojas[h].hijod;
+
+}
+
+
+
+
+//-------------------------------------------------------------------------------------------
+// chequear si tengo que splitear. Devuelve el primero de los nodos que cumple la condicion
+//-------------------------------------------------------------------------------------------
+
+int Foliage::Chequea_Split(int h,  char ch, float rva, float rvb,float rvc, float rvd, float radio)
+{
+	
+	int  nodo;
+	
+
+	nodo = -1;
+
+	if (MiArbol->Hojas[h].hijoi != -1) 
+
+	{  // si el hijo derecho o el izquierdo están en la zona de máximo detalle, haré que estos se activen 	
+		  if ( (Criterio (MiArbol->Hojas[MiArbol->Hojas[h].hijoi],  ch, rva,rvb,rvc,rvd, radio ) == true) ||
+			  (Criterio (MiArbol->Hojas[MiArbol->Hojas[h].hijod], ch, rva,rvb,rvc,rvd, radio ) == true))
+			
+				nodo = MiArbol->Hojas[h].hijoi; 
+			
+			else // si no, bajo un nivel más hasta encontrar algún descendiente que se encuentre en la zona de + detalle
+			{
+				nodo = Chequea_Split (MiArbol->Hojas[h].hijoi,  ch, rva,rvb,rvc,rvd, radio);
+				if ( nodo == -1 ) nodo = Chequea_Split (MiArbol->Hojas[h].hijod, ch, rva,rvb,rvc,rvd, radio);
+			}
+				  
+		}
+		
+	return (nodo);
+		
+}
+
+//-------------------------------------------------------------------------------------------
+// fuerzo a splitear
+// hoja -> es el nodo que cumple la condicion
+// padre -> es el nodo que chequeaba de la lista de activos
+// hpost -> es el nodo siguiente en la lista de activos
+//-------------------------------------------------------------------------------------------
+
+bool Foliage::Forzar_Split(int hoja, int padre, int &hpost)
+{
+	
+	int h;
+	lista <int> listah;
+	bool bien;
+
+	bien = false;
+	h = MiArbol->Hojas[hoja].padre;
+	listah.Inserta (h); // Inserta un dato en la lista
+
+	while ( h != padre)
+	{
+		h = MiArbol->Hojas[h].padre;
+		listah.Inserta (h); // Inserta un dato en la lista
+	}
+
+
+	while  (listah.NDatos () != 0) 
+	{
+		h = listah.GetCola ();//coger el padre más alto
+		SplitHoja(h, hpost);
+		listah.Borra(h);
+	
+	}
+
+	if ( listah.NDatos() == 0)
+		bien = true;
+	return (bien);
+		
+}		
+
+
+
+
+/******************************************   RESOLUCIÓN CONSTANTE **************************************************/
+
+
+int Foliage::ResolucionC (float dist, float dmax, float dmin)
+{
+
+	float difdist,  d;
+	int difhojas, nhojas;
+
+	if (( dist > dmin) && (dist <dmax))
+	{
+		difdist = dmax - dmin;
+		difhojas = MiArbol->nHojas - MiArbol->minHojas;
+
+		d = dist - dmin;
+
+		//regla de 3
+
+		nhojas = abs(d*difhojas /difdist);
+
+		AjusteHojas ((MiArbol->nHojas)-nhojas);
+
+	}
+	else if (dist > dmax) {
+		AjusteHojas (MiArbol->minHojas);
+	}
+	else if (dist < dmin) {
+		AjusteHojas (MiArbol->nHojas);
+	}
+		
+	return (nhactivas);
+}
+
+
+
+void Foliage::AjusteHojas( int nhojas)
+{
+	if ((nhojas <= MiArbol->nHojas) && (nhojas >= MiArbol->minHojas))
+	{
+		if ( nhojas < nhactivas) {
+			RCecol ( nhactivas - nhojas);
+		}
+		else  {
+			 RCsplit (nhojas-nhactivas );
+		}
+
+		nhactivas = nhojas;
+	//	printf ( "ajusto a %i\n", nhactivas );
+
+	}
+
+}
+
+//-----------------------------------------
+//
+//	RECORDAR!!!
+//		NO cumple el criterio ------------>  POCO  DETALLE ( COLAPSAR )
+//		SI cumple el criterio ------------>  MUCHO DETALLE ( SPLITEAR )
+//
+// el ch se le pasa a Criterio y es allí donde se evalua
+//------------------------------------------
+
+/*
+void Foliage::RCecol (  int nhojas)
+{
+	int i, hpost;
+
+	i = ppio;
+	
+	while (( i != -1) && (nhojas>0)){
+ 		hpost = Acth[i].next;
+
+			if ( MiArbol->Hojas[i].padre != -1) 
+				if ( MiArbol->Hojas[MiArbol->Hojas[i].padre].hijoi == i)
+				{if ( EsActivo (MiArbol->Hojas[MiArbol->Hojas[i].padre].hijod ) )
+				{ 
+					ColapsaHoja ( MiArbol->Hojas[i].padre, hpost);
+					nhojas --; }
+				}
+				else 
+				{if ( EsActivo (MiArbol->Hojas[MiArbol->Hojas[i].padre].hijoi ) )
+				{
+					ColapsaHoja ( MiArbol->Hojas[i].padre, hpost); 
+					nhojas --; }
+				}
+
+
+		i = hpost;
+		
+	}
+}
+*/
+
+void Foliage::RCecol ( int num)
+{
+
+	int  j, h;
+
+	j = num;
+	h = final+1;
+		while ((h<=MiArbol->TotHojas) && (j>0))
+		{
+			while (( ppio == MiArbol->Hojas[h].hijoi) || ( ppio == MiArbol->Hojas[h].hijod))
+				ppio = Acth[ppio].next;
+
+			while (( final == MiArbol->Hojas[h].hijoi) || ( final == MiArbol->Hojas[h].hijod))
+				final = Acth[final].prev; 
+
+
+			//COLAPSAR = QUITO DOS DE ACTIVOS PONGO UNO A ACTIVO
+
+			if (Acth[MiArbol->Hojas[h].hijoi].next != -1)
+				Acth[Acth[MiArbol->Hojas[h].hijoi].next].prev = Acth[MiArbol->Hojas[h].hijoi].prev;
+			if (Acth[MiArbol->Hojas[h].hijoi].prev != -1)
+				Acth[Acth[MiArbol->Hojas[h].hijoi].prev].next = Acth[MiArbol->Hojas[h].hijoi].next;
+
+			if (Acth[MiArbol->Hojas[h].hijod].next != -1)
+				Acth[Acth[MiArbol->Hojas[h].hijod].next].prev = Acth[MiArbol->Hojas[h].hijod].prev;
+			if (Acth[MiArbol->Hojas[h].hijod].prev != -1)
+				Acth[Acth[MiArbol->Hojas[h].hijod].prev].next = Acth[MiArbol->Hojas[h].hijod].next;
+
+	
+			//  desconecto a los hijos
+			Acth[MiArbol->Hojas[h].hijoi].prev = -1;
+			Acth[MiArbol->Hojas[h].hijoi].next = -1;
+			Acth[MiArbol->Hojas[h].hijod].prev = -1;
+			Acth[MiArbol->Hojas[h].hijod].next = -1;
+
+			//añado al final
+			Acth[h].prev = final;
+			Acth[h].next = -1;
+			Acth[final].next = h;
+			final = h;
+
+
+			// decremento el contador de colapsos
+			j--;
+			//incremento el posible siguiente colapso 
+			h++;
+
+
+		}
+
+}
+
+/*
+void Foliage::RCsplit (  int nhojas)
+{
+	int i, hpost;
+
+	i = ppio;
+	
+	while (( i != -1) && (nhojas>0)){
+		hpost = Acth[i].next;
+
+		if (MiArbol->Hojas[i].hijoi != -1){
+					SplitHoja(i, hpost);
+					nhojas --;
+
+		}
+		
+		i = hpost;
+
+	}
+}
+*/
+
+int Foliage::AnteriorActivo (int h)
+{
+	int i;
+
+	
+	if (ppio > h)  i = -1;
+	else
+	{
+		i = h--;
+	
+		while (EsActivo (i) == false) 	
+			i--;
+	}
+
+	return (i);
+}
+
+int Foliage::PosteriorActivo (int h)
+{	int i;
+
+	i = h++;
+	
+	while ((EsActivo (i) == false) || (i> MiArbol->TotHojas))
+		i++;
+
+	if (i > MiArbol->TotHojas) i=-1;
+
+
+	return (i);
+}
+
+void Foliage::RCsplit ( int num)
+{
+
+	int  j, h, ant, post;
+
+	j = num;
+	h = final;
+	while ((h > MiArbol->nHojas) &&  (j>0))
+	{
+
+		///////////// insertar a los hijos en orden segun su indice
+		//hijo izquierdo
+		ant = AnteriorActivo (MiArbol->Hojas[h].hijoi);
+		post = PosteriorActivo (MiArbol->Hojas[h].hijoi);
+
+
+		Acth[MiArbol->Hojas[h].hijoi].next = post;
+		Acth[MiArbol->Hojas[h].hijoi].prev = ant;
+		if (ant != -1) Acth[ant].next = MiArbol->Hojas[h].hijoi;
+			else ppio = MiArbol->Hojas[h].hijoi;
+		if (post != -1) Acth[post].prev = MiArbol->Hojas[h].hijoi;
+
+		
+		//hijo derecho
+		ant = AnteriorActivo (MiArbol->Hojas[h].hijod);
+		post = PosteriorActivo (MiArbol->Hojas[h].hijod);
+
+
+		Acth[MiArbol->Hojas[h].hijod].next = post;
+		Acth[MiArbol->Hojas[h].hijod].prev = ant;
+		if (ant != -1)  Acth[ant].next = MiArbol->Hojas[h].hijod;
+				else ppio = MiArbol->Hojas[h].hijod;
+		if (post != -1) Acth[post].prev = MiArbol->Hojas[h].hijod;
+
+
+		// despues de insertar los hijos miro a ver cual spliteare el siguiente
+		final = Acth[h].prev;
+		
+		//y desconecto al padre
+		if ( Acth[h].prev != -1)
+			Acth[Acth[h].prev].next = Acth[h].next;
+		//if ( Acth[h].next != -1)
+		//	Acth[Acth[h].next].prev = Acth[h].prev;
+		Acth[h].prev = -1;
+		Acth[h].next = -1;
+	
+		// decremento el contador de colapsos
+		j--;
+		//incremento el posible siguiente colapso 
+		h--;
+
+
+	}
+
+
+ }
+
+/******************************************   IMPOSTORES **************************************************/
+	
+//--------------------------------------------------------------------------------------------------------------------------------
+// Dibuja la caja envolvente. DibujaCaja la dibuja realmente, y la 
+//--------------------------------------------------------------------------------------------------------------------------------
+			/*	
+void Foliage::DibujaCaja (float alfa, float d)
+{
+
+	glPushMatrix();
+
+	glColor3f(1.0, 0.0, 0.0);
+
+//	glLineWidth(2.0);
+//	glTranslated (0.0,cy, 0.0);
+//	glScalef (width,heigth,depth);
+//	glutWireCube ( 1.0);
+	glRotatef(-alfa,0,1,0);
+
+	glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+	glBegin (GL_POLYGON); 
+
+		glVertex3f (MiArbol->cx + MiArbol->rad, MiArbol->cy - MiArbol->rad, d); 
+		glVertex3f (MiArbol->cx - MiArbol->rad, MiArbol->cy - MiArbol->rad, d);
+		glVertex3f (MiArbol->cx - MiArbol->rad, MiArbol->cy + MiArbol->rad, d);
+		glVertex3f (MiArbol->cx + MiArbol->rad, MiArbol->cy + MiArbol->rad, d);
+
+
+	glEnd();
+
+
+	glColor3f(1.0, 1.0, 1.0);
+
+	glPopMatrix();
+	
+
+}
+
+*/
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/hoja.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/hoja.h	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/hoja.h	(revision 830)
@@ -0,0 +1,28 @@
+#ifndef HOJA_H
+#define HOJA_H
+
+
+class Hoja
+{
+	public :
+		// Variable members
+    	int  Vert_Hoja[4];// Array of pointers to vertices
+		float  Normal[3];
+		float  Cuantas_hojas;
+		int padre;
+		int hijoi;
+		int hijod;
+		int visible;
+		int raiz;
+	
+		
+	public :
+		// Constructors
+		Hoja (void); // Void constructor
+		Hoja (const Hoja& aHoja); // Copy constructor
+		virtual ~Hoja (void); // Destructor
+
+
+};
+
+#endif
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Vector.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Vector.h	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/Vector.h	(revision 830)
@@ -0,0 +1,73 @@
+/*
+---------------------------------------------------------------------
+This file is part of Sandra Engine (real-time 3D engine)
+ Copyright (C) 2004 Jesus Gumbau Portales
+
+This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, 
+ USA, or go to http://www.gnu.org/copyleft/lesser.txt.
+---------------------------------------------------------------------
+*/
+
+// 21-02-2001
+// Jesus Gumbau Portales
+
+#ifndef __VECTOR_H__
+#define __VECTOR_H__
+
+#include <math.h>
+
+#ifndef PI
+#define PI	3.14159f
+#endif
+#define GradToRad(x) x*PI/180.0f
+
+class Vector
+{
+public:
+	Vector(double vx=0.0f, double vy=0.0f, double vz=0.0f, double vw=1.0f){ x=vx; y=vy; z=vz; w=vw; }
+	double x,y,z,w;
+	inline Vector operator*(double f) const { return Vector(x*f,y*f,z*f); }
+	inline void operator+=(const Vector &v){ x+=v.x; y+=v.y; z+=v.z; }
+	inline void operator+=(double f){ x+=f; y+=f; z+=f; }
+	inline void operator-=(const Vector &v){ x-=v.x; y-=v.y; z-=v.z; }
+	inline void operator-=(double f){ x-=f; y-=f; z-=f; }
+	inline Vector operator+(const Vector &v) const { return Vector(x+v.x,y+v.y,z+v.z); }
+//	Vector operator-(Vector &v){ return Vector(x-v.x,y-v.y,z-v.z); }
+	inline Vector operator-(const Vector &v) const { return Vector(x-v.x,y-v.y,z-v.z); }
+	inline double Module(void) const { return sqrtf(x*x + y*y + z*z); }
+	inline bool operator==(const Vector &v) const { return (x==v.x && y==v.y && z==v.z); }
+	inline bool operator!=(const Vector &v) const { return (x!=v.x || y!=v.y || z!=v.z); }
+	inline Vector operator-(void) const { return Vector(-x,-y,-z); }
+	inline Vector operator/(double f) const { return (*this)*(1/f); }
+	inline Vector operator/=(double f) { x/=f; y/=f; z/=f; return (*this); }
+	inline Vector operator=(const Vector &v) { x=v.x; y=v.y; z=v.z; w=v.w; return Vector(x,y,z,w); }
+	inline Vector operator=(double f) { x=f; y=f; z=f; return Vector(x,y,z); }
+	inline bool operator<(const Vector &v) const { return (x<v.x && y<v.y && z<v.z && w<v.w); }
+	inline void Normalize(void){
+		double module=sqrtf(x*x + y*y + z*z);
+		x=x/module;
+		y=y/module;
+		z=z/module;
+	}
+
+
+	static const Vector UNITY;
+		
+	const double &operator[](unsigned int i) const { return (&x)[i]; }
+	double &operator[](unsigned int i){ return (&x)[i]; }
+};
+
+#endif
+
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/activas.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/activas.cpp	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/activas.cpp	(revision 830)
@@ -0,0 +1,19 @@
+#include "activas.h"
+#include <stdio.h>
+
+
+//---------------------------------------------------------------------------------------------------
+// Constructor de copia sin parámetros
+//---------------------------------------------------------------------------------------------------
+Activas::Activas (void)  
+{
+	indice = prev = next = -1;
+}
+
+
+//--------------------------------------------------------------------------------------------------------------------------------
+// Destructor. We must deallocate the memory allocated for pointers 
+//--------------------------------------------------------------------------------------------------------------------------------
+Activas::~Activas (void)
+{
+}
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/foliage.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/foliage.h	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/foliage.h	(revision 830)
@@ -0,0 +1,64 @@
+#ifndef FOLIAGE_H
+#define FOLIAGE_H
+
+
+#include "arbol.h"
+#include "Activas.h"
+//#include "material.h"
+#include "tlista.h"
+//#include <vl\VLf.h>
+#include "TMatrix.h"
+
+
+
+class Foliage
+{
+	public :
+
+	Arbol	 *MiArbol;
+	Activas  *Acth; // primera hoja activa
+	int ppio, final;
+	int nhactivas;
+	TMatrix mat_aux;
+
+	public :
+		Foliage (void); // Void constructor
+		Foliage ( Arbol* Arbol1 ); // Constructor with the name of a file cotaining the data
+		virtual ~Foliage (void); // Destructor
+		
+		// sacar por pantalla
+/*		void Dibuja_Hoja ( Hoja&);
+		int  DibujarHojas (float frustum[6][4], float zoom);
+		void DibujaEsfera (float);*/
+
+		//culling
+		void Culling (float frustum[6][4]);
+		bool LeafinFrustum ( int i, float frustum[6][4]);
+		
+		// resolucion variable
+		bool EsActivo (  int num);
+		int  DondeEsta (  float x, float y, float z, float rva, float rvb,float rvc, float rvd);
+		bool Criterio ( Hoja &aHoja, char ch, float rva, float rvb,float rvc, float rvd, float radio);
+		int  ResolucionV ( char c, float rva, float rvb,float rvc, float rvd, float radio);
+		void ColapsaHoja (int, int&);
+		bool Forzar_Colapse (int hoja,  int &hpost,  char ch, float rva, float rvb,float rvc, float rvd, float radio);
+		void SplitHoja (int, int&);
+		int  Chequea_Split(int, char, float rva, float rvb,float rvc, float rvd, float radio);
+		bool Forzar_Split(int, int, int&);
+		int  AnteriorActivo (int h);
+		int  PosteriorActivo (int h);
+
+
+		// resolucion constante
+		int  ResolucionC (float dist, float dmax, float dmin);
+		void AjusteHojas( int nhojas);
+		void RCecol (  int nhojas);
+		void RCsplit (  int nhojas);
+
+		//impostores
+//		void DibujaCaja (float alfa, float d);
+//		int  DibujaMediaCopa ( char c, float rva, float rvb,float rvc, float rvd, float radio);
+		
+};
+
+#endif
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/TMatrix.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/TMatrix.h	(revision 830)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/TMatrix.h	(revision 830)
@@ -0,0 +1,639 @@
+ /*
+---------------------------------------------------------------------
+This file is part of Sandra Engine (real-time 3D engine)
+ Copyright (C) 2004 Jesus Gumbau Portales
+
+This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, 
+ USA, or go to http://www.gnu.org/copyleft/lesser.txt.
+---------------------------------------------------------------------
+*/
+
+// 21-02-2001
+// Jesus Gumbau Portales
+
+#ifndef __TMATRIX_H__
+#define __TMATRIX_H__
+
+#include "Vector.h"
+
+#define MATRIX_WORLD_SPACE 0
+#define MATRIX_OBJECT_SPACE 1
+
+	class RotMatrix
+	{
+	private:
+		Vector col[3];
+		float tempmat[16];
+	public:
+		RotMatrix(void){
+			col[0].x=1.0f; col[1].x=0.0f; col[2].x=0.0f;
+			col[0].y=0.0f; col[1].y=1.0f; col[2].y=0.0f;
+			col[0].z=0.0f; col[1].z=0.0f; col[2].z=1.0f;
+		}
+		RotMatrix(const RotMatrix &t){
+			col[0]=t.col[0];
+			col[1]=t.col[1];
+			col[2]=t.col[2];
+		}
+
+		void SetBaseX(float v[3]){ col[0].x=v[0]; col[0].y=v[1]; col[0].z=v[2]; }
+		void SetBaseY(float v[3]){ col[1].x=v[0]; col[1].y=v[1]; col[1].z=v[2]; }
+		void SetBaseZ(float v[3]){ col[2].x=v[0]; col[2].y=v[1]; col[2].z=v[2]; }
+
+		void SetBaseX(float x, float y, float z){ col[0].x=x; col[0].y=y; col[0].z=z; }
+		void SetBaseY(float x, float y, float z){ col[1].x=x; col[1].y=y; col[1].z=z; }
+		void SetBaseZ(float x, float y, float z){ col[2].x=x; col[2].y=y; col[2].z=z; }
+
+		void SetBaseX(const Vector &v){ col[0].x=v.x; col[0].y=v.y; col[0].z=v.z; }
+		void SetBaseY(const Vector &v){ col[1].x=v.x; col[1].y=v.y; col[1].z=v.z; }
+		void SetBaseZ(const Vector &v){ col[2].x=v.x; col[2].y=v.y; col[2].z=v.z; }
+
+		Vector GetBaseX(void) const { return col[0]; }
+		Vector GetBaseY(void) const { return col[1]; }
+		Vector GetBaseZ(void) const { return col[2]; }
+
+		// RotMatrix x Vector
+		Vector operator*(const Vector &v) const {
+			return Vector(col[0].x*v.x + col[1].x*v.y + col[2].x*v.z,
+						  col[0].y*v.x + col[1].y*v.y + col[2].y*v.z,
+						  col[0].z*v.x + col[1].z*v.y + col[2].z*v.z);
+		}
+
+		Vector &operator[](unsigned int column){
+			return ((Vector&)(col[column]));
+		}
+		const Vector &operator[](unsigned int column) const {
+			return ((Vector&)(col[column]));
+		}
+
+
+		// RotMatrix - RotMatrix
+		RotMatrix operator-(const RotMatrix &tm) const {
+			RotMatrix res;
+
+			for (unsigned int c=0; c<3; c++)
+				for (unsigned int f=0; f<3; f++)
+					res[c][f]=col[c][f]-tm[c][f];
+
+			return res;
+		}
+
+
+		// RotMatrix * RotMatrix
+		RotMatrix operator*(const RotMatrix &tm) const {
+			RotMatrix res;
+			for (unsigned int c=0; c<3; c++)
+				for (unsigned int f=0; f<3; f++)
+				{
+					float ff=0.0f;
+					ff+=col[0][f]*tm[c][0];
+					ff+=col[1][f]*tm[c][1];
+					ff+=col[2][f]*tm[c][2];
+					res[c][f]=ff;
+				}
+			return res;
+		}
+
+		void PostMultiply(const RotMatrix &tm){
+			RotMatrix res;
+			for (unsigned int f=0; f<3; f++)
+				for (unsigned int c=0; c<3; c++)
+				{
+					float ff=0.0f;
+					ff+=col[0][c]*tm[f][0];
+					ff+=col[1][c]*tm[f][1];
+					ff+=col[2][c]*tm[f][2];
+					res[c][f]=ff;
+				}
+			(*this)=res;
+		}
+
+		const RotMatrix & operator=(const RotMatrix &tm){
+			col[0]=tm.col[0];
+			col[1]=tm.col[1];
+			col[2]=tm.col[2];
+			return tm;
+		}
+
+		bool operator!=(const RotMatrix &tm) const {
+			if (col[0]!=tm[0]) return false;
+			if (col[1]!=tm[1]) return false;
+			if (col[2]!=tm[2]) return false;
+			return true;
+		}
+
+		void LoadIdentity(void){
+			col[0][0]=1.0f; col[1][0]=0.0f; col[2][0]=0.0f;
+			col[0][1]=0.0f; col[1][1]=1.0f; col[2][1]=0.0f;
+			col[0][2]=0.0f; col[1][2]=0.0f; col[2][2]=1.0f;
+		}
+
+		// returns a mat[16] in opengl conform format
+		// WARNING: returns a dir to a TEMP variable
+		float *GetOpenGLConform(void){
+			tempmat[0]=col[0][0];
+			tempmat[1]=col[0][1];
+			tempmat[2]=col[0][2];
+			tempmat[3]=0.0f;
+			tempmat[4]=col[1][0];
+			tempmat[5]=col[1][1];
+			tempmat[6]=col[1][2];
+			tempmat[7]=0.0f;
+			tempmat[8]=col[2][0];
+			tempmat[9]=col[2][1];
+			tempmat[10]=col[2][2];
+			tempmat[11]=0.0f;
+			tempmat[12]=0.0f;
+			tempmat[13]=0.0f;
+			tempmat[14]=0.0f;
+			tempmat[15]=1.0f;
+			return tempmat;
+		}
+
+
+		// sets the matrix to a rotation matrix 
+		void LoadRotationXMatrix(float angle){
+			float cosa=cosf(GradToRad(angle));
+			float sina=sinf(GradToRad(angle));
+			col[0][0]=1.0f; col[1][0]=0.0f; col[2][0]=0.0f;
+			col[0][1]=0.0f; col[1][1]=cosa; col[2][1]=-sina;
+			col[0][2]=0.0f; col[1][2]=sina; col[2][2]=cosa;
+		}
+
+		void LoadRotationYMatrix(float angle){
+			float cosa=cosf(GradToRad(angle));
+			float sina=sinf(GradToRad(angle));
+			col[0][0]=cosa; col[1][0]=0.0f; col[2][0]=sina;
+			col[0][1]=0.0f; col[1][1]=1.0f; col[2][1]=0.0f;
+			col[0][2]=-sina;col[1][2]=0.0f; col[2][2]=cosa;
+		}
+
+		void LoadRotationZMatrix(float angle){
+			float cosa=cosf(GradToRad(angle));
+			float sina=sinf(GradToRad(angle));
+			col[0][0]=cosa; col[1][0]=-sina;col[2][0]=0.0f;
+			col[0][1]=sina; col[1][1]=cosa; col[2][1]=0.0f;
+			col[0][2]=0.0f; col[1][2]=0.0f; col[2][2]=1.0f;
+		}
+
+		// Rotate the object around X axis
+		void RotateX(float angle, int mode=MATRIX_OBJECT_SPACE){
+			RotMatrix tr;
+			tr.LoadRotationXMatrix(angle); // FIXME!!!!! -angle?!?!
+			if (mode==MATRIX_OBJECT_SPACE)
+				operator=( (*this)*tr );
+			else
+				operator=( tr*(*this) );
+		}
+
+		void RotateY(float angle, int mode=MATRIX_OBJECT_SPACE){
+			RotMatrix tr;
+			tr.LoadRotationYMatrix(angle);
+			if (mode==MATRIX_OBJECT_SPACE)
+				operator=( (*this)*tr );
+			else
+				operator=( tr*(*this) );
+		}
+
+		void RotateZ(float angle, int mode=MATRIX_OBJECT_SPACE){
+			RotMatrix tr;
+			tr.LoadRotationZMatrix(angle);
+			if (mode==MATRIX_OBJECT_SPACE)
+				operator=( (*this)*tr );
+			else
+				operator=( tr*(*this) );
+		}
+
+		void RotateAxis(float angle, Vector axis, int mode=MATRIX_OBJECT_SPACE){
+			RotMatrix Rx,Ry,Rz,iRx,iRy;
+			float d = (float)sqrt(axis.y*axis.y + axis.z*axis.z);
+
+			Rx.SetBaseX(1.0f, 0.0f, 0.0f);
+			Rx.SetBaseY(0.0f, axis.z/d, axis.y/d);
+			Rx.SetBaseZ(0.0f, -axis.y/d, axis.z/d);			
+			
+			Ry.SetBaseX(d, 0.0f, axis.x);
+			Ry.SetBaseY(0.0f, 1.0f, 0.0f);
+			Ry.SetBaseZ(-axis.x, 0.0f, d);
+
+			Rz.LoadRotationZMatrix(angle);
+
+			iRx = Rx;	iRx.Traspose();
+			iRy = Ry;	iRy.Traspose();
+			
+			RotMatrix accum;
+			accum.LoadIdentity();
+			if (d!=0)
+				accum = accum * iRx;
+			accum = accum * iRy;
+			accum = accum * Rz;
+			accum = accum * Ry;
+			if (d!=0)
+				accum = accum * Rx;
+
+			if (mode==MATRIX_OBJECT_SPACE)
+				operator=( (*this)*accum );
+			else
+				operator=( accum*(*this) );
+		}
+
+		void Traspose(void){
+			tempmat[0]=col[0][0];
+			tempmat[1]=col[0][1];
+			tempmat[2]=col[0][2];
+
+			tempmat[3]=col[1][0];
+			tempmat[4]=col[1][1];
+			tempmat[5]=col[1][2];
+
+			tempmat[6]=col[2][0];
+			tempmat[7]=col[2][1];
+			tempmat[8]=col[2][2];
+
+			col[0].x=tempmat[0];  col[1].x=tempmat[1];  col[2].x=tempmat[2];
+			col[0].y=tempmat[4];  col[1].y=tempmat[4];  col[2].y=tempmat[5];
+			col[0].z=tempmat[6];  col[1].z=tempmat[7];  col[2].z=tempmat[8];
+		}
+
+		// This function inverts (only) a valid ROTRANSFORM Matrix (with unitary vector lengths). This should not work on arbitrary matrices
+		void Invert(void){
+			Traspose();
+		}
+	};
+
+
+	class TMatrix
+	{
+	private:
+		Vector col[4];
+		float tempmat[16];
+	public:
+		TMatrix(void){
+			col[0].x=1.0f; col[1].x=0.0f; col[2].x=0.0f; col[3].x=0.0f;
+			col[0].y=0.0f; col[1].y=1.0f; col[2].y=0.0f; col[3].y=0.0f;
+			col[0].z=0.0f; col[1].z=0.0f; col[2].z=1.0f; col[3].z=0.0f;
+			col[0].w=0.0f; col[1].w=0.0f; col[2].w=0.0f; col[3].w=1.0f;
+		}
+		TMatrix(const TMatrix &t){
+			col[0]=t.col[0];
+			col[1]=t.col[1];
+			col[2]=t.col[2];
+			col[3]=t.col[3];
+		}
+
+		TMatrix(const Vector &tr, const RotMatrix &rot, const Vector &scale){
+			col[0] = rot.GetBaseX()*scale.x;
+			col[1] = rot.GetBaseY()*scale.y;
+			col[2] = rot.GetBaseZ()*scale.z;
+			col[3] = tr;
+			col[0].w=0.0f; col[1].w=0.0f; col[2].w=0.0f; col[3].w=1.0f;
+		}
+
+		void SetBaseX(float v[3]){ col[0].x=v[0]; col[0].y=v[1]; col[0].z=v[2]; }
+		void SetBaseY(float v[3]){ col[1].x=v[0]; col[1].y=v[1]; col[1].z=v[2]; }
+		void SetBaseZ(float v[3]){ col[2].x=v[0]; col[2].y=v[1]; col[2].z=v[2]; }
+		void SetPoint(float v[3]){ col[3].x=v[0]; col[3].y=v[1]; col[3].z=v[2]; }
+
+		void SetBaseX(float x, float y, float z){ col[0].x=x; col[0].y=y; col[0].z=z; }
+		void SetBaseY(float x, float y, float z){ col[1].x=x; col[1].y=y; col[1].z=z; }
+		void SetBaseZ(float x, float y, float z){ col[2].x=x; col[2].y=y; col[2].z=z; }
+		void SetPoint(float x, float y, float z){ col[3].x=x; col[3].y=y; col[3].z=z; }
+
+		void SetBaseX(const Vector &v){ col[0].x=v.x; col[0].y=v.y; col[0].z=v.z; }
+		void SetBaseY(const Vector &v){ col[1].x=v.x; col[1].y=v.y; col[1].z=v.z; }
+		void SetBaseZ(const Vector &v){ col[2].x=v.x; col[2].y=v.y; col[2].z=v.z; }
+		void SetPoint(const Vector &v){ col[3].x=v.x; col[3].y=v.y; col[3].z=v.z; }
+
+		Vector GetBaseX(void) const { return col[0]; }
+		Vector GetBaseY(void) const { return col[1]; }
+		Vector GetBaseZ(void) const { return col[2]; }
+
+		// TMatrix x Vector
+		Vector operator*(const Vector &v) const {
+			return Vector(col[0].x*v.x + col[1].x*v.y + col[2].x*v.z + col[3].x*v.w,
+						  col[0].y*v.x + col[1].y*v.y + col[2].y*v.z + col[3].y*v.w,
+						  col[0].z*v.x + col[1].z*v.y + col[2].z*v.z + col[3].z*v.w,
+						  col[0].w*v.x + col[1].w*v.y + col[2].w*v.z + col[3].w*v.w);
+		}
+
+		Vector &operator[](unsigned int column){
+			return ((Vector&)(col[column]));
+		}
+		const Vector &operator[](unsigned int column) const {
+			return ((Vector&)(col[column]));
+		}
+
+
+		// TMatrix - TMatrix
+		TMatrix operator-(const TMatrix &tm) const {
+			TMatrix res;
+
+			for (unsigned int c=0; c<4; c++)
+				for (unsigned int f=0; f<4; f++)
+					res[c][f]=col[c][f]-tm[c][f];
+
+			return res;
+		}
+
+
+		// TMatrix * TMatrix
+		TMatrix operator*(const TMatrix &tm) const {
+			TMatrix res;
+			for (unsigned int c=0; c<4; c++)
+				for (unsigned int f=0; f<4; f++)
+				{
+					float ff=0.0f;
+					ff+=col[0][f]*tm[c][0];
+					ff+=col[1][f]*tm[c][1];
+					ff+=col[2][f]*tm[c][2];
+					ff+=col[3][f]*tm[c][3];
+					res[c][f]=ff;
+				}
+			return res;
+		}
+
+		void PostMultiply(const TMatrix &tm){
+			TMatrix res;
+			for (unsigned int f=0; f<4; f++)
+				for (unsigned int c=0; c<4; c++)
+				{
+					float ff=0.0f;
+					ff+=col[0][c]*tm[f][0];
+					ff+=col[1][c]*tm[f][1];
+					ff+=col[2][c]*tm[f][2];
+					ff+=col[3][c]*tm[f][3];
+					res[c][f]=ff;
+				}
+			(*this)=res;
+		}
+
+		const TMatrix & operator=(const TMatrix &tm){
+			col[0]=tm.col[0];
+			col[1]=tm.col[1];
+			col[2]=tm.col[2];
+			col[3]=tm.col[3];
+			return tm;
+		}
+
+		bool operator!=(const TMatrix &tm) const {
+			if (col[0]!=tm[0]) return false;
+			if (col[1]!=tm[1]) return false;
+			if (col[2]!=tm[2]) return false;
+			if (col[3]!=tm[3]) return false;
+			return true;
+		}
+
+		void LoadIdentity(void){
+			col[0][0]=1.0f; col[1][0]=0.0f; col[2][0]=0.0f; col[3][0]=0.0f;
+			col[0][1]=0.0f; col[1][1]=1.0f; col[2][1]=0.0f; col[3][1]=0.0f;
+			col[0][2]=0.0f; col[1][2]=0.0f; col[2][2]=1.0f; col[3][2]=0.0f;
+			col[0][3]=0.0f; col[1][3]=0.0f; col[2][3]=0.0f; col[3][3]=1.0f;
+		}
+
+		// returns a mat[16] in opengl conform format
+		// WARNING: returns a dir to a TEMP variable
+		float *GetOpenGLConform(void){
+			tempmat[0]=col[0][0];
+			tempmat[1]=col[0][1];
+			tempmat[2]=col[0][2];
+			tempmat[3]=col[0][3];
+			tempmat[4]=col[1][0];
+			tempmat[5]=col[1][1];
+			tempmat[6]=col[1][2];
+			tempmat[7]=col[1][3];
+			tempmat[8]=col[2][0];
+			tempmat[9]=col[2][1];
+			tempmat[10]=col[2][2];
+			tempmat[11]=col[2][3];
+			tempmat[12]=col[3][0];
+			tempmat[13]=col[3][1];
+			tempmat[14]=col[3][2];
+			tempmat[15]=col[3][3];
+			return tempmat;
+		}
+
+		void ImportOpenGLMatrix(float *oglmatrix){
+			col[0][0]=oglmatrix[0];
+			col[0][1]=oglmatrix[1];
+			col[0][2]=oglmatrix[2];
+			col[0][3]=oglmatrix[3];
+			col[1][0]=oglmatrix[4];
+			col[1][1]=oglmatrix[5];
+			col[1][2]=oglmatrix[6];
+			col[1][3]=oglmatrix[7];
+			col[2][0]=oglmatrix[8];
+			col[2][1]=oglmatrix[9];
+			col[2][2]=oglmatrix[10];
+			col[2][3]=oglmatrix[11];
+			col[3][0]=oglmatrix[12];
+			col[3][1]=oglmatrix[13];
+			col[3][2]=oglmatrix[14];
+			col[3][3]=oglmatrix[15];
+		}
+
+/*		// REVISAR ESTO
+		Vector GetAbsolutePos(void) const {
+			return (operator*(col[3]));
+		}
+*/
+		Vector GetTranslation(void) const {
+			return col[3];
+		}
+
+		// sets the matrix to a rotation matrix 
+		void LoadRotationXMatrix(float angle){
+			float cosa=cosf(GradToRad(angle));
+			float sina=sinf(GradToRad(angle));
+			col[0][0]=1.0f; col[1][0]=0.0f; col[2][0]=0.0f; col[3][0]=0.0f;
+			col[0][1]=0.0f; col[1][1]=cosa; col[2][1]=-sina;col[3][1]=0.0f;
+			col[0][2]=0.0f; col[1][2]=sina; col[2][2]=cosa; col[3][2]=0.0f;
+			col[0][3]=0.0f; col[1][3]=0.0f; col[2][3]=0.0f; col[3][3]=1.0f;
+		}
+
+		void LoadRotationYMatrix(float angle){
+			float cosa=cosf(GradToRad(angle));
+			float sina=sinf(GradToRad(angle));
+			col[0][0]=cosa; col[1][0]=0.0f; col[2][0]=sina; col[3][0]=0.0f;
+			col[0][1]=0.0f; col[1][1]=1.0f; col[2][1]=0.0f; col[3][1]=0.0f;
+			col[0][2]=-sina;col[1][2]=0.0f; col[2][2]=cosa; col[3][2]=0.0f;
+			col[0][3]=0.0f; col[1][3]=0.0f; col[2][3]=0.0f; col[3][3]=1.0f;
+		}
+
+		void LoadRotationZMatrix(float angle){
+			float cosa=cosf(GradToRad(angle));
+			float sina=sinf(GradToRad(angle));
+			col[0][0]=cosa; col[1][0]=-sina;col[2][0]=0.0f; col[3][0]=0.0f;
+			col[0][1]=sina; col[1][1]=cosa; col[2][1]=0.0f; col[3][1]=0.0f;
+			col[0][2]=0.0f; col[1][2]=0.0f; col[2][2]=1.0f; col[3][2]=0.0f;
+			col[0][3]=0.0f; col[1][3]=0.0f; col[2][3]=0.0f; col[3][3]=1.0f;
+		}
+
+		// Rotate the object around X axis
+		void RotateX(float angle, int mode=MATRIX_OBJECT_SPACE){
+			TMatrix tr;
+			tr.LoadRotationXMatrix(angle); // FIXME!!!!! -angle?!?!
+			if (mode==MATRIX_OBJECT_SPACE)
+				operator=( (*this)*tr );
+			else
+				operator=( tr*(*this) );
+		}
+
+		void RotateY(float angle, int mode=MATRIX_OBJECT_SPACE){
+			TMatrix tr;
+			tr.LoadRotationYMatrix(angle);
+			if (mode==MATRIX_OBJECT_SPACE)
+				operator=( (*this)*tr );
+			else
+				operator=( tr*(*this) );
+		}
+
+		void RotateZ(float angle, int mode=MATRIX_OBJECT_SPACE){
+			TMatrix tr;
+			tr.LoadRotationZMatrix(angle);
+			if (mode==MATRIX_OBJECT_SPACE)
+				operator=( (*this)*tr );
+			else
+				operator=( tr*(*this) );
+		}
+
+		void RotateAxis(float angle, Vector axis, int mode=MATRIX_OBJECT_SPACE){
+			TMatrix Rx,Ry,Rz,iRx,iRy;
+			float d = (float)sqrt(axis.y*axis.y + axis.z*axis.z);
+
+			Rx.SetBaseX(1.0f, 0.0f, 0.0f);
+			Rx.SetBaseY(0.0f, axis.z/d, axis.y/d);
+			Rx.SetBaseZ(0.0f, -axis.y/d, axis.z/d);			
+			
+			Ry.SetBaseX(d, 0.0f, axis.x);
+			Ry.SetBaseY(0.0f, 1.0f, 0.0f);
+			Ry.SetBaseZ(-axis.x, 0.0f, d);
+
+			Rz.LoadRotationZMatrix(angle);
+
+			iRx = Rx;	iRx.Traspose();
+			iRy = Ry;	iRy.Traspose();
+			
+			TMatrix accum;
+			accum.LoadIdentity();
+			if (d!=0)
+				accum = accum * iRx;
+			accum = accum * iRy;
+			accum = accum * Rz;
+			accum = accum * Ry;
+			if (d!=0)
+				accum = accum * Rx;
+
+			if (mode==MATRIX_OBJECT_SPACE)
+				operator=( (*this)*accum );
+			else
+				operator=( accum*(*this) );
+		}
+
+		void Translate(Vector tv, int mode=MATRIX_OBJECT_SPACE){
+			TMatrix tr;
+			tr.col[3]=tv;
+			if (mode==MATRIX_OBJECT_SPACE)
+				operator=( (*this)*tr );
+			else
+				operator=( tr*(*this) );
+		}
+
+		void Scale(Vector sv, int mode=MATRIX_OBJECT_SPACE){
+			if (mode==MATRIX_OBJECT_SPACE)
+				operator=( (*this)*ScaleMatrix(sv) );
+			else
+				operator=( ScaleMatrix(sv)*(*this) );			
+		}
+
+		static TMatrix ScaleMatrix(const Vector &v){
+			TMatrix mat;
+			mat[0].x = v.x;
+			mat[1].y = v.y;
+			mat[2].z = v.z;
+			return mat;
+		}
+
+		static TMatrix TranslationMatrix(const Vector &v){
+			TMatrix mat;
+			mat[3] = v;
+			mat[3].w = 1.0f;
+			return mat;
+		}
+		
+
+		void Traspose(void){
+			tempmat[0]=col[0][0];
+			tempmat[1]=col[0][1];
+			tempmat[2]=col[0][2];
+			tempmat[3]=col[0][3];
+
+			tempmat[4]=col[1][0];
+			tempmat[5]=col[1][1];
+			tempmat[6]=col[1][2];
+			tempmat[7]=col[1][3];
+
+			tempmat[8]=col[2][0];
+			tempmat[9]=col[2][1];
+			tempmat[10]=col[2][2];
+			tempmat[11]=col[2][3];
+
+			tempmat[12]=col[3][0];
+			tempmat[13]=col[3][1];
+			tempmat[14]=col[3][2];
+			tempmat[15]=col[3][3];
+
+			col[0].x=tempmat[0];  col[1].x=tempmat[1];  col[2].x=tempmat[2];  col[3].x=tempmat[3];
+			col[0].y=tempmat[4];  col[1].y=tempmat[5];  col[2].y=tempmat[6];  col[3].y=tempmat[7];
+			col[0].z=tempmat[8];  col[1].z=tempmat[9];  col[2].z=tempmat[10]; col[3].z=tempmat[11];
+			col[0].w=tempmat[12]; col[1].w=tempmat[13]; col[2].w=tempmat[14]; col[3].w=tempmat[15];
+		}
+
+		// This function inverts a (only) TRANSFORM Matrix. This should not work on arbitrary matrices
+		void Invert(void){
+			tempmat[0]=col[0][0];
+			tempmat[1]=col[0][1];
+			tempmat[2]=col[0][2];
+			tempmat[3]=0.0f;
+
+			tempmat[4]=col[1][0];
+			tempmat[5]=col[1][1];
+			tempmat[6]=col[1][2];
+			tempmat[7]=0.0f;
+
+			tempmat[8]=col[2][0];
+			tempmat[9]=col[2][1];
+			tempmat[10]=col[2][2];
+			tempmat[11]=0.0f;
+
+			tempmat[12]=-(col[3][0]*col[0][0])-(col[3][1]*col[0][1])-(col[3][2]*col[0][2]);
+			tempmat[13]=-(col[3][0]*col[1][0])-(col[3][1]*col[1][1])-(col[3][2]*col[1][2]);
+			tempmat[14]=-(col[3][0]*col[2][0])-(col[3][1]*col[2][1])-(col[3][2]*col[2][2]);
+			tempmat[15]=1.0f;
+
+			col[0].x=tempmat[0];  col[1].x=tempmat[1];  col[2].x=tempmat[2];	col[3].x=tempmat[12];
+			col[0].y=tempmat[4];  col[1].y=tempmat[5];  col[2].y=tempmat[6];	col[3].y=tempmat[13];
+			col[0].z=tempmat[8];  col[1].z=tempmat[9];  col[2].z=tempmat[10];	col[3].z=tempmat[14];
+			col[0].w=0.0f;		  col[1].w=0.0f;		col[2].w=0.0f;			col[3].w=tempmat[15];
+		}
+
+	};
+
+
+
+
+
+
+#endif
+
