Index: GTP/trunk/Lib/Geom/shared/GTGeometry/include/GeoMeshSimpSequence.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/include/GeoMeshSimpSequence.h	(revision 1526)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/include/GeoMeshSimpSequence.h	(revision 2090)
@@ -32,6 +32,6 @@
 	struct	GeoVertex
 	{
-		Index	id;
-		Index	bonefrom;
+		Index		id;
+		Index		bonefrom;
 		Vector3	position;
 		Vector2 texcoord;
@@ -88,5 +88,5 @@
 			void Save(Serializer &s);
 
-			// 'Inserts the mesh name into the meshsimplificationsequence
+			// Inserts the mesh name into the meshsimplificationsequence.
 			void putMeshName(char *);
 
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/include/GeoMeshSimplifier.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/include/GeoMeshSimplifier.h	(revision 1070)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/include/GeoMeshSimplifier.h	(revision 2090)
@@ -2,4 +2,5 @@
 #define __GEO_MESH_SIMPLIFIER__
 
+#include <map>
 #include	<math.h>
 #include	"GeoMesh.h"
@@ -10,17 +11,100 @@
 //#include "SimplificationMethod.h"
 
+using	namespace	Geometry;
+
 namespace Geometry
 {
+
+	//-----------------------------------------------------------------------
+	//	Class for join triangle holes.
+	//-----------------------------------------------------------------------
+	class _coord_
+	{
+		public:
+			float x,y,z;
+			inline _coord_(	float x	=	0.0f,
+					float y	=	0.0f,
+					float z	=	0.0f)
+			{ this->x = x; this->y = y; this->z = z; }
+
+			inline _coord_(const _coord_ &f)
+			{
+				x	=	f.x;
+				y=f.y;
+				z=f.z;
+			}
+
+			inline _coord_ & operator=(const _coord_ &f)
+			{
+				x	=	f.x;
+				y	=	f.y;
+				z	=	f.z;
+
+				return *this;
+			}
+
+			inline bool operator<(const _coord_ &f) const
+			{
+				if (x<f.x-0.0001) return true;
+				if (x>f.x+0.0001) return false;
+				if (y<f.y-0.0001) return true;
+				if (y>f.y+0.0001) return false;
+				if (z<f.z-0.0001) return true;
+				if (z>f.z+0.0001) return false;
+
+				return	false;
+			}
+	};
+
+	//-----------------------------------------------------------------------
+	//	Class tha implements a double-linked map.
+	//-----------------------------------------------------------------------
+	class	EdgesMultimap
+	{
+		private:
+			multimap<int,int>	edges;
+		public:
+			EdgesMultimap();
+			~EdgesMultimap();
+			void	insert(int v1,int v2);
+			void	remove(int v1,int v2);
+			void	contract(int v1,int v2);
+			bool	exists(int v1,int v2);
+	};
+
+	//-----------------------------------------------------------------------
+	//	Class that conserves textures adding new vertices to mesh.
+	//-----------------------------------------------------------------------
+	class	TextureConserver
+	{
+		private:
+			EdgesMultimap			*mEdges;
+			Mesh							*mGeoMesh;
+
+		public:
+			multimap<int,int>	mVertices;
+
+			TextureConserver();
+			~TextureConserver();
+
+			void	JoinVertices(Mesh *mesh);
+
+			MeshSimplificationSequence *
+				WriteRealSimpSeq(MeshSimplificationSequence *simpseq);
+
+			Mesh	*GetMesh();
+	};
+
 	/// Mesh simplificator interface.
 	/** This module is used by both models, general mesh models and the plant and tree models for the trunk and the branches. It contains functions that generate simplified versions of 3D objects made out of triangles. Given a 3D object, this module computes a sequence of geometric transformations that reduce the objects geometric detail while preserving its appearance. For each simplification step, returns a simplification sequence containing the edge to be collapse, the two triangles being removed and the new triangles remapped to the model.\n\n
 
 Inputs:\n
-	- A pointer to the Geometry::Mesh object containing the 3D model to be simplified.
-	.
-    	
+- A pointer to the Geometry::Mesh object containing the 3D model to be simplified.
+.
+
 Outputs:\n
-	-# The simplified mesh, contained in a Geometry::Mesh object.
-	-# Simplification sequence, represented by a Geometry::MeshSimplificationSequence object.
-	*/
+-# The simplified mesh, contained in a Geometry::Mesh object.
+-# Simplification sequence, represented by a Geometry::MeshSimplificationSequence object.
+*/
 
 	class MeshSimplifier
@@ -29,5 +113,5 @@
 			/// Class constructor. Retrieves a pointer to a valid Geometry::Mesh object to simplify.
 			MeshSimplifier(	const Geometry::Mesh	*,
-											Geometry::TIPOFUNC		upb=0);
+					Geometry::TIPOFUNC		upb=0);
 
 			/// Virtual class destructor.
@@ -76,44 +160,61 @@
 	class ViewPointDrivenSimplifier : public MeshSimplifier
 	{
-	private:
-		
-		//	Auxiliar vertex buffer.
-		Geometry::VertexBuffer	*mVB;
-		
-		//	Loads a vmi mesh with a given geometry mesh.
-		VMI::Mesh * initMeshStructure(Geometry::Mesh	*geoMesh);
-
-		//	Loads a geometry mesh with a given vmi mesh.
-		void	loadMesh();
-
-		//	Find vertex in auxiliar vertex buffer.
-		void	findVertex(size_t	submesh, size_t	index);
-		
-		//	Gets the VMI mesh simplification sequence.
-		void	GetMeshSimpSequence();
-
-	public:
-
-		/// Class constructor. Will call Simplifier class constructor.
-		ViewPointDrivenSimplifier(	const Geometry::Mesh 	*geoMesh,
-																Geometry::TIPOFUNC		upb=0);
-
-		/// Class destructor.
-		~ViewPointDrivenSimplifier(void);
-
-		/// Copy constructor
-		//ViewPointDrivenSimplifier(const ViewPointDrivenSimplifier&);
-
-		/// Assignment operator
-		//ViewPointDrivenSimplifier& operator =(const ViewPointDrivenSimplifier&);
-
-		/// Starts the simplification process. Receives as a parameter the LOD factor in a range of [0,1]. Implements the Simplifier::Simplify method to perform an image based simplification.
-		void Simplify(Geometry::Real);
-
-		/// Starts the simplification process. Receives as a parameter the number of vertices of the resulting mesh. Implements the Simplifier::Simplify method to perform an image based simplification.
-		void Simplify(Geometry::uint32);
-
-		// Returns the simplified mesh.
-		//Mesh *GetMesh();
+		private:
+
+			//	Vectors of positions, normals and texture coordinates.
+			vector<Vector3>	vPositions;
+			vector<Vector3>	vNormals;
+			vector<Vector2>	vTexCoords;
+
+			//	Auxiliar vertex buffer.
+			Geometry::VertexBuffer	*mVB;
+
+			//	Set of indices.
+			map<int,int>	mIndexMap;
+
+			//	Join and split vertices to matain texture aspect.
+			TextureConserver	*mTexConserver;
+
+			//	Loads a vmi mesh with a given geometry mesh.
+			VMI::Mesh * initMeshStructure(Geometry::Mesh	*geoMesh);
+
+			//	Loads a geometry mesh with a given vmi mesh.
+			void	loadMesh();
+
+			//	Find vertex in auxiliar vertex buffer.
+			void	findVertex(size_t	submesh, size_t	index);
+
+			//	Gets the VMI mesh simplification sequence.
+			void	GetMeshSimpSequence();
+
+			//	Fill up vectors of positions, normals and texture coordinates.
+			void	fillUpPosNorTC(Mesh	*geoMesh);
+
+			//	Reassigns bones.
+			void bonesReassignament();
+
+		public:
+
+			/// Class constructor. Will call Simplifier class constructor.
+			ViewPointDrivenSimplifier(	const Geometry::Mesh 	*geoMesh,
+					Geometry::TIPOFUNC		upb=0);
+
+			/// Class destructor.
+			~ViewPointDrivenSimplifier(void);
+
+			/// Copy constructor
+			//ViewPointDrivenSimplifier(const ViewPointDrivenSimplifier&);
+
+			/// Assignment operator
+			//ViewPointDrivenSimplifier& operator =(const ViewPointDrivenSimplifier&);
+
+			/// Starts the simplification process. Receives as a parameter the LOD factor in a range of [0,1]. Implements the Simplifier::Simplify method to perform an image based simplification.
+			void Simplify(Geometry::Real);
+
+			/// Starts the simplification process. Receives as a parameter the number of vertices of the resulting mesh. Implements the Simplifier::Simplify method to perform an image based simplification.
+			void Simplify(Geometry::uint32);
+
+			// Returns the simplified mesh.
+			//Mesh *GetMesh();
 	};
 
@@ -122,23 +223,23 @@
 	class GeometryBasedSimplifier : public MeshSimplifier
 	{
-	public:
-		/// Class constructor. Will call Simplifier class constructor.
-		GeometryBasedSimplifier(	const Geometry::Mesh	*geoMesh,
-															Geometry::TIPOFUNC		upb=0);
-
-		/// Class destructor.
-		~GeometryBasedSimplifier(void);
-
-		/// Copy constructor
-		//GeometryBasedSimplifier(const GeometryBasedSimplifier&);
-
-		/// Assignment operator
-		//GeometryBasedSimplifier& operator =(const GeometryBasedSimplifier&);
-
-		/// Starts the simplification process. Receives as a parameter the LOD factor in a range of [0,1]. Implements the Simplifier::Simplify method to perform an image based simplification.
-		void Simplify(Geometry::Real);
-
-		/// Starts the simplification process. Receives as a parameter the number of vertices of the resulting mesh. Implements the Simplifier::Simplify method to perform an image based simplification.
-		void Simplify(Geometry::uint32);
+		public:
+			/// Class constructor. Will call Simplifier class constructor.
+			GeometryBasedSimplifier(	const Geometry::Mesh	*geoMesh,
+					Geometry::TIPOFUNC		upb=0);
+
+			/// Class destructor.
+			~GeometryBasedSimplifier(void);
+
+			/// Copy constructor
+			//GeometryBasedSimplifier(const GeometryBasedSimplifier&);
+
+			/// Assignment operator
+			//GeometryBasedSimplifier& operator =(const GeometryBasedSimplifier&);
+
+			/// Starts the simplification process. Receives as a parameter the LOD factor in a range of [0,1]. Implements the Simplifier::Simplify method to perform an image based simplification.
+			void Simplify(Geometry::Real);
+
+			/// Starts the simplification process. Receives as a parameter the number of vertices of the resulting mesh. Implements the Simplifier::Simplify method to perform an image based simplification.
+			void Simplify(Geometry::uint32);
 	};
 } // end of Geometry namespace;
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/gfx/tools/Buffer.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/gfx/tools/Buffer.h	(revision 1526)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/gfx/tools/Buffer.h	(revision 2090)
@@ -32,5 +32,7 @@
 	{
 		if( fill == len )
-		resize( len*2 );
+		{
+			resize( len*2 );
+		}
 
 		data[fill] = t;
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/mesh.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/mesh.h	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/mesh.h	(revision 2090)
@@ -11,4 +11,5 @@
     GLuint *triangles;   // List of triangles
     int enable;
+		int	movable;	//	If vertex is part of a border.
 } Vertex;
 
@@ -22,4 +23,5 @@
 typedef struct _Triangle {
     GLuint		id;         // Triangle id
+    GLuint  group;        // Triangle group
 		GLuint		submesh;		// Triangle submesh	
     GLuint		indices[3]; // Triangle vertices
@@ -45,5 +47,7 @@
 extern void computeTriangleNormal(Vertex *vertices, Triangle *t);
 
+extern Vertex *addVertex(Vertex *list, int *n, float x, float y, float z, int *pos);
 extern int findEdge(Edge *e, GLuint num, GLuint _u, GLuint _v);
+extern Edge *addEdge(Edge *list, int *n, int u, int v, int *pos);
 extern GLboolean findVertex(GLfloat *vertices, GLuint num, GLfloat x, GLfloat y, GLfloat z, int *pos);
 
@@ -55,12 +59,13 @@
 
 extern int *trianglesAdjToEdge(Mesh *mesh, int e, int *n);
-extern int *trianglesAdjToVertex(Mesh *mesh, int v, int *n);
 extern int *verticesAdjToVertex(Mesh *mesh, int v, int *n);
 extern int *edgesAdjToVertex(Mesh *mesh, int v, int *n);
 extern int *edgesAdjToVertices(Mesh *mesh, int *vertices, int numVertices, int *n);
 
+// list of integers
 extern void printItemList(int *list, int n);
 extern int findItem(int *list, int n, int item);
 extern void addItem(int *list, int *n, int item);
+extern void delItem(int *list, int *n, int item);
 
 
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/simplify.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/simplify.h	(revision 1007)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/simplify.h	(revision 2090)
@@ -7,21 +7,75 @@
 #include "bheap.h"
 
+#include	<map>
+
+using	namespace	std;
+
 namespace	VMI
 {
-extern GLdouble computeEdgeCost(Mesh *mesh, int e);
+	extern GLdouble computeEdgeCost(Mesh *mesh, int e);
 
-extern bheap_t *initHeap(Mesh *mesh);
+	extern bheap_t *initHeap(Mesh *mesh);
 
-extern bheap_t *updateHeap(bheap_t *h, Mesh *mesh, Change *c);
+	extern bheap_t *updateHeap(bheap_t *h, Mesh *mesh, Change *c);
 
-extern void simplifyModel(Mesh *mesh, GLuint numDemandedTri);
+	extern void simplifyModel(Mesh *mesh, GLuint numDemandedTri);
 
 
-extern void bh_mydump(Mesh *mesh, bheap_t *h);
-extern GLdouble computeEdgeLength(Vertex *vertices, int u, int v);
+	extern void bh_mydump(Mesh *mesh, bheap_t *h);
+	extern GLdouble computeEdgeLength(Vertex *vertices, int u, int v);
 
-extern void swap(unsigned int *i, unsigned int *j);
-extern void chooseBestEndPoints(Mesh *mesh, int e);
+	extern void chooseBestEndPoints(Mesh *mesh, int e);
 
+	extern void	initVertexMultimap(	Mesh *mesh,
+																	multimap<int,int> &vertexMultimap);
+	/////////////////////////////////////////////////////////////////////////////
+	//	Coordinates class.
+	/////////////////////////////////////////////////////////////////////////////
+	class _float3_
+	{
+		public:
+
+			float x,y,z;
+
+			_float3_(float x=0.0f, float y=0.0f, float z=0.0f)
+			{
+				this->x = x; this->y = y; this->z = z;
+			}
+
+			_float3_(const _float3_ &f)
+			{
+				x=f.x; y=f.y; z=f.z;
+			}
+
+			_float3_ & operator=(const _float3_ &f)
+			{
+				x=f.x; y=f.y; z=f.z; return *this;
+			}
+
+			bool operator<(const _float3_ &f) const
+			{
+				if (x<f.x) return true;
+				if (x>f.x) return false;
+				if (y<f.y) return true;
+				if (y>f.y) return false;
+				if (z<f.z) return true;
+				if (z>f.z) return false;
+				return false;
+			}
+	};
+
+	extern int extractValidEdge(Mesh *mesh,	bheap_t *h);
+
+	extern int	isValidEdge(Mesh	*mesh,	int edge);
+
+	void	deleteVertexOfMap(Mesh	*mesh, int u);
+	bool	compareVertices(Vertex *vertices,int	u,	int v);
+	void	contractInitialMesh(Mesh	*mesh);
+	void	contractTwinVertices(Mesh	*mesh,	int	u,	int	v);
+
+	//	Vectors of positions, normals and texture coordinates.
+	extern	vector<Geometry::Vector3>	vPositions;
+	extern	vector<Geometry::Vector3>	vNormals;
+	extern	vector<Geometry::Vector2>	vTexCoords;
 }
 
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/histogram.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/histogram.h	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/histogram.h	(revision 2090)
@@ -20,8 +20,10 @@
 extern void printFullHistogram(GLuint **histogram, GLuint numCameras, GLuint numTriangles);
 extern void getSWHistogram(GLuint *histogram, GLubyte *pixels);
+extern void getSWHistogramWin(GLuint *histogram, GLubyte *pixels, GLfloat min[3], GLfloat max[3], Change *c);
 extern void getSWHistoByOcclusionQuery(Mesh *mesh, Color *colors, GLuint *histogram);
 
 extern void resetSWHistogram(GLuint *histogram, GLuint numTriangles);
-
+extern void getBoundingBox(Change *c, GLfloat min[3], GLfloat max[3]);
+extern void getWindow(GLfloat min[3], GLfloat max[3], int minw[2], int maxw[2]);
 }
 
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/interleave.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/interleave.h	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/interleave.h	(revision 2090)
@@ -20,4 +20,5 @@
     GLfloat x, y, z;    // position
 } Vertex_;
+extern GLuint vertex_buf, color_buf;
 
 extern void setupInterleave(Mesh *mesh, Color *colors);
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/global.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/global.h	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/global.h	(revision 2090)
@@ -8,4 +8,5 @@
 #include "mesh.h"
 #include "color.h"
+#include "change.h"
 
 //	For progress update.
@@ -58,4 +59,20 @@
 
 //#define SALIENCY
+
+// Extension added into the filename
+#ifdef KL // Kullback-Leibler
+#define EXT "VKL"
+#endif
+#ifdef MI // Mutual Information
+#define EXT "VMI"
+#endif
+#ifdef HE // Hellinger
+#define EXT "VHE"
+#endif
+#ifdef CS // Chi-Square
+#define EXT "VCS"
+#endif
+
+//#define USE_EDGE_ADJACENCY
 
 #define CHECK_OPENGL_ERROR( cmd ) \
@@ -110,5 +127,6 @@
                  bEnableOffScreen,
                  bSaveLog,
-                 bLoadCamerasFromFile;
+                 bLoadCamerasFromFile,
+								 bRemoveRedundantVertices;
 
 extern GLsizei width, height;
@@ -121,4 +139,5 @@
 
 extern void renderScene(GLuint **histogram, GLuint numCameras);
+extern void renderSceneWin(GLuint **histogram, GLuint numCameras, Change *c);
 
 extern void renderGeometry(void);
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/metrics.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/metrics.h	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/metrics.h	(revision 2090)
@@ -8,11 +8,13 @@
 namespace	VMI
 {
-extern GLuint computeBackgroundArea(Mesh *mesh, GLuint *histogram);
-extern GLdouble computeMeanProjArea(GLuint **histogram, GLuint numCameras, int t);
 extern GLdouble computeMI(Mesh *mesh, GLuint **histogram, GLuint numCameras, GLuint cam);
+extern GLdouble decMI(GLdouble I, GLuint **histogram, GLuint numCameras, GLuint cam, Change *c);
+extern GLdouble incMI(GLdouble I, GLuint **histogram, GLuint numCameras, GLuint cam, Change *c);
+
 extern GLdouble computeHE(Mesh *mesh, GLuint *histogram);
 extern GLdouble computeKL(Mesh *mesh, GLuint *histogram);
 extern GLdouble computeCS(Mesh *mesh, GLuint *histogram);
 
+extern GLdouble computeMeanProjArea(GLuint **histogram, GLuint numCameras, int t);
 extern GLdouble computeJS(GLuint **histogram, GLuint numCameras, GLuint j, GLuint k);
 extern GLdouble computeEntropy(GLuint **histogram, GLuint numCameras, GLuint k);
@@ -21,4 +23,5 @@
 
 extern void getProjectedAreas(GLuint **histogram, GLuint numCameras);
+extern void getProjectedAreasWin(GLuint **histogram, GLuint numCameras, Change *c);
 extern void resetProjectedAreas(GLuint **histogram, GLuint numCameras);
 
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/saliency.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/saliency.h	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/saliency.h	(revision 2090)
@@ -14,4 +14,5 @@
 
 extern void computeSaliency(Mesh *mesh, GLuint **histogram, GLuint numCameras);
+extern void updateTriangleSaliency(Mesh *mesh, GLuint **histogram, GLuint numCameras, int v);
 
 extern double computeTriangleSaliency(Mesh *mesh, GLuint **histogram, GLuint numCameras, GLuint k);
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/area.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/area.h	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/area.h	(revision 2090)
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/color.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/color.h	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/color.h	(revision 2090)
@@ -14,11 +14,11 @@
 } Color;
 
-extern Color *initColors(GLuint numTriangles);
-extern void fillAllColors(Color *colors, GLuint numTriangles, GLuint begin, GLuint end, GLubyte color);
+extern Color *initColors(GLuint numColors);
+extern void fillAllColors(Color *colors, GLuint numColors, GLuint begin, GLuint end, GLubyte color);
 extern void setColors(Color *colors, GLuint numPasses, GLuint begin, GLuint end);
-extern void setColors2(Color *colors, GLuint numTriangles, GLuint begin, GLuint end);
-extern void setColors3(Color *colors, GLuint numTriangles, GLubyte color);
-extern void setColors4(Color *colors, GLuint numTriangles);
-extern void viewColors(Color *colors, GLuint numTriangles);
+extern void setColors2(Color *colors, GLuint numColors, GLuint begin, GLuint end);
+extern void setColors3(Color *colors, GLuint numColors, GLubyte color);
+extern void setColors4(Color *colors, GLuint numColors);
+extern void viewColors(Color *colors, GLuint numColors);
 
 }
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/bheap.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/bheap.h	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/bheap.h	(revision 2090)
@@ -15,10 +15,11 @@
  */
 typedef struct {
-    int item;  /* vertex number is used for the item. */
+    int dirty;  /* dirty flag if used for the lazy evaluation */
+    int item;  /* edge number is used for the item. */
     double key;  /* distance is used as the key. */
 } bheap_item_t;
 
 /* Binary heap structure for frontier set in Dijkstra's algorithm.
- * a[] - stores (distance, vertex) pairs of the binary heap.
+ * a[] - stores (distance, edge) pairs of the binary heap.
  * p[] - stores the positions of vertices in the binary heap a[].
  * n - is the size of the binary heap.
@@ -58,4 +59,17 @@
  */
 void bh_delete(bheap_t *h, int item);
+/* bh_mark() marks an item from the binary heap pointed to by h.
+ */
+void bh_mark(bheap_t *h, int item, int flag);
+
+/* bh_get_key() returns the key value of an item from the binary heap pointed 
+ * to by h.
+ */
+double bh_get_key(bheap_t *h, int item);
+
+/* bh_is_dirty() returns the dirty value of an item from the binary heap pointed
+ * to by h.
+ */
+int bh_is_dirty(bheap_t *h, int item);
 
 /* bh_decrease_key() decreases the value of 'item's key and then performs
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/change.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/change.h	(revision 1024)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/change.h	(revision 2090)
@@ -5,4 +5,5 @@
 #include	<vector>
 #include	<map>
+#include	<GeoMeshSimpSequence.h>
 
 namespace	VMI
@@ -20,4 +21,5 @@
 	} Change;
 
+	/*
 	// Represents a simplification step in the sequence.
 	struct vmiStep
@@ -41,5 +43,23 @@
 	extern	std::vector<vmiStep> mVMISteps;
 
+	//	Vertex info.
+	struct	GeoVertex
+	{
+		Index		id;
+		Index		bonefrom;
+		Vector3	position;
+		Vector2 texcoord;
+		Vector3 normal;
+	};
+
+	//	Vertices added in simplification.
+	std::vector<GeoVertex>	mNewVertices;
+	*/
+
+	// Stores all the simplification steps.
+	extern	Geometry::MeshSimplificationSequence *mSequence;
+
 	extern Change *createChange (Mesh *mesh, int e);
+	extern Change *newChange (Mesh *mesh, int u, int v);
 	extern void writeChange(FILE* file, Change *c);
 	extern void deleteChange(Change *c);
@@ -47,8 +67,8 @@
 
 	extern void modifyTriangle(Triangle *t, int c, int p);
-	extern int isATriangleToModify(Triangle *t, int c, int p);
-	extern int getTrianglesToModify(Mesh *mesh, int c, int p, Triangle *modified);
+	extern int isATriangleToModify(Triangle *t, int c);
+	extern Triangle *getTrianglesToModify(Mesh *mesh, Change *c, GLuint *numMod);
 	extern int isATriangleToDelete(Triangle *t, int c, int p);
-	extern int getTrianglesToDelete(Mesh *mesh, int numMod, Triangle *modified, Triangle *deleted, int c, int p);
+	extern Triangle *getTrianglesToDelete(Mesh *mesh, Change *c, GLuint *numDel);
 
 	extern void modifyTriangles(Mesh *mesh, Change *c);
@@ -62,11 +82,16 @@
 	extern void doChange(Mesh *mesh, Change *c);
 	extern void undoChange(Mesh *mesh, Change *c);
-	extern void computeChanges(Mesh *mesh, Change *c);
+	extern void computeChange(Mesh *mesh, Change *c);
+
+	extern void modifyEdges(Mesh *mesh, Change *c);
+  extern void deleteEdges(Mesh *mesh, Change *c);
 
 	//	Save simplification sequence in Geometry Game Tools format.
-	extern void	saveSimplificationSequence(Change	*c);
+	extern void	saveSimplificationSequence(Change	*c, int obligatory);
 
-	extern std::map<int, INTVECTOR> inversemap;
+	//extern std::map<int, INTVECTOR> inversemap;
+	extern void swap(int *i, int *j);
+	extern int hasEdge(Triangle *t, int e);
+	extern void getEdges(Triangle *t, Change *c, int *d, int *a);
 }
-
 #endif
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/camera.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/camera.h	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/include/camera.h	(revision 2090)
@@ -5,4 +5,5 @@
 
 #define OCTAHEDRON     6  // number of vertices
+#define CUBE           8
 #define ICOSAHEDRON   12
 #define DODECAHEDRON  20
@@ -26,4 +27,5 @@
 extern void drawSphere(Camera *cameras, GLdouble radius, int slices, int stacks);
 extern void drawOctahedron(Camera *cameras, GLdouble r);
+extern void drawCube(Camera *cameras, GLdouble r);
 extern void drawIcosahedron(Camera *cameras, GLdouble r);
 extern void drawDodecahedron(Camera *cameras, GLdouble r);
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/interleave.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/interleave.cpp	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/interleave.cpp	(revision 2090)
@@ -17,5 +17,5 @@
 static Color   *buf_colors = NULL;
 
-static GLuint vertex_buf = 0,
+GLuint vertex_buf = 0,
        color_buf = 0;
 }
@@ -100,17 +100,7 @@
     setupVertexArray(mesh, colors);
     
-    // Disable the vertex array functionality:
-    glDisableClientState(GL_VERTEX_ARRAY);
-    glDisableClientState(GL_COLOR_ARRAY);
-    
-    glDeleteBuffersARB(1, &vertex_buf);
-    
-    glGenBuffersARB(1, &vertex_buf);
     glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertex_buf);
     glBufferDataARB(GL_ARRAY_BUFFER_ARB, mesh->currentNumTriangles * 3 * 3 * sizeof(float), buf_vertices, GL_STATIC_DRAW_ARB); //upload data
     
-    glDeleteBuffersARB(1, &color_buf);
-    
-    glGenBuffersARB(1, &color_buf);
     glBindBufferARB(GL_ARRAY_BUFFER_ARB, color_buf);
     glBufferDataARB(GL_ARRAY_BUFFER_ARB, mesh->currentNumTriangles * 3 * sizeof(Color), buf_colors, GL_STATIC_DRAW_ARB); //upload data
@@ -182,10 +172,4 @@
     updateVertexArray(mesh);
     
-    // Disable the vertex array functionality:
-    glDisableClientState(GL_VERTEX_ARRAY);
-    
-    glDeleteBuffersARB(1, &vertex_buf);
-    
-    glGenBuffersARB(1, &vertex_buf);
     glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertex_buf);
     glBufferDataARB(GL_ARRAY_BUFFER_ARB, mesh->currentNumTriangles * 3 * 3 * sizeof(float), buf_vertices, GL_STATIC_DRAW_ARB); //upload data
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/metrics.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/metrics.cpp	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/metrics.cpp	(revision 2090)
@@ -13,16 +13,4 @@
 using namespace	VMI;
 
-GLuint VMI::computeBackgroundArea(Mesh *mesh, GLuint *histogram) {
-    GLuint i, area = 0;
-
-    for (i=0; i<mesh->numTriangles; i++) { // Triangles start at 1
-        if (mesh->triangles[i].enable == TRUE) {
-            area += histogram[i + 1];
-        }
-    }
-
-    return ((GLuint)(width * height) - area);
-}
-
 GLdouble VMI::computeMeanProjAreaNoBG(GLuint **histogram, GLuint numCameras, int t) {
     GLuint i;
@@ -37,15 +25,16 @@
 
 GLdouble VMI::computeMeanProjArea(GLuint **histogram, GLuint numCameras, int t) {
-    GLuint i;
-    GLdouble mean_proj_area = 0.0, total_proj_area, resolution = width * height;
-
-    for (i=0; i<numCameras; i++) {
+	GLuint i;
+	GLdouble mean_proj_area = 0.0, total_proj_area, resolution = width * height;
+
+	for (i=0; i<numCameras; i++) {
 		total_proj_area = resolution - histogram[i][0];
 
-        mean_proj_area += histogram[i][t] / total_proj_area;
-    }
-
-    return (mean_proj_area / (GLdouble)numCameras);
-}
+		mean_proj_area += histogram[i][t] / total_proj_area;
+	}
+
+	return (mean_proj_area / (GLdouble)numCameras);
+}
+///////////////////////////////////////////////////////////////////////////////
 // Mutual Information
 GLdouble VMI::computeMI(Mesh *mesh, GLuint **histogram, GLuint numCameras, GLuint cam) {
@@ -76,4 +65,78 @@
     return (I / numCameras);
 }
+
+GLdouble VMI::decMI(GLdouble I, GLuint **histogram, GLuint numCameras, GLuint cam, Change *c) {
+    GLdouble newI = I * numCameras, 
+             pov = 0.0, po;
+    GLsizei total_proj_area = width * height;
+    GLint i, t;
+
+    // decrease entropy of deleted triangles
+    for (i=0; i<c->numDel; i++) { 
+        
+        t = c->deleted[i].id;
+        // projected pixels of triangle t is at t + 1 position
+        pov = (GLdouble)histogram[cam][t + 1] / total_proj_area;
+        
+        po = computeMeanProjAreaNoBG(histogram, numCameras, t + 1) / total_proj_area;
+        
+        if ((pov > 0.0) && (po > 0.0))
+            newI -= (pov * log2(pov / po));
+    }
+
+    // decrease entropy of modified triangles
+    for (i=0; i<c->numMod; i++) { 
+        
+        t = c->modified[i].id;
+        // projected pixels of triangle t is at t + 1 position
+        pov = (GLdouble)histogram[cam][t + 1] / total_proj_area;
+        
+        po = computeMeanProjAreaNoBG(histogram, numCameras, t + 1) / total_proj_area;
+        
+        if ((pov > 0.0) && (po > 0.0))
+            newI -= (pov * log2(pov / po));
+    }
+
+    // take into account the background
+    pov = (GLdouble)histogram[cam][0] / total_proj_area;
+    
+    po = computeMeanProjAreaNoBG(histogram, numCameras, 0) / total_proj_area;
+    
+    if ((pov > 0.0) && (po > 0.0))
+        newI -= (pov * log2(pov / po));
+
+    return (newI / numCameras);
+}
+
+GLdouble VMI::incMI(GLdouble I, GLuint **histogram, GLuint numCameras, GLuint cam, Change *c) {
+    GLdouble newI = I * numCameras, 
+             pov = 0.0, po;
+    GLsizei total_proj_area = width * height;
+    GLuint i, t;
+
+    // increase entropy of modified triangles
+    for (i=0; i<(GLuint)c->numMod; i++) { 
+        
+        t = c->modified[i].id;
+        // projected pixels of triangle t is at t + 1 position
+        pov = (GLdouble)histogram[cam][t + 1] / total_proj_area;
+        
+        po = computeMeanProjAreaNoBG(histogram, numCameras, t + 1) / total_proj_area;
+        
+        if ((pov > 0.0) && (po > 0.0))
+            newI += (pov * log2(pov / po));
+    }
+
+    // take into account the background
+    pov = (GLdouble)histogram[cam][0] / total_proj_area;
+    
+    po = computeMeanProjAreaNoBG(histogram, numCameras, 0) / total_proj_area;
+    
+    if ((pov > 0.0) && (po > 0.0))
+        newI += (pov * log2(pov / po));
+
+    return (newI / numCameras);
+}
+///////////////////////////////////////////////////////////////////////////////
 // Kullback-Leibler divergence
 GLdouble VMI::computeKL(Mesh *mesh, GLuint *histogram) {
@@ -107,5 +170,5 @@
 // Hellinger divergence (square root)
 GLdouble VMI::computeHE(Mesh *mesh, GLuint *histogram) {
-    GLdouble I = 0.0, t, 
+    GLdouble I = 0.0, temp, 
              total_real_area = 0.0, pi, qi;
     GLsizei  total_proj_area = (width * height) - histogram[0];
@@ -128,12 +191,13 @@
             if ((pi > 0.0) && (qi > 0.0)) {
                 
-                t = sqrt(pi) - sqrt(qi);
+                temp = sqrt(pi) - sqrt(qi);
                 
-                I += (t * t);
+                I += (temp * temp);
             }
         }
     }
 
-    return (sqrt(I / 2.0));
+    return sqrt(I / 2.0);
+
 }
 
@@ -168,17 +232,32 @@
 ///////////////////////////////////////////////////////////////////////////////
 GLdouble VMI::computeEntropy(GLuint **histogram, GLuint numCameras, GLuint k) {
-    GLdouble H = 0.0, POk, pi,
-		     total_proj_area, resolution = width * height, pv = 1.0 / (GLdouble)numCameras;
+	GLdouble H = 0.0, POk, pi,
+					 total_proj_area, resolution = width * height, pv = 1.0 / (GLdouble)numCameras;
+	GLuint i;
+
+	for (i=0; i<numCameras; i++) {
+
+		total_proj_area = resolution - histogram[i][0];
+
+		POk = computeMeanProjArea(histogram, numCameras, k + 1);
+
+		if (POk > 0.0)
+			pi = (pv * ((double)histogram[i][k + 1]) / total_proj_area ) / POk;
+		else pi = 0.0;
+
+		if (pi > 0.0)
+			H += (pi * log2(pi));
+	}
+
+	return -H;
+}
+
+GLdouble VMI::computeMixedEntropy(GLdouble *mixed, GLuint numCameras) {
+    GLdouble H = 0.0, pi;
     GLuint i;
     
     for (i=0; i<numCameras; i++) {
-
-		total_proj_area = resolution - histogram[i][0];
-        
-        POk = computeMeanProjArea(histogram, numCameras, k + 1);
-        
-        if (POk > 0.0)
-            pi = (pv * ((double)histogram[i][k + 1]) / total_proj_area ) / POk;
-        else pi = 0.0;
+        
+        pi = mixed[i];
         
         if (pi > 0.0)
@@ -188,61 +267,46 @@
     return -H;
 }
-
-GLdouble VMI::computeMixedEntropy(GLdouble *mixed, GLuint numCameras) {
-    GLdouble H = 0.0, pi;
-    GLuint i;
-    
-    for (i=0; i<numCameras; i++) {
-        
-        pi = mixed[i];
-        
-        if (pi > 0.0)
-            H += (pi * log2(pi));
-    }
-    
-    return -H;
-}
 ///////////////////////////////////////////////////////////////////////////////
 // Jensen-Shannon divergence
 GLdouble VMI::computeJS(GLuint **histogram, GLuint numCameras, GLuint j, GLuint k) {
-    GLdouble js, Wj = 0.0, Wk = 0.0, POj, POk, pj, pk, total_proj_area,
-		     resolution = width * height, pv = 1.0 / (GLdouble)numCameras,
-			 *mixing = (GLdouble *)malloc(numCameras * sizeof(GLdouble));
-    GLuint i;
-    
-    POj = computeMeanProjArea(histogram, numCameras, j + 1);
-    POk = computeMeanProjArea(histogram, numCameras, k + 1);
-
-    //printf("%f %f\n", POj, POk);
-    
-    // weights
-    if ((POj + POk) > 0.0) {
-        Wj = POj / (POj + POk);
-        Wk = POk / (POj + POk);
-    }
-
-    //printf("%f %f\n", Wj, Wk);
-    
-    // Compute mixing distribution
-    for (i=0; i<numCameras; i++) {
-        
+	GLdouble js, Wj = 0.0, Wk = 0.0, POj, POk, pj, pk, total_proj_area,
+					 resolution = width * height, pv = 1.0 / (GLdouble)numCameras,
+					 *mixing = (GLdouble *)malloc(numCameras * sizeof(GLdouble));
+	GLuint i;
+
+	POj = computeMeanProjArea(histogram, numCameras, j + 1);
+	POk = computeMeanProjArea(histogram, numCameras, k + 1);
+
+	//printf("%f %f\n", POj, POk);
+
+	// weights
+	if ((POj + POk) > 0.0) {
+		Wj = POj / (POj + POk);
+		Wk = POk / (POj + POk);
+	}
+
+	//printf("%f %f\n", Wj, Wk);
+
+	// Compute mixing distribution
+	for (i=0; i<numCameras; i++) {
+
 		total_proj_area = resolution - histogram[i][0];
 
-        if (POj > 0.0) pj = (pv * ((double)histogram[i][j + 1] / total_proj_area)) / POj;
-        else pj = 0.0;
-            
-        if (POk > 0.0) pk = (pv * ((double)histogram[i][k + 1] / total_proj_area)) / POk;
-        else pk = 0.0;
-            
-        mixing[i] = (Wj * pj) + (Wk * pk);
-    }
-    
-    js = /*(POj + POk) * */(computeMixedEntropy(mixing, numCameras) 
-		- (Wj * computeEntropy(histogram, numCameras, j)) 
-		- (Wk * computeEntropy(histogram, numCameras, k)));
+		if (POj > 0.0) pj = (pv * ((double)histogram[i][j + 1] / total_proj_area)) / POj;
+		else pj = 0.0;
+
+		if (POk > 0.0) pk = (pv * ((double)histogram[i][k + 1] / total_proj_area)) / POk;
+		else pk = 0.0;
+
+		mixing[i] = (Wj * pj) + (Wk * pk);
+	}
+
+	js = /*(POj + POk) * */(computeMixedEntropy(mixing, numCameras) 
+			- (Wj * computeEntropy(histogram, numCameras, j)) 
+			- (Wk * computeEntropy(histogram, numCameras, k)));
 
 	free(mixing);
 
-    return js;
+	return js;
 }
 ///////////////////////////////////////////////////////////////////////////////
@@ -250,4 +314,9 @@
 
     renderScene(histogram, numCameras);
+}
+
+void VMI::getProjectedAreasWin(GLuint **histogram, GLuint numCameras, Change *c) {
+
+    renderSceneWin(histogram, numCameras, c);
 }
 
@@ -301,5 +370,5 @@
     meanI /= numCameras;
 #endif
-    printIs(mis, numCameras);
+    //printIs(mis, numCameras);
     printf("I0= %f\n", meanI); 
 }
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/saliency.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/saliency.cpp	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/saliency.cpp	(revision 2090)
@@ -23,30 +23,41 @@
 
 void VMI::computeSaliency(Mesh *mesh, GLuint **histogram, GLuint numCameras) {
-    GLuint i = 0;
-    double sal;
-    
-    maxSal = minSal = computeTriangleSaliency(mesh, histogram, numCameras, 0);
-
-    mesh->triangles[0].saliency = maxSal;
-
-    for (i=1; i<mesh->numTriangles; i++) {
-
-        sal = computeTriangleSaliency(mesh, histogram, numCameras, i);
-
-        if (sal > maxSal) maxSal = sal;
-        if (sal < minSal) minSal = sal;
-        
-        mesh->triangles[i].saliency = sal;
-    }
-
-    printf("\nMax Sal: %f  Min Sal: %f\n", maxSal, minSal);
-
-    percentile = computePercentile(alpha, mesh->triangles, mesh->numTriangles);
-    printf("\n%dth percentile: %f\n", alpha, percentile);
+	GLuint i = 0;
+	double sal;
+
+	maxSal = minSal = computeTriangleSaliency(mesh, histogram, numCameras, 0);
+
+	mesh->triangles[0].saliency = maxSal;
+
+	for (i=1; i<mesh->numTriangles; i++) {
+
+		sal = computeTriangleSaliency(mesh, histogram, numCameras, i);
+
+		if (sal > maxSal) maxSal = sal;
+		if (sal < minSal) minSal = sal;
+
+		mesh->triangles[i].saliency = sal;
+	}
+
+	printf("\nMax Sal: %f  Min Sal: %f\n", maxSal, minSal);
+
+	percentile = computePercentile(alpha, mesh->triangles, mesh->numTriangles);
+	printf("\n%dth percentile: %f\n", alpha, percentile);
+}
+
+void updateTriangleSaliency(Mesh *mesh, GLuint **histogram, GLuint numCameras, int v) {
+	int i, t;
+
+	for(i=0; i<(int)mesh->vertices[v].numTriangles; i++) {
+
+		t = mesh->vertices[v].triangles[i];
+
+		mesh->triangles[t].saliency = computeTriangleSaliency(mesh, histogram, numCameras, t);
+	}
 }
 
 double VMI::computeTriangleSaliency(Mesh *mesh, GLuint **histogram, GLuint numCameras, GLuint k) {
-    GLuint i, l, v0, v1, v2;
-    int triangles[MAX_NUM_TRI], n = 0;
+     GLuint i, l, v0, v1, v2;
+    int *triangles = NULL, n = 0;
     double sal = 0.0;
     
@@ -55,4 +66,9 @@
     v2 = mesh->triangles[k].indices[2];
     
+    /* Allocating memory */
+    triangles = (int *)malloc((mesh->vertices[v0].numTriangles +
+                               mesh->vertices[v1].numTriangles +
+                               mesh->vertices[v2].numTriangles) * sizeof(int));
+
     for(i=0; i<mesh->vertices[v0].numTriangles; i++) {
         l = mesh->vertices[v0].triangles[i];
@@ -86,4 +102,6 @@
     //getchar();
     
+    free(triangles);
+
     return (sal /*/ n*/);
 }
@@ -150,5 +168,6 @@
     if((fp= fopen(filename, "rt"))== NULL) {
         printf("Can't open file %s\n", filename);
-        exit(1);
+				getchar();
+				exit(1);
     }
 
@@ -219,35 +238,37 @@
 void VMI::computeRGB(double min, double max,double value,float *r,float *g,float *b)
 {
-    //Dados el valor máximo, el mínimo y el valor que le quieres calcular el color te devuelve el respectivo RGB.
-    if(value>max) value=max;
-    if(value<min) value=min;
-    
-    if(max==min) value=1;
-    else value=(float)(value-min)/(float)(max-min);
-    
-    if (value<=0.25)
-    {
-        (*r)=0;
-        (*g)=4*value;
-        (*b)=1;
-    }
-    else if (value<=0.50)
-    {
-        (*r)=0;
-        (*g)=1;
-        (*b)=2-4*value;
-    }
-    else if (value<=0.75)
-    {
-        (*r)=4*value-2;
-        (*g)=1;
-        (*b)=0;
-    }
-    else
-    {
-        (*r)=1;
-        (*g)=4-4*value;
-        (*b)=0;
-    }
+	/* Given the maximum, the minimum value and the demanded color value returns
+	 * the respective RGB color
+	 */
+	if(value>max) value=max;
+	if(value<min) value=min;
+
+	if(max==min) value=1;
+	else value=(float)(value-min)/(float)(max-min);
+
+	if (value<=0.25)
+	{
+		(*r)=0;
+		(*g)=4*value;
+		(*b)=1;
+	}
+	else if (value<=0.50)
+	{
+		(*r)=0;
+		(*g)=1;
+		(*b)=2-4*value;
+	}
+	else if (value<=0.75)
+	{
+		(*r)=4*value-2;
+		(*g)=1;
+		(*b)=0;
+	}
+	else
+	{
+		(*r)=1;
+		(*g)=4-4*value;
+		(*b)=0;
+	}
 }
 
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/color.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/color.cpp	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/color.cpp	(revision 2090)
@@ -7,8 +7,10 @@
 using namespace VMI;
 
-Color *VMI::initColors(GLuint numTriangles) {
+Color *VMI::initColors(GLuint numColors) {
     Color *colors;
 
-    colors = (Color *)malloc(sizeof(Color) * (numTriangles + 1)); // Triangles start at 1
+    colors = (Color *)malloc(sizeof(Color) * (numColors + 1));
+		/* The 0 position is reserved for the BACKGROUND, thus color of triangle 0
+       is at 1 position and so on */
 
     if (colors == NULL) {
@@ -17,14 +19,14 @@
     }
 
-    // Fill the color buffer with BACKGROUND
-    memset(colors, BACKGROUND, sizeof(Color) * (numTriangles + 1));
+    /* Fill the color buffer with the BACKGROUND color */
+    memset(colors, BACKGROUND, sizeof(Color) * (numColors + 1));
 
     return colors;
 }
 
-void VMI::fillAllColors(Color *colors, GLuint numTriangles, GLuint begin, GLuint end, GLubyte color) {
+void VMI::fillAllColors(Color *colors, GLuint numColors, GLuint begin, GLuint end, GLubyte color) {
     GLuint i;
 
-    if (end > numTriangles) return;
+    if (end > numColors) return;
 
     for (i=begin; i<end; i++) {
@@ -84,11 +86,11 @@
 }
 
-void VMI::setColors2(Color *colors, GLuint numTriangles, GLuint begin, GLuint end) {
+void VMI::setColors2(Color *colors, GLuint numColors, GLuint begin, GLuint end) {
     GLuint i, 
         channel = 0,
-        step = (numTriangles < MAX_NUM_COLORS) ? (MAX_NUM_COLORS / numTriangles) : 1;
+        step = (numColors < MAX_NUM_COLORS) ? (MAX_NUM_COLORS / numColors) : 1;
     GLubyte r = 1;
 
-    if (end > numTriangles) return;
+    if (end > numColors) return;
 
     for (i = begin; i < end; i++) {
@@ -126,13 +128,13 @@
             channel = 0;
         }
-        //printf("c:%d (%d,%d,%d,%d)\n",i, colors[i].r, colors[i].g, colors[i].b,  colors[i].a);
+        //printf("c:%d (%d,%d,%d,%d)\n", i, colors[i].r, colors[i].g, colors[i].b,  colors[i].a);
         //getchar();
     }
 }
 
-void VMI::setColors3(Color *colors, GLuint numTriangles, GLubyte color) {
+void VMI::setColors3(Color *colors, GLuint numColors, GLubyte color) {
     GLuint i;
     
-    for (i = 0; i < numTriangles; i++) {
+    for (i = 0; i < numColors; i++) {
 
         colors[i].r = color;
@@ -141,13 +143,13 @@
         colors[i].a = 0;
 
-        //printf("c:%d (%d,%d,%d,%d)\n",i, colors[i].r, colors[i].g, colors[i].b,  colors[i].a);
+        //printf("c:%d (%d,%d,%d,%d)\n", i, colors[i].r, colors[i].g, colors[i].b,  colors[i].a);
         //getchar();
     }
 }
 
-void VMI::setColors4(Color *colors, GLuint numTriangles) {
+void VMI::setColors4(Color *colors, GLuint numColors) {
     GLuint i, c = 1;
     
-    for (i = 0; i < numTriangles; i++) {
+    for (i = 0; i < numColors; i++) {
 
         colors[i].r = c & 0xFF;
@@ -156,5 +158,5 @@
         colors[i].a = (c & 0xFF000000) >> 24;
 
-        //printf("c:%d (%d,%d,%d,%d)\n",i, colors[i].r, colors[i].g, colors[i].b,  colors[i].a);
+        //printf("c:%d (%d,%d,%d,%d)\n", i, colors[i].r, colors[i].g, colors[i].b,  colors[i].a);
         c++; 
     }
@@ -162,9 +164,9 @@
 }
 
-void VMI::viewColors(Color *colors, GLuint numTriangles) {
+void VMI::viewColors(Color *colors, GLuint numColors) {
     GLuint i;
 
     printf("\n");
-    for (i=0; i<numTriangles; i++) 
-        printf("c:%d (%d,%d,%d,%d)\n",i, colors[i].r, colors[i].g, colors[i].b,  colors[i].a);
+    for (i=0; i<numColors; i++) 
+        printf("c:%d (%d,%d,%d,%d)\n", i, colors[i].r, colors[i].g, colors[i].b,  colors[i].a);
 }
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/bheap.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/bheap.cpp	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/bheap.cpp	(revision 2090)
@@ -154,4 +154,22 @@
         }
     }
+}
+/* bh_mark() marks an item from the binary heap pointed to by h.
+ */
+void bh_mark(bheap_t *h, int item, int flag)
+{
+    h->a[h->p[item]].dirty = flag;
+}
+/* bh_get_key() returns the key value of an item from the binary heap h.
+ */
+double bh_get_key(bheap_t *h, int item)
+{
+    return h->a[h->p[item]].key;
+}
+/* bh_is_dirty() returns the dirty value of an item from the binary heap h.
+ */
+int bh_is_dirty(bheap_t *h, int item)
+{
+    return h->a[h->p[item]].dirty;
 }
 
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/glm.c
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/glm.c	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/glm.c	(revision 2090)
@@ -135,5 +135,5 @@
     copied = 1;
     for (i = 1; i <= *numvectors; i++) {
-        for (j = 1; j <= copied; j++) {
+        for (j = 1; j </*=*/ copied; j++) {
             if (glmEqual(&vectors[3 * i], &copies[3 * j], epsilon)) {
                 goto duplicate;
@@ -1723,9 +1723,9 @@
     vectors  = model->vertices;
     copies = glmWeldVectors(vectors, &numvectors, epsilon);
-    
-#if 0
+
+//#if 0
     printf("glmWeld(): %d redundant vertices.\n", 
-        model->numvertices - numvectors - 1);
-#endif
+        model->numvertices - numvectors /* - 1*/);
+//#endif
     
     for (i = 0; i < model->numtriangles; i++) {
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/main.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/main.cpp	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/main.cpp	(revision 2090)
@@ -25,5 +25,6 @@
           bBeQuiet         = GL_FALSE,
           bSaveLog         = GL_FALSE,
-          bLoadCamerasFromFile = GL_FALSE;
+          bLoadCamerasFromFile = GL_FALSE,
+          bRemoveRedundantVertices = GL_TRUE;
 
 GLuint cameraType = 0,
@@ -55,6 +56,6 @@
     gluPerspective(fov, (GLdouble)width / height, 0.1, 40.0);
     
-    glPixelStorei(GL_PACK_ALIGNMENT, 1);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    //glPixelStorei(GL_PACK_ALIGNMENT, 1);
+    //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     
     glShadeModel(GL_FLAT);
@@ -62,8 +63,7 @@
     glDisable(GL_BLEND);
 
-    //glEnable(GL_CULL_FACE); // important
+    glEnable(GL_CULL_FACE); // important
 
     glEnable(GL_DEPTH_TEST);
-    glDepthFunc(GL_LEQUAL);
 
     if (GL_TRUE != glewIsSupported((const char*) "GL_EXT_framebuffer_object"))
@@ -117,4 +117,11 @@
     {
         fprintf(stderr,"GL_ARB_vertex_buffer_object extension is not available!\n");
+    } else {
+#ifdef VERTEX_BUFFER_OBJECTS
+        
+        glGenBuffersARB(1, &vertex_buf);
+        
+        glGenBuffersARB(1, &color_buf);
+#endif
     }
     if (GL_TRUE != glewIsSupported((const char*) "GL_ARB_occlusion_query"))
@@ -238,22 +245,15 @@
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-    // Switch to projection mode
-    glMatrixMode(GL_PROJECTION);
-    // Save previous matrix which contains the 
-    // settings for the perspective projection
-    glPushMatrix();
-    // Reset matrix
-    glLoadIdentity();
-    glOrtho(0.0, (GLdouble)width, 0.0, (GLdouble)height, 1.0, 1.0);
-    glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity();
+    setOrthographicProjection();
 
     glEnable(GL_TEXTURE_2D);
     glBindTexture(GL_TEXTURE_2D, color_tex);
     glBegin(GL_QUADS);
-    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 0.0);
-    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 0.0);
-    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, 0.0);
-    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, 0.0);
+    
+    glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
+    glTexCoord2f(1.0f, 0.0f); glVertex2f(width, 0.0f); 
+    glTexCoord2f(1.0f, 1.0f); glVertex2f(width, height);
+    glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, height);
+
     glEnd();
     glFlush();
@@ -312,4 +312,81 @@
     ///////////////////////////////////////////////////////////////////////////
 }
+void VMI::renderSceneWin(GLuint **histogram, GLuint numCameras, Change *c)
+{
+    GLuint i, j, t, background;
+    int del_area, mod_area;
+    GLfloat min[3], max[3];
+
+    // draw to the frame buffer
+    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
+
+    //printChange(c);
+    getBoundingBox(c, min, max);
+    //printf("\n(%f,%f,%f)-(%f,%f,%f)\n", min[0], min[1], min[2], max[0], max[1], max[2]);
+    
+    // Apply HW acceleration OpenGL Technique
+    applyHWAcceleration(); 
+
+    glDrawBuffer(GL_BACK);
+    glReadBuffer(GL_BACK);
+
+    // Get the projected areas for all cameras
+    for (i=0; i<numCameras; i++) {
+        
+        // Clear color and depth buffers
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+        
+        glMatrixMode(GL_MODELVIEW);
+        glLoadIdentity();
+        
+        // Camera  i
+        gluLookAt(cameras[i].eyeX, cameras[i].eyeY, cameras[i].eyeZ,
+                  cameras[i].centerX, cameras[i].centerY, cameras[i].centerZ,
+                  cameras[i].upX, cameras[i].upY, cameras[i].upZ);
+        
+        renderGeometry();
+        glFlush();
+        
+        ///////////////////////////////////////////////////////////////////////////
+        background = histogram[i][0];
+        //printf("b: %d\n", histogram[i][0]);
+
+        del_area = 0;
+        mod_area = 0;
+
+        for (j=0; j<( GLuint)c->numDel; j++) {
+            t = c->deleted[j].id;
+            del_area += histogram[i][t + 1];
+
+            histogram[i][t + 1] = 0;
+        }
+
+        for (j=0; j<( GLuint)c->numMod; j++) {
+            t = c->modified[j].id;
+            del_area += histogram[i][t + 1];
+
+            histogram[i][t + 1] = 0;
+        }
+        
+        getSWHistogramWin(histogram[i], pixels, min, max, c); 
+
+        for (j=0; j<( GLuint)c->numMod; j++) {
+            t = c->modified[j].id;
+            mod_area += histogram[i][t + 1];
+
+            //printf("t%d: %d\n",t, histogram[i][t + 1]);
+        }
+        histogram[i][0] = background + (del_area - mod_area);
+        //printf("b: %d\n", histogram[i][0]);
+    }
+    //getchar();
+
+    // draw to the window, reading from the color texture
+    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+    if (!bEnableOffScreen) drawTexture();
+    
+    ///////////////////////////////////////////////////////////////////////////
+}
 
 void VMI::freeMemory(void) {
@@ -339,5 +416,32 @@
 #endif
 
-		glutDestroyWindow(vmiWin);
+		if (vmiWin != 0)
+		{
+			glutDestroyWindow(vmiWin);
+		}
+
+#ifdef VERTEX_BUFFER_OBJECTS
+    glDeleteBuffersARB(1, &vertex_buf);
+    
+    glDeleteBuffersARB(1, &color_buf);
+#endif
+
+	pmodel = NULL; // The .obj model
+
+	pixels = NULL;
+
+	cameras = NULL;
+	numCameras = 0;
+
+	colors = NULL;
+
+	histogram = NULL;
+  queries = NULL;
+
+	mesh = NULL;
+
+	initialIs = NULL;
+
+	vmiWin = 0;
 }
 
@@ -391,29 +495,7 @@
 
 #ifdef SALIENCY
-#ifdef KL // Kullback-Leibler
-	sprintf(s,"%s_%d_%d_VKL_S.obj", filename, numCameras, mesh->currentNumTriangles);
-#endif
-#ifdef MI // Mutual Information
-	sprintf(s,"%s_%d_%d_VMI_S.obj", filename, numCameras, mesh->currentNumTriangles);
-#endif
-#ifdef HE // Hellinger
-	sprintf(s,"%s_%d_%d_VHE_S.obj", filename, numCameras, mesh->currentNumTriangles);
-#endif
-#ifdef CS // Chi-Square
-	sprintf(s,"%s_%d_%d_VCS_S.obj", filename, numCameras, mesh->currentNumTriangles);
-#endif
+    sprintf(s,"%s_%d_%d_%s_S.obj", filename, numCameras, mesh->currentNumTriangles, EXT);
 #else
-#ifdef KL // Kullback-Leibler
-	sprintf(s,"%s_%d_%d_VKL.obj", filename, numCameras, mesh->currentNumTriangles);
-#endif
-#ifdef MI // Mutual Information
-	sprintf(s,"%s_%d_%d_VMI.obj", filename, numCameras, mesh->currentNumTriangles);
-#endif
-#ifdef HE // Hellinger
-	sprintf(s,"%s_%d_%d_VHE.obj", filename, numCameras, mesh->currentNumTriangles);
-#endif
-#ifdef CS // Chi-Square
-	sprintf(s,"%s_%d_%d_VCS.obj", filename, numCameras, mesh->currentNumTriangles);
-#endif
+    sprintf(s,"%s_%d_%d_%s.obj", filename, numCameras, mesh->currentNumTriangles, EXT);
 #endif
 
@@ -454,95 +536,73 @@
  *  RGBA display mode, and handle input events.
  */
-//int main(int argc, char** argv)
-//{
-//    char s[MAX_CHAR];
-//
-//    process_cmdline(argc, argv);
-//    
-//    // Load a .obj model
-//    pmodel = glmReadOBJ(argv[argc-1]);
-//    if (!pmodel) exit(0);
-//    glmUnitize(pmodel);
-//    //glmFacetNormals(pmodel);
-//    //glmVertexNormals(pmodel, 90.0);
-//
-//    mesh = initMesh(pmodel);
-//    //printMesh(mesh);
-//    //getchar();
-//
-//    if ((numDemandedTriangles == 0) || (numDemandedTriangles >= mesh->currentNumTriangles))
-//        usage_error("Illegal number of triangles.");
-//
-//    printf("w: %d h: %d\n", width, height);
-//    printf("t: %d c: %d o: %d r: %f\n", numDemandedTriangles, cameraType, bEnableOffScreen, radius);
-//    //getchar();
-//
-//    // Get a filename without extension
-//    strncpy(filename, argv[argc - 1], strlen(argv[argc - 1]) - 4);
-//    
-//    glutInit(&argc, argv);
-//    glutInitDisplayMode(GLUT_DEPTH | GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA); /* RGB and Alpha */
-//    glutInitWindowSize(width, height);
-//    glutInitWindowPosition(100, 100);
-//
-//#ifdef KL // Kullback-Leibler
-//    sprintf(s, "VKL - [%s]", argv[argc-1]); 
-//#endif
-//#ifdef MI // Mutual Information
-//    sprintf(s, "VMI - [%s]", argv[argc-1]); 
-//#endif
-//#ifdef HE // Hellinger
-//    sprintf(s, "VHE - [%s]", argv[argc-1]); 
-//#endif
-//#ifdef CS // Chi-Square
-//    sprintf(s, "VCS - [%s]", argv[argc-1]); 
-//#endif
-//    
-//    vmiWin = glutCreateWindow(s);
-//
-//    glewInit();
-//
-//    init();
-//
-//    if (bLoadCamerasFromFile == GL_FALSE) {
-//        switch (cameraType) {
-//        case 0:
-//            cameras = setCameras(radius, OCTAHEDRON, &numCameras);
-//            printf("Number of cameras: %d\n", OCTAHEDRON);
-//            break;
-//        case 1:
-//            cameras = setCameras(radius, ICOSAHEDRON, &numCameras);
-//            printf("Number of cameras: %d\n", ICOSAHEDRON);
-//            break;
-//        case 2:
-//            cameras = setCameras(radius, DODECAHEDRON, &numCameras);
-//            printf("Number of cameras: %d\n", DODECAHEDRON);
-//            break;
-//        default:
-//            break;
-//        }
-//    } else {
-//        sprintf(s,"%s.cam", filename);
-//        
-//        cameras = loadCameras(radius, s, &numCameras);
-//        //getchar();
-//    }
-//
-//		histogram = initHistogram(mesh->currentNumTriangles, numCameras);
-//
-//    initialIs = initIs(numCameras);
-//    
-//		if (!bEnableOffScreen) {
-//			  glutReshapeFunc(reshape);
-//        glutKeyboardFunc(keyboard);
-//			  glutDisplayFunc(display);
-//		}
-//		else {
-//        display();
-//    		freeMemory(); 		
-//    }
-//    exit(0);
-//
-//    glutMainLoop();
-//    return 0;
-//}
+/*int main(int argc, char** argv)
+{
+    char s[MAX_CHAR];
+
+    process_cmdline(argc, argv);
+    
+    // Load a .obj model
+    pmodel = glmReadOBJ(argv[argc-1]);
+    if (!pmodel) exit(0);
+    glmUnitize(pmodel);
+    if (bRemoveRedundantVertices == GL_TRUE)
+        glmWeld(pmodel, 0.00001);
+    //glmFacetNormals(pmodel);
+    //glmVertexNormals(pmodel, 90.0);
+
+    mesh = initMesh(pmodel);
+    //printMesh(mesh);
+    //getchar();
+
+    if ((numDemandedTriangles == 0) || (numDemandedTriangles >= mesh->numTriangles))
+        usage_error("Illegal number of triangles.");
+
+    printf("w: %d h: %d\n", width, height);
+    printf("t: %d c: %d o: %d r: %f\n", numDemandedTriangles, cameraType, bEnableOffScreen, radius);
+    //getchar();
+
+    // Get a filename without extension
+    strncpy(filename, argv[argc - 1], strlen(argv[argc - 1]) - 4);
+    
+    glutInit(&argc, argv);
+    glutInitDisplayMode(GLUT_DEPTH | GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA); // RGB and Alpha
+    glutInitWindowSize(width, height);
+    glutInitWindowPosition(100, 100);
+
+    sprintf(s, "%sW - [%s]", EXT, argv[argc-1]);
+    
+    glutCreateWindow(s);
+
+    glewInit();
+
+    init();
+
+    if (bLoadCamerasFromFile == GL_FALSE)
+        cameras = setCameras(radius, cameraType, &numCameras);
+    else {
+        sprintf(s,"%s.cam", filename);
+        
+        cameras = loadCameras(radius, s, &numCameras);
+        //getchar();
+    }
+
+    histogram = initHistogram(mesh->numTriangles, numCameras);
+
+    initialIs = initIs(numCameras);
+    
+    // Allocate memory for colors
+    colors = initColors(mesh->numTriangles);
+
+    // Set a different color for every triangle 
+    setColors4(colors, mesh->numTriangles);
+
+    if (!bEnableOffScreen){
+        glutReshapeFunc(reshape);
+        glutKeyboardFunc(keyboard);
+        glutDisplayFunc(display);
+
+        glutMainLoop();
+    } else display();
+
+    return 0;
+}*/
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/change.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/change.cpp	(revision 1024)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/change.cpp	(revision 2090)
@@ -6,27 +6,49 @@
 #include "../include/change.h"
 
-#define MAX_NUM_TRI 250
-
 using namespace VMI;
-
-std::vector<VMI::vmiStep> VMI::mVMISteps;
-
-Change *VMI::createChange (Mesh *mesh, int e) {
-    Change *c;
-    
-    c = (Change*) malloc (sizeof(Change));
-    if (NULL == c) {
-        fprintf (stderr, "no more memory for mesh changes");
-        exit(1);
-    }
-    c->e = e;
-    c->u = mesh->edges[e].u;
-    c->v = mesh->edges[e].v;
-    c->modified = NULL;
-    c->deleted = NULL;
-    c->numDel = 0;
-    c->numMod = 0;
-    
-    return c;
+using namespace std;
+
+Geometry::MeshSimplificationSequence *VMI::mSequence	=	NULL;
+
+Change *VMI::createChange(Mesh *mesh, int e) {
+	Change *c;
+
+	c = (Change*) malloc (sizeof(Change));
+	if (NULL == c) {
+		fprintf (stderr, "no more memory for a mesh change\n");
+		exit(1);
+	}
+	c->e = e;
+	c->u = mesh->edges[e].u;
+	c->v = mesh->edges[e].v;
+	c->modified = NULL;
+	c->deleted = NULL;
+	c->numDel = 0;
+	c->numMod = 0;
+
+	computeChange(mesh, c);
+
+	return c;
+}
+
+Change *VMI::newChange(Mesh *mesh, int u, int v) {
+	Change *c;
+
+	c = (Change*) malloc (sizeof(Change));
+	if (NULL == c) {
+		fprintf (stderr, "no more memory for a mesh change\n");
+		exit(1);
+	}
+	c->e = -1; // Default edge, not used
+	c->u = u;
+	c->v = v;
+	c->modified = NULL;
+	c->deleted = NULL;
+	c->numDel = 0;
+	c->numMod = 0;
+
+	computeChange(mesh, c);
+
+	return c;
 }
 
@@ -91,5 +113,4 @@
 void VMI::modifyTriangle(Triangle *t, int c, int p)
 {
-
 	if ((int)t->indices[0] == c)
 		t->indices[0]= p;
@@ -100,5 +121,5 @@
 }
 
-int VMI::isATriangleToModify(Triangle *t, int c, int p)
+int VMI::isATriangleToModify(Triangle *t, int c)
 {
 	int u = t->indices[0],
@@ -109,86 +130,4 @@
 
 	return FALSE;
-}
-
-void VMI::modifyTriangles(Mesh *mesh, Change *c)
-{
-	int i, t;
-
-	for (i=0; i<c->numMod; i++)
-	{
-		t = c->modified[i].id;
-		modifyTriangle(&mesh->triangles[t], c->u, c->v);
-
-		//printf("New area of triangle %d:\n", t);
-		mesh->triangles[t].area = computeTriangleArea(mesh->vertices, &mesh->triangles[t]);
-
-		computeTriangleNormal(mesh->vertices, &mesh->triangles[t]);
-	}
-}
-
-void VMI::unmodifyTriangles(Mesh *mesh, Change *c)
-{
-	int i, t;
-
-	for (i=0; i<c->numMod; i++) {
-		t = c->modified[i].id;
-
-		memcpy(&mesh->triangles[t], &c->modified[i], sizeof(Triangle));
-		/*printf("t(%d %d %d)\n", mesh->triangles[t].indices[0], 
-			mesh->triangles[t].indices[1],
-			mesh->triangles[t].indices[2]);*/
-	}
-}
-
-void VMI::deleteTriangles(Mesh *mesh, Change *c)
-{
-	int i, t;
-
-	for (i=0; i<c->numDel; i++)
-	{
-		t = c->deleted[i].id;
-
-		//printf("Deleting triangle %d\n",t);
-		mesh->triangles[t].enable = FALSE;
-		mesh->currentNumTriangles--;
-	}
-}
-
-void VMI::undeleteTriangles(Mesh *mesh, Change *c)
-{
-	int i, t;
-
-	for (i=0; i<c->numDel; i++)
-	{
-		t = c->deleted[i].id;
-
-		memcpy(&mesh->triangles[t], &c->deleted[i], sizeof(Triangle));
-		/*printf("t(%d %d %d)\n", mesh->triangles[t].indices[0], 
-			mesh->triangles[t].indices[1], 
-			mesh->triangles[t].indices[2]);*/
-
-		mesh->triangles[t].enable = TRUE;
-		mesh->currentNumTriangles++;
-	}
-}
-
-int VMI::getTrianglesToModify(Mesh *mesh, int c, int p, Triangle *modified)
-{
-	GLuint i, num = 0;
-
-	for (i=0; i<mesh->numTriangles; i++)
-	{
-		if ((mesh->triangles[i].enable == TRUE) && 
-				isATriangleToModify(&mesh->triangles[i], c, p))
-		{
-
-			//printf("Triangle to modify %d\n", i);
-			// Save the original values of the triangle
-			memcpy(&modified[num], &mesh->triangles[i], sizeof(Triangle));
-			num++;
-		}
-	}
-
-	return num;
 }
 
@@ -211,48 +150,298 @@
 }
 
-int VMI::getTrianglesToDelete(Mesh *mesh, int numMod, Triangle *modified, Triangle *deleted, int c, int p)
-{
-	int i, num = 0;
-	GLuint t;
-
-	for (i=0; i<numMod; i++)
-	{
-		t = modified[i].id;
-
-		if (isATriangleToDelete(&mesh->triangles[t], c, p))
-		{                                             
-			//printf("Triangle to delete %d\n",t);                    
-			memcpy(&deleted[num], &modified[i], sizeof(Triangle));
-			num++;
-		}
-	}
-	return num;
-}
-
-void VMI::printList(Triangle *list, int n)
-{
-	int i;
-
-	for (i=0; i<n; i++)
-		printf("%d ",list[i].id);
-
-	printf("\n");
-}
-
-void VMI::deleteItem(Triangle *list, int *n, int item)
-{
-	int i, j;
-
-	for (i=0; i<*n; i++)
-	{
-		if (list[i].id == (GLuint)item)
-		{
-			// delete it
-			for (j =i + 1 ; j<*n; j++)
-				list[j - 1] = list[j];
-			(*n)--;
-			i--; // Delete all ocurrencies of an item
-		}
-	}
+void VMI::modifyTriangles(Mesh *mesh, Change *c)
+{
+	int i, t;
+
+	// Reallocate memory for new adjacent triangles from vertex v
+  if (c->numMod > 0) {
+      mesh->vertices[c->v].triangles = 
+          (GLuint *)realloc(mesh->vertices[c->v].triangles, 
+          (mesh->vertices[c->v].numTriangles + mesh->vertices[c->u].numTriangles) * sizeof(GLuint));
+  }
+
+	for (i=0; i<c->numMod; i++) {
+		t = c->modified[i].id;
+		modifyTriangle(&mesh->triangles[t], c->u, c->v);
+
+		//printf("New area of triangle %d:\n", t);
+		mesh->triangles[t].area = computeTriangleArea(mesh->vertices, &mesh->triangles[t]);
+
+		computeTriangleNormal(mesh->vertices, &mesh->triangles[t]);
+
+		// Update vertex adjacency c->v
+		addItem((int *)mesh->vertices[c->v].triangles, (int *)&mesh->vertices[c->v].numTriangles, t);
+	}
+}
+
+void VMI::unmodifyTriangles(Mesh *mesh, Change *c)
+{
+	int i, t;
+
+	for (i=0; i<c->numMod; i++) {
+		t = c->modified[i].id;
+
+		memcpy(&mesh->triangles[t], &c->modified[i], sizeof(Triangle));
+		/*printf("t(%d %d %d)\n", mesh->triangles[t].indices[0], 
+			mesh->triangles[t].indices[1],
+			mesh->triangles[t].indices[2]);*/
+
+		// Update vertex adjacency c->v
+		delItem((int *)mesh->vertices[c->v].triangles, (int *)&mesh->vertices[c->v].numTriangles, t);
+	}
+
+}
+
+int VMI::hasEdge(Triangle *t, int e) {
+    int e0 = t->edges[0],
+        e1 = t->edges[1],
+        e2 = t->edges[2];
+    
+    if ((e == e0) || (e == e1) || (e == e2)) return TRUE;
+
+    return FALSE;
+}
+
+void VMI::getEdges(Triangle *t, Change *c, int *l, int *r) {
+
+    // Default edges
+    *l = -1;
+    *r = -1;
+
+    // Set edge l and r
+    if ((int)t->edges[0] == c->e) {
+        *l = t->edges[1];
+        *r = t->edges[2];
+        if ((int)mesh->edges[*l].u == c->v || (int)mesh->edges[*l].v == c->v)
+            swap(l, r);
+    } else if ((int)t->edges[1] == c->e) {
+        *l = t->edges[0];
+        *r = t->edges[2];
+        if ((int)mesh->edges[*l].u == c->v || (int)mesh->edges[*l].v == c->v)
+            swap(l, r);
+    } else if ((int)t->edges[2] == c->e) {
+        *l = t->edges[0];
+        *r = t->edges[1];
+        if ((int)mesh->edges[*l].u == c->v || (int)mesh->edges[*l].v == c->v)
+            swap(l, r);
+    }
+}
+
+void VMI::swap(int *i, int *j) {
+    int t;
+
+    t = *i;
+    *i = *j;
+    *j = t;
+}
+
+void VMI::deleteTriangles(Mesh *mesh, Change *c)
+{
+	    int i, j, t, v;
+#ifdef USE_EDGE_ADJACENCY
+    int t1, l, r;
+#endif
+    
+    for (i=0; i<c->numDel; i++) {
+        t = c->deleted[i].id;
+
+        //printf("%d(%d,%d) Deleting triangle %d\n",c->e, c->u, c->v, t);
+
+        // Update vertex adjacency
+        for (j=0; j<3; j++) {
+            v = c->deleted[i].indices[j];
+            
+            delItem((int *)mesh->vertices[v].triangles,(int *)&mesh->vertices[v].numTriangles,t);
+        }
+
+#ifdef USE_EDGE_ADJACENCY
+        // Update triangle edge adjancency
+        // The modified triangles have to be calculated before
+        // Set edge l and r
+        getEdges(&c->deleted[i], c, &l, &r);
+        //printf("e%d(%d,%d): l:%d r:%d\n", c->e, c->u, c->v, l, r);
+        // Find triangle that contains edge l
+        for (j=0; j<c->numMod; j++)
+            if (hasEdge(&c->modified[j], l)) {
+                // Change edge l by r in the Mesh
+                t1 = c->modified[j].id;
+                //printf("t:%d %d %d %d\n", t1, mesh->triangles[t1].edges[0], mesh->triangles[t1].edges[1] ,mesh->triangles[t1].edges[2]);
+                if (mesh->triangles[t1].edges[0] == (GLuint)l) mesh->triangles[t1].edges[0] = r;
+                if (mesh->triangles[t1].edges[1] == (GLuint)l) mesh->triangles[t1].edges[1] = r;
+                if (mesh->triangles[t1].edges[2] == (GLuint)l) mesh->triangles[t1].edges[2] = r;
+                //printf("t:%d %d %d %d\n", t1, mesh->triangles[t1].edges[0], mesh->triangles[t1].edges[1] ,mesh->triangles[t1].edges[2]);
+                break;
+            }
+
+        // Delete edge l
+        if (l != -1) mesh->edges[l].enable = FALSE;
+#endif
+        mesh->triangles[t].enable = FALSE;
+        mesh->currentNumTriangles--;
+    }
+}
+
+void VMI::undeleteTriangles(Mesh *mesh, Change *c) {
+    int i, j, t, v;
+    
+    for (i=0; i<c->numDel; i++) {
+        t = c->deleted[i].id;
+        
+        //printf("Undeleting triangle %d\n",t);
+
+        memcpy(&mesh->triangles[t], &c->deleted[i], sizeof(Triangle));
+        /*printf("t(%d %d %d)\n", mesh->triangles[t].indices[0], 
+                                  mesh->triangles[t].indices[1], 
+                                  mesh->triangles[t].indices[2]);*/
+
+        // Update vertex adjacency
+        for (j=0; j<3; j++) {
+            v = c->deleted[i].indices[j];
+            
+            addItem((int *)mesh->vertices[v].triangles,(int *)&mesh->vertices[v].numTriangles,t);
+        }
+#ifdef USE_EDGE_ADJACENCY
+        // Enable adjacent edges
+        for (j=0; j<3; j++) {
+            mesh->edges[mesh->triangles[t].edges[j]].enable = TRUE;
+        }
+#endif
+        mesh->triangles[t].enable = TRUE;
+        mesh->currentNumTriangles++;
+    }
+}
+
+Triangle *VMI::getTrianglesToModify(Mesh *mesh, Change *c, GLuint *numMod) {
+  int i, t;
+  Triangle *modified = NULL;
+
+  // Allocating memory
+  modified = (Triangle *)malloc(mesh->vertices[c->u].numTriangles * sizeof(Triangle));
+  *numMod = 0;
+  
+  for (i=0; i<(int)mesh->vertices[c->u].numTriangles; i++) {
+      
+      t = mesh->vertices[c->u].triangles[i];
+      
+      if ((mesh->triangles[t].enable == TRUE) && 
+          !isATriangleToDelete(&mesh->triangles[t], c->u, c->v)) {
+          
+          //printf("Triangle to modify %d\n", t);
+          // Save the original values of the triangle
+          memcpy(&modified[*numMod], &mesh->triangles[t], sizeof(Triangle));
+          (*numMod)++;
+      }
+  }
+  return modified;
+}
+
+Triangle *VMI::getTrianglesToDelete(Mesh *mesh, Change *c, GLuint *numDel) {
+  int i, t;
+  Triangle *deleted = NULL;
+  
+  // Allocating memory
+  deleted = (Triangle *)malloc(mesh->vertices[c->u].numTriangles * sizeof(Triangle));
+  *numDel = 0;
+
+  for (i=0; i<(int)mesh->vertices[c->u].numTriangles; i++) {
+      
+      t = mesh->vertices[c->u].triangles[i];
+
+      if ((mesh->triangles[t].enable == TRUE) &&
+          isATriangleToDelete(&mesh->triangles[t], c->u, c->v)) {
+                                                    
+          //printf("Triangle to delete %d\n",t);                    
+          memcpy(&deleted[*numDel], &mesh->triangles[t], sizeof(Triangle));
+          (*numDel)++;
+      }
+  }
+  return deleted;
+}
+
+void VMI::deleteEdges(Mesh *mesh, Change *c) {
+    int i, e;
+#ifndef USE_EDGE_ADJACENCY
+    int n0, n1, n2;
+#else
+    int j, u, v;
+#endif
+
+#ifdef USE_EDGE_ADJACENCY
+    for (i=0; i<c->numDel; i++) {
+        
+        for (j=0; j<3; j++) {
+            e = c->deleted[i].edges[j];
+            if (e != c->e) {
+                u = mesh->edges[e].u;
+                v = mesh->edges[e].v;
+                if (u == c->u || v == c->u) {
+                    //printf("%d\n",j);
+                    mesh->edges[e].enable = FALSE;
+                }
+            }
+        }
+        //getchar();
+    }
+#else
+    for (i=0; i<c->numDel; i++) {
+
+        n0 = c->deleted[i].indices[0];
+        n1 = c->deleted[i].indices[1];
+        n2 = c->deleted[i].indices[2];
+
+        if ((n0 == c->u && n1 != c->v) || (n1 == c->u && n0 != c->v)) {
+            e = findEdge(mesh->edges, mesh->numEdges, n0, n1);
+
+            //printf("a\n");
+            if (e != -1)
+                mesh->edges[e].enable = FALSE;
+        }
+
+        if ((n1 == c->u && n2 != c->v) || (n2 == c->u && n1 != c->v)) {
+            e = findEdge(mesh->edges, mesh->numEdges, n1, n2);
+            
+            //printf("b\n");
+            if (e != -1)
+                mesh->edges[e].enable = FALSE;
+        }
+
+        if ((n0 == c->u && n2 != c->v) || (n2 == c->u && n0 != c->v)) {
+            e = findEdge(mesh->edges, mesh->numEdges, n0, n2);
+            
+            //printf("c\n");
+            if (e != -1)
+                mesh->edges[e].enable = FALSE;
+        }
+        //getchar();
+    }
+#endif
+}
+
+void VMI::modifyEdges(Mesh *mesh, Change *c) {
+    int e, u, v;
+    
+    // Update mesh and heap
+    for(e = 0; e < (int)mesh->numEdges; e++) {
+        
+        if (mesh->edges[e].enable == TRUE) {
+            
+            // Modify edge
+            if ((int)mesh->edges[e].u == c->u)
+                mesh->edges[e].u = c->v;
+            
+            if ((int)mesh->edges[e].v == c->u)
+                mesh->edges[e].v = c->v;
+            
+            // Check edge
+            u = mesh->edges[e].u;
+            v = mesh->edges[e].v;
+            
+            // if the edge is not valid, we simply delete it
+            if ((u == v) || 
+                (u == c->u) || (v == c->u)) 
+                
+                mesh->edges[e].enable = FALSE;
+        }
+    }
 }
 
@@ -260,53 +449,17 @@
 
 // Compute the triangle mesh changes due to a heap node simplification
-void VMI::computeChanges(Mesh *mesh, Change *c)
-{
-	Triangle m[MAX_NUM_TRI], d[MAX_NUM_TRI/2];
-	int numMod = getTrianglesToModify(mesh, c->u, c->v, m);
-	int numDel = getTrianglesToDelete(mesh, numMod, m, d, c->u, c->v);
-	int i;
-
-	//printf("d %d\n",numDel);
-	//printList(d, numDel);
-
-	for (i=0; i<numDel; i++)
-		deleteItem(m, &numMod, d[i].id);
-
-	//printf("m %d\n",numMod);
-	//printList(m, numMod);
-	//getchar();
-
-	c->numDel = numDel;
-	// Free memory
-	if (c->deleted != NULL) free(c->deleted);
-	// Allocate memory
-	c->deleted = (Triangle *)malloc(sizeof(Triangle) * numDel);
-	
-	if (c->deleted == NULL)
-	{
-		fprintf(stderr, "Error allocating memory\n");
-		exit(1);
-	}
-	
-	memcpy(c->deleted, d, sizeof(Triangle) * numDel);
-
-	c->numMod = numMod;
-	
-	// Free memory
-	if (c->modified != NULL) free(c->modified);
-	
-	// Allocate memory
-	c->modified = (Triangle *)malloc(sizeof(Triangle) * numMod);
-	
-	if (c->modified == NULL)
-	{
-		fprintf(stderr, "Error allocating memory\n");
-		exit(1);
-	}
-	
-	memcpy(c->modified, m, sizeof(Triangle) * numMod);
-
-	//printChange(c);
-	//getchar();
+void VMI::computeChange(Mesh *mesh, Change *c) {
+  GLuint numMod, numDel;
+  Triangle *m = getTrianglesToModify(mesh, c, &numMod),
+            *d = getTrianglesToDelete(mesh, c, &numDel);
+  
+  c->numDel   = numDel;
+  c->deleted  = d;
+  
+  c->numMod   = numMod;
+  c->modified = m;
+
+  //printChange(c);
+  //getchar();
 }
 
@@ -316,12 +469,17 @@
 	modifyTriangles(mesh, c);
 
+	// This function must be called after modifyTriangles()
 	deleteTriangles(mesh, c);
 
+	// Delete vertex u
 	mesh->vertices[c->u].enable = FALSE;
 	mesh->currentNumVertices--;
+
+	//printMesh(mesh);
+	//getchar();
 }
 
 void VMI::undoChange(Mesh *mesh, Change *c)
-{    
+{
 	unmodifyTriangles(mesh, c);
 
@@ -330,54 +488,64 @@
 	mesh->vertices[c->u].enable = TRUE;
 	mesh->currentNumVertices++;
-}
-
+
+	//printMesh(mesh);
+	//getchar();
+}
+
+/*
 namespace VMI{
 std::map<int, INTVECTOR> inversemap;
 }
+*/
 
 //	Save simplification sequence in Geometry Game Tools format.
-extern void	VMI::saveSimplificationSequence(Change	*c)
-{
-
-	int stepnum= 1;
-	for(INTVECTOR::iterator it= inversemap[c->u].begin(); it!=inversemap[c->u].end(); it++)
+extern void	VMI::saveSimplificationSequence(Change	*c,int obligatory)
+{
+	Geometry::MeshSimplificationSequence::Step	step;
+
+	if (mSequence == NULL)
 	{
-		vmiStep	step;
-		step.mV0	=	*it;
-		step.mV1	=	c->v;
-
-		//	If only one triangle has been deleted.
-		if (c->numDel == 1)
-		{
-			step.mT0	=	c->deleted[0].id;
-			step.mT1	=	c->deleted[0].id;
-		}
-		//	If two triangles have been deleted.
-		else
-		{
-			step.mT0	=	c->deleted[0].id;
-			step.mT1	=	c->deleted[1].id;
-		}
-
-		step.x	=	0.0;
-		step.y	=	0.0;
-		step.z	=	0.0;
-
-		//	Write obligatory field.
-		if (stepnum==inversemap[c->u].size())
-			step.obligatory	=	0;
-		else
-			step.obligatory	=	1;
-		stepnum++;
-
-		//	List of new triangles.
-		//	For each modified triangle.
-		for (int	i = 0;	i < c->numMod;	i++)
-		{
-			step.mModfaces.push_back(c->modified[i].id);
-		}
-
-		//	Add step to list of changes.
-		mVMISteps.push_back(step);
-	}
-}
+		mSequence	=	new Geometry::MeshSimplificationSequence();
+	}
+
+	step.mV0	=	c->v;
+	step.mV1	=	c->u;
+
+	//	Debug.
+	cout	<<	"----> V0: "
+				<<	step.mV0
+				<<	" V1: "
+				<<	step.mV1
+				<<	endl;
+
+	//	If only one triangle has been deleted.
+	if (c->numDel == 1)
+	{
+		step.mT0	=	c->deleted[0].id;
+		step.mT1	=	c->deleted[0].id;
+	}
+	//	If two triangles have been deleted.
+	else
+	{
+		step.mT0	=	c->deleted[0].id;
+		step.mT1	=	c->deleted[1].id;
+	}
+
+	step.x	=	0.0;
+	step.y	=	0.0;
+	step.z	=	0.0;
+
+	//	Write obligatory field.
+	step.obligatory	=	obligatory;
+
+	//	List of new triangles.
+	//	For each modified triangle.
+	for (int	i = 0;	i < c->numMod;	i++)
+	{
+		step.mModfaces.push_back(c->modified[i].id);
+	}
+
+	//	Add step to list of changes.
+	mSequence->mSteps.push_back(step);
+}
+
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/camera.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/camera.cpp	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/camera.cpp	(revision 2090)
@@ -174,36 +174,47 @@
 
     switch (type) {
-    case OCTAHEDRON:
-        cameras = (Camera *)malloc(sizeof(Camera) * type);
+    case 0:
+        cameras = (Camera *)malloc(sizeof(Camera) * OCTAHEDRON);
         if (cameras == NULL) {
             fprintf(stderr, "Error allocating memory\n");
             exit(1);
         }
-        *numCameras = type;
+        *numCameras = OCTAHEDRON;
         drawOctahedron(cameras, radius);
         break;
-    case ICOSAHEDRON:
-        cameras = (Camera *)malloc(sizeof(Camera) * type);
+    case 1:
+        cameras = (Camera *)malloc(sizeof(Camera) * CUBE);
         if (cameras == NULL) {
             fprintf(stderr, "Error allocating memory\n");
             exit(1);
         }
-        *numCameras = type;
-        drawIcosahedron(cameras, radius);
+        *numCameras = CUBE;
+        drawCube(cameras, radius);
         break;
-    case DODECAHEDRON:
-        cameras = (Camera *)malloc(sizeof(Camera) * type);
+    case 2:
+        cameras = (Camera *)malloc(sizeof(Camera) * ICOSAHEDRON);
         if (cameras == NULL) {
             fprintf(stderr, "Error allocating memory\n");
             exit(1);
         }
-        *numCameras = type;
+        *numCameras = ICOSAHEDRON;
+        drawIcosahedron(cameras, radius);
+        break;
+    case 3:
+        cameras = (Camera *)malloc(sizeof(Camera) * DODECAHEDRON);
+        if (cameras == NULL) {
+            fprintf(stderr, "Error allocating memory\n");
+            exit(1);
+        }
+        *numCameras = DODECAHEDRON;
         drawDodecahedron(cameras, radius);
         break;
     default:
-        printf("Error cameras not defined\n");
+        printf("Error, cameras not defined\n");
         exit(1);
         break;
     }
+
+    printf("Number of cameras: %d\n", *numCameras);
 
     return cameras;
@@ -506,2 +517,58 @@
     copyToCameras(cameras, 12, vertices);
 }
+
+void VMI::drawCube(Camera *cameras, GLdouble r) // any radius in which the polyhedron is inscribed
+{
+    GLdouble vertices[8][3] = {
+        {-1, -1, 1},   // vertex v0
+        {1,  -1, 1},   // vertex v1
+        {1,  -1, -1},  // vertex v2
+        {-1, -1, -1},  // vertex v3
+        {-1, 1,  1},   // vertex v4
+        {1,  1,  1},   // vertex v5
+        {1,  1,  -1},  // vertex v6 
+        {-1, 1,  -1},  // vertex v7
+    }; // 8 vertices with x, y, z coordinates
+    int i;
+#ifdef DRAW_DEBUG
+    int tindex[12][3] = {
+        
+        {0, 1, 4}, //polygon v0,v1,v4
+        {1, 5, 4}, //polygon v1,v5,v4
+        {1, 2, 5}, //polygon v1,v2,v5
+        {2, 6, 5}, //polygon v2,v6,v5
+        {2, 3, 6}, //polygon v2,v3,v6
+        {3, 7, 6}, //polygon v3,v7,v6
+        {3, 0, 7}, //polygon v3,v0,v7
+        {0, 4, 7}, //polygon v0,v4,v7
+        {4, 5, 7}, //polygon v4,v5,v7
+        {5, 6, 7}, //polygon v5,v6,v7
+        {3, 2, 0}, //polygon v3,v2,v0
+        {2, 1, 0}, //polygon v2,v1,v0
+    };
+#endif
+    
+    for(i=0; i<8; i++)
+    {
+        vertices[i][0]*=r;
+        vertices[i][1]*=r;
+        vertices[i][2]*=r;
+    }
+
+    // map vertices to 12 faces 
+#ifdef DRAW_DEBUG
+    
+    for (i=0; i<12; i++) { 
+        
+        glBegin(GL_POINTS );
+        glVertex3fv(&vertices[tindex[i][0]][0]); 
+        glVertex3fv(&vertices[tindex[i][1]][0]); 
+        glVertex3fv(&vertices[tindex[i][2]][0]);    
+        glEnd(); 
+    }
+
+#endif
+    
+    copyToCameras(cameras, 8, vertices);
+}
+
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/mesh.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/mesh.cpp	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/mesh.cpp	(revision 2090)
@@ -11,6 +11,8 @@
 using namespace	VMI;
 
-#define MAX_NUM_TRI 450
-
+#define OUTPUT_SEVERAL_GROUPS
+
+///////////////////////////////////////////////////////////////////////////////
+// list of integers
 void VMI::printItemList(int *list, int n) {
     int i;
@@ -35,4 +37,19 @@
         list[(*n)++] = item;
 }
+
+void VMI::delItem(int *list, int *n, int item) {
+    int i, j;
+    
+    for (i=0; i<*n; i++) {
+        if (list[i] == item) {
+            // delete it
+            for (j =i + 1 ; j<*n; j++)
+                list[j - 1] = list[j];
+            (*n)--;
+            i--; // Delete all ocurrencies of an item
+        }
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
 
 int VMI::findEdge(Edge *e, GLuint num, GLuint _u, GLuint _v) {
@@ -56,4 +73,31 @@
 
     return found;
+}
+
+// Adds a new edge at the end of the mesh edge list
+Edge *VMI::addEdge(Edge *list, int *n, int u, int v, int *pos) {
+	  Edge *newList;
+
+		// Reallocate memory for the new edge
+    newList = (Edge *)realloc(list, ((*n) + 1) * sizeof(Edge));
+
+		// New vertex indices
+		newList[*n].u = u;
+    newList[*n].v = v;
+
+		// This edge has no triangle adjancency
+		newList[*n].numTriangles = 0;
+		newList[*n].triangles = NULL;
+		
+		// Enable the new edge
+		newList[*n].enable = TRUE;
+
+		// New edge position
+		*pos = *n;
+
+		// New number of edges
+	  (*n)++;
+
+		return newList;
 }
 
@@ -131,6 +175,8 @@
 Mesh *VMI::initMesh(GLMmodel* pmodel) {
 
-    GLuint i, j, v1, v2, v3, n, e, t;
+    GLuint i, j, curGroup, v1, v2, v3, n, m, t;
+    int e;
     Mesh *mesh;
+    GLMgroup *group;
 
     mesh = (Mesh *)malloc (sizeof(Mesh));
@@ -157,5 +203,4 @@
     printf("Adding vertices...");
     for (i=1; i<=pmodel->numvertices; i++) { // Vertices start at 1
-
         mesh->vertices[i - 1].x = pmodel->vertices[3 * i + 0];
         mesh->vertices[i - 1].y = pmodel->vertices[3 * i + 1];
@@ -170,4 +215,41 @@
 
     printf("Adding triangles...");
+
+#ifdef OUTPUT_SEVERAL_GROUPS
+    group = pmodel->groups;
+    curGroup=0; // current group
+    while(group) {
+        
+        for (i=0; i<group->numtriangles; i++) {
+            
+            t = group->triangles[i];
+
+            mesh->triangles[t].id = t;
+            mesh->triangles[t].group = curGroup; // set group
+            mesh->triangles[t].indices[0] = pmodel->triangles[t].vindices[0] - 1;
+            mesh->triangles[t].indices[1] = pmodel->triangles[t].vindices[1] - 1;
+            mesh->triangles[t].indices[2] = pmodel->triangles[t].vindices[2] - 1;
+            mesh->triangles[t].area = computeTriangleArea(mesh->vertices, &mesh->triangles[t]);
+            //printf("\n%d a: %f",i , mesh->triangles[i].area);
+            computeTriangleNormal(mesh->vertices, &mesh->triangles[t]);
+            
+            mesh->triangles[t].saliency = 0.0;
+            
+            mesh->triangles[t].enable = GL_TRUE;
+            
+            for (j=0; j<3; j++) {
+                // Adding triangle i adjacent to 3 vertices
+                v1 = mesh->triangles[t].indices[j];
+                
+                // Reallocate memory for the new adjacent triangle
+                mesh->vertices[v1].triangles = 
+					(GLuint *)realloc(mesh->vertices[v1].triangles, (mesh->vertices[v1].numTriangles + 1) * sizeof(GLuint));
+                addItem((int *)mesh->vertices[v1].triangles, (int *)&mesh->vertices[v1].numTriangles, t);
+            }
+        }
+        curGroup++;
+        group = group->next;
+    }
+#else // One single group
     for (i=0; i<pmodel->numtriangles; i++) {
         mesh->triangles[i].id = i;
@@ -188,13 +270,16 @@
    
             // Reallocate memory for the new adjacent triangle
-            mesh->vertices[v1].triangles = (GLuint *)realloc(mesh->vertices[v1].triangles, (mesh->vertices[v1].numTriangles + 1) * sizeof(GLuint));
+            mesh->vertices[v1].triangles = 
+			    (GLuint *)realloc(mesh->vertices[v1].triangles, (mesh->vertices[v1].numTriangles + 1) * sizeof(GLuint));
             addItem((int *)mesh->vertices[v1].triangles, (int *)&mesh->vertices[v1].numTriangles, i);
         }
     }
-    //printf("\n");
+    printf("\n");
+#endif
     printf("Ok\n");
 
     mesh->numTriangles = pmodel->numtriangles;
     mesh->currentNumTriangles = pmodel->numtriangles;
+    printf("Number of triangles: %d\n", mesh->numTriangles);
 
     mesh->edges = (Edge *)malloc (sizeof(Edge) * mesh->numTriangles * 3);  // E = 3 T / 2
@@ -205,11 +290,4 @@
     }
     
-    // Init edges
-    for (i=0; i<mesh->numTriangles * 3; i++) {
-        
-        mesh->edges[i].triangles    = NULL;
-        mesh->edges[i].numTriangles = 0;
-    }
-
     printf("Adding edges...");
     n = 0;
@@ -221,76 +299,66 @@
         v3 = mesh->triangles[i].indices[2];
         
+        /////////////////////////////////////////////////////////////////////////////////
+		// edge (v1,v2)
         if ((e = findEdge(mesh->edges, n, v1, v2)) == -1) {
             mesh->edges[n].u = v1;
             mesh->edges[n].v = v2;
+						mesh->edges[n].triangles    = NULL;
+        		mesh->edges[n].numTriangles = 0;
             mesh->edges[n].enable = GL_TRUE;
-            
-            // Reallocate memory for the new adjacent triangle
-            mesh->edges[n].triangles = (GLuint *)realloc(mesh->edges[n].triangles, (mesh->edges[n].numTriangles + 1) * sizeof(GLuint));
-            // Adding triangle i adjacent to edge n
-            addItem((int *)mesh->edges[n].triangles, (int *)&mesh->edges[n].numTriangles, i);
-            //printf("n:%d i:%d\n", n, i);
-            
-            // Adding edge n adjacent to triangle i
-            addItem((int *)mesh->triangles[i].edges, (int *)&t, n);
+            m = n;
             n++;
-        } else {
-            // Reallocate memory for the new adjacent triangle
-            mesh->edges[e].triangles = (GLuint *)realloc(mesh->edges[e].triangles, (mesh->edges[e].numTriangles + 1) * sizeof(GLuint));
-            // Adding triangle i adjacent to edge e
-            addItem((int *)mesh->edges[e].triangles, (int *)&mesh->edges[e].numTriangles, i);
-            //printf("n:%d i:%d\n", e, i);
-            
-            // Adding edge e adjacent to triangle i
-            addItem((int *)mesh->triangles[i].edges, (int *)&t, e);
-        }
+        } else m = e;
+		// Reallocate memory for the new adjacent triangle
+        mesh->edges[m].triangles = 
+			(GLuint *)realloc(mesh->edges[m].triangles, (mesh->edges[m].numTriangles + 1) * sizeof(GLuint));
+        // Adding triangle i adjacent to edge m
+        addItem((int *)mesh->edges[m].triangles, (int *)&mesh->edges[m].numTriangles, i);
+        //printf("n:%d i:%d\n", m, i);
+        
+        // Adding edge m adjacent to triangle i
+        addItem((int *)mesh->triangles[i].edges, (int *)&t, m);
+
+        /////////////////////////////////////////////////////////////////////////////////
+        // edge (v2,v3)
         if (( e = findEdge(mesh->edges, n, v2, v3)) == -1) {
             mesh->edges[n].u = v2;
             mesh->edges[n].v = v3;
+						mesh->edges[n].triangles    = NULL;
+        		mesh->edges[n].numTriangles = 0;
             mesh->edges[n].enable = GL_TRUE;
-            
-            // Reallocate memory for the new adjacent triangle
-            mesh->edges[n].triangles = (GLuint *)realloc(mesh->edges[n].triangles, (mesh->edges[n].numTriangles + 1) * sizeof(GLuint));
-            // Adding triangle i adjacent to edge n
-            addItem((int *)mesh->edges[n].triangles, (int *)&mesh->edges[n].numTriangles, i);
-            //printf("n:%d i:%d\n", n, i);
-            
-            // Adding edge n adjacent to triangle i
-            addItem((int *)mesh->triangles[i].edges, (int *)&t, n);
+            m = n;
             n++;
-        } else {
-            // Reallocate memory for the new adjacent triangle
-            mesh->edges[e].triangles = (GLuint *)realloc(mesh->edges[e].triangles, (mesh->edges[e].numTriangles + 1) * sizeof(GLuint));
-            // Adding triangle i adjacent to edge e
-            addItem((int *)mesh->edges[e].triangles, (int *)&mesh->edges[e].numTriangles, i);
-            //printf("n:%d i:%d\n", e, i);
-            
-            // Adding edge e adjacent to triangle i
-            addItem((int *)mesh->triangles[i].edges, (int *)&t, e);
-        }
+        } else m = e;
+		// Reallocate memory for the new adjacent triangle
+        mesh->edges[m].triangles = 
+			(GLuint *)realloc(mesh->edges[m].triangles, (mesh->edges[m].numTriangles + 1) * sizeof(GLuint));
+        // Adding triangle i adjacent to edge m
+        addItem((int *)mesh->edges[m].triangles, (int *)&mesh->edges[m].numTriangles, i);
+        //printf("n:%d i:%d\n", m, i);
+        
+        // Adding edge m adjacent to triangle i
+        addItem((int *)mesh->triangles[i].edges, (int *)&t, m);
+
+        /////////////////////////////////////////////////////////////////////////////////
+        // edge (v3,v1)
         if ((e = findEdge(mesh->edges, n, v3, v1)) == -1) {
             mesh->edges[n].u = v3;
             mesh->edges[n].v = v1;
+						mesh->edges[n].triangles    = NULL;
+        		mesh->edges[n].numTriangles = 0;
             mesh->edges[n].enable = GL_TRUE;
-            
-            // Reallocate memory for the new adjacent triangle
-            mesh->edges[n].triangles = (GLuint *)realloc(mesh->edges[n].triangles, (mesh->edges[n].numTriangles + 1) * sizeof(GLuint));
-            // Adding triangle i adjacent to edge n
-            addItem((int *)mesh->edges[n].triangles, (int *)&mesh->edges[n].numTriangles, i);
-            //printf("n:%d i:%d\n", n, i);
-            
-            // Adding edge n adjacent to triangle i
-            addItem((int *)mesh->triangles[i].edges, (int *)&t, n);
+            m = n;
             n++;
-        } else  {
-            // Reallocate memory for the new adjacent triangle
-            mesh->edges[e].triangles = (GLuint *)realloc(mesh->edges[e].triangles, (mesh->edges[e].numTriangles + 1) * sizeof(GLuint));
-            // Adding triangle i adjacent to edge e
-            addItem((int *)mesh->edges[e].triangles, (int *)&mesh->edges[e].numTriangles, i);
-            //printf("n:%d i:%d\n", e, i);
-            
-            // Adding edge e adjacent to triangle i
-            addItem((int *)mesh->triangles[i].edges, (int *)&t, e);
-        }
+        } else m = e;
+		// Reallocate memory for the new adjacent triangle
+        mesh->edges[m].triangles = 
+			(GLuint *)realloc(mesh->edges[m].triangles, (mesh->edges[m].numTriangles + 1) * sizeof(GLuint));
+        // Adding triangle i adjacent to edge m
+        addItem((int *)mesh->edges[m].triangles, (int *)&mesh->edges[m].numTriangles, i);
+        //printf("n:%d i:%d\n", m, i);
+        
+        // Adding edge m adjacent to triangle i
+        addItem((int *)mesh->triangles[i].edges, (int *)&t, m);
     }
     printf("Ok\n");
@@ -322,5 +390,5 @@
     printf("------------------------\n");
     for (i=0; i<mesh->numEdges; i++) {
-        printf("e%d (%d,%d)\n", i, mesh->edges[i].u, mesh->edges[i].v);
+        printf("e%d (%d,%d) %d\n", i, mesh->edges[i].u, mesh->edges[i].v, mesh->edges[i].enable);
         printf("  t(%d)[", mesh->edges[i].numTriangles);
         if (mesh->edges[i].triangles != NULL) {
@@ -329,5 +397,5 @@
                 printf(",%d", mesh->edges[i].triangles[j]);
             }
-        }
+				}
         printf("]\n");
     }
@@ -336,6 +404,6 @@
     printf("------------------------\n");
     for (i=0; i<mesh->numTriangles; i++) {
-        printf("t%d (%d,%d,%d)\n", i, mesh->triangles[i].indices[0], mesh->triangles[i].indices[1],
-                                     mesh->triangles[i].indices[2]);
+        printf("t%d (%d,%d,%d) %d\n", i, mesh->triangles[i].indices[0], mesh->triangles[i].indices[1],
+                                     mesh->triangles[i].indices[2],  mesh->triangles[i].enable);
         printf("  e(3)[");
         printf("%d", mesh->triangles[i].edges[0]);
@@ -385,79 +453,62 @@
 
 int *VMI::trianglesAdjToEdge(Mesh *mesh, int e, int *n) {
-    int triangles[MAX_NUM_TRI];
-    int i, n0, n1, n2, 
+    int i, n0, n1, n2, num = 0, t, 
         u = mesh->edges[e].u, 
         v = mesh->edges[e].v;
-    int *list, num = 0;
-
-    for (i=0; i<(int)mesh->numTriangles; i++) {
-        
-        if (mesh->triangles[i].enable == TRUE) {
-            
-            n0 = mesh->triangles[i].indices[0];
-            n1 = mesh->triangles[i].indices[1];
-            n2 = mesh->triangles[i].indices[2];
+    int *triangles = NULL;
+
+	if ((mesh->vertices[u].numTriangles + 
+         mesh->vertices[v].numTriangles) > 0)
+		 triangles = (int *)malloc((mesh->vertices[u].numTriangles + 
+                                    mesh->vertices[v].numTriangles) * sizeof(int));
+
+    for (i=0; i<(int)mesh->vertices[u].numTriangles; i++) {
+
+        t = mesh->vertices[u].triangles[i];
+        
+        if (mesh->triangles[t].enable == TRUE) {
+            
+            n0 = mesh->triangles[t].indices[0];
+            n1 = mesh->triangles[t].indices[1];
+            n2 = mesh->triangles[t].indices[2];
             
             if ((n0 == v) || (n1 == v) || (n2 == v) ||
                 (n0 == u) || (n1 == u) || (n2 == u))
                 
-                triangles[num++] = i;
-        }
-    }
-
-    list = (int*) malloc (sizeof(int) * num);
-    if (NULL == list) {
-        fprintf (stderr, "no more memory for list");
-        exit(1);
-    }
-
-    memcpy(list, triangles, sizeof(int) * num);
-
+                addItem(triangles, &num, t);
+        }
+    }
+
+    for (i=0; i<(int)mesh->vertices[v].numTriangles; i++) {
+
+        t = mesh->vertices[v].triangles[i];
+        
+        if (mesh->triangles[t].enable == TRUE) {
+            
+            n0 = mesh->triangles[t].indices[0];
+            n1 = mesh->triangles[t].indices[1];
+            n2 = mesh->triangles[t].indices[2];
+            
+            if ((n0 == v) || (n1 == v) || (n2 == v) ||
+                (n0 == u) || (n1 == u) || (n2 == u))
+                
+                addItem(triangles, &num, t);
+        }
+    }
     *n = num;
 
-    return list;
-}
-
-int *VMI::trianglesAdjToVertex(Mesh *mesh, int v, int *n) {
-    int triangles[MAX_NUM_TRI];
-    int i, n0, n1, n2;
-    int *list, num = 0;
-
-    for (i=0; i<(int)mesh->numTriangles; i++) {
-        
-        if (mesh->triangles[i].enable == TRUE) {
-            
-            n0 = mesh->triangles[i].indices[0];
-            n1 = mesh->triangles[i].indices[1];
-            n2 = mesh->triangles[i].indices[2];
-            
-            if ((n0 == v) || (n1 == v) || (n2 == v))
-                
-                triangles[num++] = i;
-        }
-    }
-
-    list = (int*) malloc (sizeof(int) * num);
-    if (NULL == list) {
-        fprintf (stderr, "no more memory for list");
-        exit(1);
-    }
-
-    memcpy(list, triangles, sizeof(int) * num);
-
-    *n = num;
-
-    return list;
+    return triangles;
 }
 
 int *VMI::verticesAdjToVertex(Mesh *mesh, int v, int *n) {
-    int numTr;
-    int *triangles = trianglesAdjToVertex(mesh, v, &numTr);
-    int *vertices = (int*) malloc (sizeof(int) * numTr * 2);
+    int *vertices = NULL;
     int i, t, n0, n1, n2;
     int num = 0;
 
-    for (i=0; i<numTr; i++) {
-        t = triangles[i];
+	if (mesh->vertices[v].numTriangles > 0)
+		vertices = (int*)malloc(sizeof(int) * mesh->vertices[v].numTriangles * 2);
+
+    for (i=0; i<(int)mesh->vertices[v].numTriangles; i++) {
+        t = mesh->vertices[v].triangles[i];
 
         n0 = mesh->triangles[t].indices[0];
@@ -469,22 +520,35 @@
         if (n2 != v) addItem(vertices, &num, n2);
     }
-
     *n = num;
 
-    free(triangles);
-
     return vertices;
 }
 
 int *VMI::edgesAdjToVertex(Mesh *mesh, int v, int *n) {
-    int numTr;
-    int *triangles = trianglesAdjToVertex(mesh, v, &numTr);
-    int *edges = (int*) malloc (sizeof(int) * numTr * 2);
-    int i, t, n0, n1, n2, e;
+    int *edges = NULL;
+    int i, t, e;
+#ifndef USE_EDGE_ADJACENCY
+    int n0, n1, n2;
+#else
+    int j;
+#endif
     int num = 0;
 
-    for (i=0; i<numTr; i++) {
-        t = triangles[i];
-
+	if (mesh->vertices[v].numTriangles > 0) 
+		edges = (int*)malloc(sizeof(int) * mesh->vertices[v].numTriangles * 2);
+
+    for (i=0; i<(int)mesh->vertices[v].numTriangles; i++) {
+
+        t = mesh->vertices[v].triangles[i];
+
+#ifdef USE_EDGE_ADJACENCY
+        for (j=0; j<3; j++) {
+            e = mesh->triangles[t].edges[j];
+            
+            if ((int)mesh->edges[e].u == v || (int)mesh->edges[e].v == v)
+                
+                addItem(edges, &num, e);
+        }
+#else
         n0 = mesh->triangles[t].indices[0];
         n1 = mesh->triangles[t].indices[1];
@@ -498,44 +562,50 @@
         
         if (((n0 == v) || (n2 == v)) &&
-            ((e = findEdge(mesh->edges, mesh->numEdges, n0, n2)) != -1)) addItem(edges, &num, e);  
-    }
-
+            ((e = findEdge(mesh->edges, mesh->numEdges, n0, n2)) != -1)) addItem(edges, &num, e);
+
+#endif
+    }
     *n = num;
 
-    free(triangles);
-
     return edges;
 }
 
 int *VMI::edgesAdjToVertices(Mesh *mesh, int *vertices, int numVertices, int *n) {
-    int edges[MAX_NUM_TRI*2];
-    int i, j, v, num = 0, e;
-    int *list, numEdges;
-
-    for (i=0; i<numVertices; i++) {
-        v = vertices[i];
-
-        list = edgesAdjToVertex(mesh, v, &numEdges);
-
-        for (j=0; j<numEdges; j++) {
-            e = list[j];
-            
-            addItem(edges, &num, e);
-        }
+    int *edges = NULL;
+    int i, j, num = 0;
+    int *list = NULL, numEdges;
+
+    if (numVertices > 0) {
+        // Add the first
+        list = edgesAdjToVertex(mesh, vertices[0], &numEdges);
+
+        // Allocate memory
+        edges = (int *)malloc(numEdges * sizeof(int));
+
+        memcpy(edges, list, sizeof(int) * numEdges);
 
         free(list);
-    }
-
-    list = (int*) malloc (sizeof(int) * num);
-    if (NULL == list) {
-        fprintf (stderr, "no more memory for list");
-        exit(1);
-    }
-
-    memcpy(list, edges, sizeof(int) * num);
-
+
+        num = numEdges;
+
+        // Add the rest
+        for (i=1; i<numVertices; i++) {
+
+            list = edgesAdjToVertex(mesh, vertices[i], &numEdges);
+
+            // Reallocate memory
+			if (numEdges > 0) {
+
+                edges = (int *)realloc(edges, (num + numEdges + 1) * sizeof(int));
+                
+                for (j=0; j<numEdges; j++)
+                    addItem(edges, &num, list[j]);
+			}
+            free(list);
+        }
+    }
     *n = num;
 
-    return list;
+    return edges;
 }
 
@@ -563,4 +633,34 @@
 }
 
+// Adds a new vertex at the end of the mesh vertex list
+Vertex *VMI::addVertex(Vertex *list, int *n, float x, float y, float z, int *pos) {
+	  Vertex *newList;
+
+		// Reallocate memory for the new vertex
+    newList = (Vertex *)realloc(list, ((*n) + 1) * sizeof(Vertex));
+
+		// New Vertex coordinates
+		newList[*n].x = x;
+    newList[*n].y = y;
+    newList[*n].z = z;
+
+		// This vertex has no triangle adjancency
+		newList[*n].numTriangles = 0;
+		newList[*n].triangles = NULL;
+	
+    // Enable the new vertex
+		newList[*n].enable = TRUE;
+
+		// New vertex position
+		*pos = *n;
+
+		// New number of vertices
+	  (*n)++;
+		
+		return newList;
+}
+
+
+
 void VMI::updateModel(GLMmodel* pmodel, Mesh *mesh, GLuint numVertices, GLuint numTriangles) {
     GLuint i , v1, v2 ,v3, numV = 1, numT = 0;
@@ -569,13 +669,9 @@
     
     if (pmodel->vertices != NULL) free(pmodel->vertices);
-
     pmodel->vertices = (GLfloat *)calloc ((numVertices + 1) * 3,  sizeof(GLfloat));
-    
 
     if (pmodel->triangles != NULL) free(pmodel->triangles);
-
     pmodel->triangles = (GLMtriangle *)malloc (numTriangles * sizeof(GLMtriangle));
 
-    
     for (i=0; i<mesh->numTriangles; i++) {
         if (mesh->triangles[i].enable) {
@@ -630,6 +726,42 @@
 
 void VMI::saveModel(char *filename, GLMmodel* pmodel, Mesh *mesh) {
-    GLuint i;
-
+    GLuint i, j, g, numT = 0;
+    GLMgroup *group;
+
+#ifdef OUTPUT_SEVERAL_GROUPS
+    // The output model maintains groups
+
+    // Empty all groups
+    group = pmodel->groups;
+    while(group) {
+        // Free memory for triangles
+        free(group->triangles);
+
+        // Reset group
+        group->triangles = NULL;
+        group->numtriangles = 0;
+
+        group = group->next;
+    }
+    // Fill all groups
+    for (i=0; i<mesh->numTriangles; i++) {
+
+        if (mesh->triangles[i].enable) {
+            g = mesh->triangles[i].group;
+
+            // Get group
+            group = pmodel->groups;
+            for (j=0; j <g; j++)
+                group = group->next;
+
+            // Reallocate memory for triangles
+            group->triangles = (GLuint *)realloc(group->triangles, (group->numtriangles + 1) * sizeof(GLuint));
+            // Add triangle into group
+            addItem((int *)group->triangles, (int *)&group->numtriangles, numT);
+
+            numT++;
+        }
+    }
+#else
     // The output model contains only one group
     pmodel->numgroups = 1;
@@ -646,4 +778,5 @@
     for (i=0; i<mesh->currentNumTriangles; i++)
         pmodel->groups->triangles[i] = i;
+#endif
 
     updateModel(pmodel, mesh, mesh->currentNumTriangles * 3, mesh->currentNumTriangles);
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/simplify.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/simplify.cpp	(revision 1007)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/simplify.cpp	(revision 2090)
@@ -9,419 +9,468 @@
 #include "../include/simplify.h"
 #include "../include/saliency.h"
+#include "../include/histogram.h"
 
 //#define RECOMPUTE_THE_WHOLE_HEAP
-//#define MAKE_FULL_COPY
 
 using namespace	VMI;
+using	namespace	std;
+
+//	Multimap to store current vertex in a simplification state.
+typedef	multimap<_float3_,	int>	t_map;
+typedef	t_map::iterator						t_map_str;
+typedef	t_map::value_type					t_pair;
+t_map															mVertexMap;
+multimap<int,int>									mVertices;
+
+vector<Geometry::Vector3>	VMI::vPositions;
+vector<Geometry::Vector3>	VMI::vNormals;
+vector<Geometry::Vector2>	VMI::vTexCoords;
 
 ///////////////////////////////////////////////////////////////////////////////
 
 void VMI::bh_mydump(Mesh *mesh, bheap_t *h) {
-    int i, d;
-
-    printf("Heap status.\n");
-    for(i = 1; i <= h->n; i++) {
-        d = h->a[i].item;
-        printf ("Heap [%d] = pri %f, e%d(%d, %d)\n", i,
-                  h->a[i].key,d,
-                  mesh->edges[d].u,
-                  mesh->edges[d].v);
-    }
-
-    printf("\n");
-    
-    for(i = 2; i <= h->n; i++) {
-        if(h->a[i].key < h->a[i/2].key) {
-            printf("key error at entry %d, value %f\n", i, h->a[i].key);
-            exit(1);
-        }
-    }
-    for(i = 1; i <= h->n; i++) {
-        if(h->p[h->a[i].item] != i) {
-            printf("indexing error at entry %d", i); exit(1);
-        }
-    }    
+	int i, d;
+
+	printf("Heap status.\n");
+	for(i = 1; i <= h->n; i++) {
+		d = h->a[i].item;
+		printf ("Heap [%d] = pri %f, e%d(%d, %d) d:%d\n",
+				i,
+				h->a[i].key,d,
+				mesh->edges[d].u,
+				mesh->edges[d].v, 
+				h->a[i].dirty);
+	}
+	printf("\n");
+
+	for(i = 2; i <= h->n; i++) {
+		if(h->a[i].key < h->a[i/2].key) {
+			printf("key error at entry %d, value %f\n", i, h->a[i].key);
+			exit(1);
+		}
+	}
+	for(i = 1; i <= h->n; i++) {
+		if(h->p[h->a[i].item] != i) {
+			printf("indexing error at entry %d", i);
+			exit(1);
+		}
+	}    
 }
 
 bheap_t *VMI::initHeap(Mesh *mesh) {
-    GLuint i;
-    double cost;
-    bheap_t *h = NULL;
-#ifdef MAKE_FULL_COPY
-    Triangle *triangleCopy = NULL;
-    GLuint lastNumTriangles = mesh->numTriangles;
-
-    // Allocate memory
-    triangleCopy = (Triangle *)malloc(lastNumTriangles * sizeof(Triangle));  
-    if (triangleCopy == NULL) {
-        fprintf(stderr, "Error allocating memory\n");
-        exit(1);
-    }
-    // Make a copy of current triangle list
-    memcpy(triangleCopy, mesh->triangles, lastNumTriangles * sizeof(Triangle));
-#endif
-    
-    printf("Creating a heap for simplification...");
-    
-    h = bh_alloc(mesh->numEdges);
-
-		//	Init percent update count.
-		float	percent	=	60.0 / mesh->numEdges;
-
-    for (i = 0; i <mesh->numEdges; i++) {
-
-				//	Update progress bar.
-				mUPB(percent);
-
-        if (mesh->edges[i].enable == TRUE) {
-
-            cost = computeEdgeCost(mesh, i);
-        
-            // Add only valid edges
-            if (cost != FLT_MAX)
-                bh_insert(h, i, cost);
-
-#ifdef MAKE_FULL_COPY
-            // Restore initial triangle list
-            memcpy(mesh->triangles, triangleCopy, lastNumTriangles * sizeof(Triangle));
-            mesh->numTriangles = lastNumTriangles;
-#endif
-        }
-    }
-    
-#ifdef MAKE_FULL_COPY
-    // Free memory
-    if (triangleCopy != NULL) free(triangleCopy);
-#endif
-    printf("Ok\n");
+	GLuint i;
+	double cost;
+	bheap_t *h = NULL;
+
+	printf("Creating a heap for simplification...");
+
+	h = bh_alloc(mesh->numEdges);
+
+	//	Init percent update count.
+	float	percent	=	60.0 / mesh->numEdges;
+
+	for (i = 0; i <mesh->numEdges; i++) {
+
+		//	Update progress bar.
+		mUPB(percent);
+
+		if (mesh->edges[i].enable == TRUE) {
+
+			cost = computeEdgeCost(mesh, i);
+
+			// Add only valid edges
+			if (cost != FLT_MAX) {
+				bh_insert(h, i, cost);
+				/* set dirty flag to FALSE */
+				bh_mark(h, i, FALSE);
+			}
+		}
+	}
+
+	printf("Ok\n");
 
 #ifdef DEBUG 
-    bh_mydump(mesh, h);
-    //getchar();
-#endif
-
-    return h;
+	bh_mydump(mesh, h);
+	//getchar();
+#endif
+
+	return h;
 }
 
 bheap_t *VMI::updateHeap(bheap_t *h, Mesh *mesh, Change *c) {
-    int e, i, n0, n1, n2, u, v;
+	int e, i;
 #ifdef RECOMPUTE_THE_WHOLE_HEAP
-    bheap_t *nh;
+	bheap_t *nh;
+	double cost;
 #else
-    int *lv, *le, numV, numE;
-#endif
-    double cost;
-#ifdef MAKE_FULL_COPY
-    GLuint lastNumTriangles = mesh->numTriangles;
-    Triangle *triangleCopy = NULL;
-    
-    // Allocate memory
-    triangleCopy = (Triangle *)malloc(lastNumTriangles * sizeof(Triangle));  
-    if (triangleCopy == NULL) {
-        fprintf(stderr, "Error allocating memory\n");
-        exit(1);
-    }
-    // Make a copy of current triangle list
-    memcpy(triangleCopy, mesh->triangles, lastNumTriangles * sizeof(Triangle));
-#endif
-
-    for (i=0; i<c->numDel; i++) {
-
-        n0 = c->deleted[i].indices[0];
-        n1 = c->deleted[i].indices[1];
-        n2 = c->deleted[i].indices[2];
-
-        if (((n0 == c->u) || (n1 == c->u)) &&
-            ((e = findEdge(mesh->edges, mesh->numEdges, n0, n1)) != -1)) {
-
-            mesh->edges[e].enable = FALSE;
-            bh_delete(h, e);
-        }
-
-        if (((n1 == c->u) || (n2 == c->u)) &&
-            ((e = findEdge(mesh->edges, mesh->numEdges, n1, n2)) != -1)) {
-             
-            mesh->edges[e].enable = FALSE;
-            bh_delete(h, e);
-        }
-
-        if (((n0 == c->u) || (n2 == c->u)) &&
-            ((e = findEdge(mesh->edges, mesh->numEdges, n0, n2)) != -1)) {
-              
-            mesh->edges[e].enable = FALSE;
-            bh_delete(h, e);
-        }
-    }
-
-    // Update mesh and heap
-    for(i = 1; i <= h->n; i++) {
-        e = h->a[i].item;
-
-        if ((int)mesh->edges[e].u == c->u)
-            mesh->edges[e].u = c->v;
-
-        if ((int)mesh->edges[e].v == c->u)
-            mesh->edges[e].v = c->v;
-        
-        // Check edge
-        u = mesh->edges[e].u;
-        v = mesh->edges[e].v;
-    
-        // if it is not a valid edge we simply delete it
-        if ((u == v) || 
-            (u == c->u) || (v == c->u)) {
-
-            mesh->edges[e].enable = FALSE;
-            bh_delete(h, e);
-        }
-    }
+	int *lv, *le, numV, numE;
+#endif
 
 #ifdef RECOMPUTE_THE_WHOLE_HEAP
 
-    nh = bh_alloc(mesh->numEdges);
-
-    // Recompute heap
-    for(i = 1; i <= h->n; i++) {
-        e = h->a[i].item;
-        
-        cost = computeEdgeCost(mesh, e);
-        
-        // Add only valid edges
-        if (cost != FLT_MAX)
-            bh_insert(nh, e, cost);
-        
-#ifdef MAKE_FULL_COPY
-        // Restore initial triangle list
-        memcpy(mesh->triangles, triangleCopy, lastNumTriangles * sizeof(Triangle));
-        mesh->numTriangles = lastNumTriangles;
-#endif
-    }
-
-#ifdef MAKE_FULL_COPY
-    // Free memory
-    if (triangleCopy != NULL) free(triangleCopy);
-#endif
-    bh_free(h);
-
-    h = nh;
+	nh = bh_alloc(mesh->numEdges);
+
+	// Recompute heap
+	for(i = 1; i <= h->n; i++) {
+		e = h->a[i].item;
+
+		cost = computeEdgeCost(mesh, e);
+
+		// Add only valid edges
+		if (cost != FLT_MAX)
+			bh_insert(nh, e, cost);
+	}
+
+	bh_free(h);
+
+	h = nh;
 
 #else
 
-    // Compute vertices adjacent to a vertex
-    lv = verticesAdjToVertex(mesh, c->v, &numV);
-
-    // Compute edges adjacent to vertices
-    le = edgesAdjToVertices(mesh, lv, numV, &numE);
-
-    free(lv);
-
-    // Delete adjacent edges from the heap
-    for(i = 0; i <numE; i++) {
-        e = le[i];
-
-        mesh->edges[e].enable = FALSE;
-        bh_delete(h, e);
-    }
-
-    // Recompute cost only for the adjacent edges
-    for(i = 0; i <numE; i++) {
-        e = le[i];
-        
-        cost = computeEdgeCost(mesh, e);
-
-        // Add only valid edges
-        if (cost != FLT_MAX) {
-            bh_insert(h, e, cost);
-            mesh->edges[e].enable = TRUE;
-        }
-        
-#ifdef MAKE_FULL_COPY
-        // Restore initial triangle list
-        memcpy(mesh->triangles, triangleCopy, lastNumTriangles * sizeof(Triangle));
-        mesh->numTriangles = lastNumTriangles;
-#endif
-
-    }
-
-#ifdef MAKE_FULL_COPY
-    // Free memory
-    if (triangleCopy != NULL) free(triangleCopy);
-#endif
-
-    free(le);
+	// Compute vertices adjacent to a vertex
+	lv = verticesAdjToVertex(mesh, c->v, &numV);
+
+	// Compute edges adjacent to vertices
+	le = edgesAdjToVertices(mesh, lv, numV, &numE);
+
+	free(lv);
+
+	// Set a dirty flag to adjacent edges from the heap
+	for(i = 0; i <numE; i++) {
+		e = le[i];
+
+		bh_mark(h, e, TRUE);
+	}
+
+	free(le);
 #endif
 
 #ifdef DEBUG 
-    bh_mydump(mesh, h);
-    //getchar();
-#endif
-
-    return h;
+	bh_mydump(mesh, h);
+	//getchar();
+#endif
+
+	return h;
 }
 
 GLdouble VMI::computeEdgeLength(Vertex *vertices, int u, int v) {
-    GLfloat ux, uy, uz, vx, vy ,vz, rx, ry, rz;
-    
-    ux = vertices[u].x;
-    uy = vertices[u].y;
-    uz = vertices[u].z;
-
-    vx = vertices[v].x;
-    vy = vertices[v].y;
-    vz = vertices[v].z;
-
-    rx = ux - vx;
-    ry = uy - vy;
-    rz = uz - vz;
-
-    return sqrt((rx * rx) + (ry * ry) + (rz * rz));
+	GLfloat ux, uy, uz, vx, vy ,vz, rx, ry, rz;
+
+	ux = vertices[u].x;
+	uy = vertices[u].y;
+	uz = vertices[u].z;
+
+	vx = vertices[v].x;
+	vy = vertices[v].y;
+	vz = vertices[v].z;
+
+	rx = ux - vx;
+	ry = uy - vy;
+	rz = uz - vz;
+
+	return sqrt((rx * rx) + (ry * ry) + (rz * rz));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void VMI::swap(unsigned int *i, unsigned int *j) {
-    unsigned int t;
-
-    t = *i;
-    *i = *j;
-    *j = t;
-}
-
 void VMI::chooseBestEndPoints(Mesh *mesh, int e) {
-    int v = mesh->edges[e].v;
-    int u = mesh->edges[e].u;
-    int numTu;
-    int *Tu  = trianglesAdjToVertex(mesh, u, &numTu);
-    int numTuv = 0;
-    int *Tuv = (int *)malloc(numTu * sizeof(int));
-    int numTv;
-    int *Tv  = trianglesAdjToVertex(mesh, v, &numTv);
-    int i, j, f, n, n0, n1, n2;
-    float cost_u_v, cost_v_u, mincurve, curve, dot;
-    
-    //printItemList(Tv, numTv);
-    //printItemList(Tu, numTu);
-    
-    // Compute Tuv
-    for (i=0; i<(int)numTu; i++) {
-        
-        n = Tu[i];
-        
-        n0 = mesh->triangles[n].indices[0];
-        n1 = mesh->triangles[n].indices[1];
-        n2 = mesh->triangles[n].indices[2];
-        
-        if ((n0 == v) || (n1 == v) || (n2 == v))
-            
-            Tuv[numTuv++] = n;
-    }
-    //printItemList(Tuv, numTuv);
-    
-    curve = 0.0f;
-    for (i=0; i<numTu; i++) {
-        n = Tu[i];
-        mincurve = 1.0f;
-        for (j=0; j<numTuv; j++) {
-            f = Tuv[j];
-            dot = glmDot(mesh->triangles[f].normal, mesh->triangles[n].normal);
-            //printf("dot: %f \n", dot);
-            mincurve = MIN(mincurve, (1.0f - dot) / 2.0f);
-        }
-        //printf("mincurve: %f \n", mincurve);
-        curve = MAX(curve, mincurve);
-    }
-    cost_u_v = curve;
-    
-    curve = 0.0f;
-    for (i=0; i<numTv; i++) {
-        n = Tv[i];
-        mincurve = 1.0f;
-        for (j=0; j<numTuv; j++) {
-            f = Tuv[j];
-            dot = glmDot(mesh->triangles[f].normal, mesh->triangles[n].normal);
-            //printf("%f \n", dot);
-            mincurve = MIN(mincurve, (1.0f - dot) / 2.0f);
-        }
-        curve = MAX(curve, mincurve);
-    }
-    cost_v_u = curve;
-    
-    //printf("e%d(%d,%d) cost: %f \n", e, u, v, cost_u_v);
-    //printf("e%d(%d,%d) cost: %f \n", e, v, u, cost_v_u);
-    
-    if ( (cost_v_u + 0.000001) < cost_u_v) {
-        //printf("Swap edge\n");
-        //printf("e%d(%d,%d) cost: %f \n", e, u, v, cost_u_v);
-        //printf("e%d(%d,%d) cost: %f \n", e, v, u, cost_v_u);
-        swap(&mesh->edges[e].u, &mesh->edges[e].v);
-    }
-
-    free(Tuv);
-    free(Tu);
-    free(Tv);
+	int v = mesh->edges[e].v;
+	int u = mesh->edges[e].u;
+	int numTu = mesh->vertices[u].numTriangles;
+	int numTuv = 0;
+	int *Tuv = (int *)malloc(numTu * sizeof(int));
+	int i, j, f, n, n0, n1, n2;
+	float cost_u_v, cost_v_u, mincurve, curve, dot;
+
+	// Compute Tuv
+	for (i=0; i<(int)numTu; i++) {
+
+		n = mesh->vertices[u].triangles[i];
+
+		n0 = mesh->triangles[n].indices[0];
+		n1 = mesh->triangles[n].indices[1];
+		n2 = mesh->triangles[n].indices[2];
+
+		if ((n0 == v) || (n1 == v) || (n2 == v))
+
+			Tuv[numTuv++] = n;
+	}
+	//printItemList(Tuv, numTuv);
+
+	curve = 0.0f;
+	for (i=0; i<numTu; i++) {
+		n = mesh->vertices[u].triangles[i];
+		mincurve = 1.0f;
+		for (j=0; j<numTuv; j++) {
+			f = Tuv[j];
+			dot = glmDot(mesh->triangles[f].normal, mesh->triangles[n].normal);
+			//printf("dot: %f \n", dot);
+			mincurve = MIN(mincurve, (1.0f - dot) / 2.0f);
+		}
+		//printf("mincurve: %f \n", mincurve);
+		curve = MAX(curve, mincurve);
+	}
+	cost_u_v = curve;
+
+	curve = 0.0f;
+	for (i=0; i<(int)mesh->vertices[v].numTriangles; i++) {
+		n = mesh->vertices[v].triangles[i];
+		mincurve = 1.0f;
+		for (j=0; j<numTuv; j++) {
+			f = Tuv[j];
+			dot = glmDot(mesh->triangles[f].normal, mesh->triangles[n].normal);
+			//printf("%f \n", dot);
+			mincurve = MIN(mincurve, (1.0f - dot) / 2.0f);
+		}
+		curve = MAX(curve, mincurve);
+	}
+
+	cost_v_u = curve;
+
+	//printf("e%d(%d,%d) cost: %f \n", e, u, v, cost_u_v);
+	//printf("e%d(%d,%d) cost: %f \n", e, v, u, cost_v_u);
+
+	if ( (cost_v_u + 0.000001) < cost_u_v) {
+		//printf("Swap edge\n");
+		//printf("e%d(%d,%d) cost: %f \n", e, u, v, cost_u_v);
+		//printf("e%d(%d,%d) cost: %f \n", e, v, u, cost_v_u);
+		
+		swap((int *)&mesh->edges[e].u, (int *)&mesh->edges[e].v);
+	}
+
+	free(Tuv);
 }
 ///////////////////////////////////////////////////////////////////////////////
 
+void saveProjectedAreas(GLuint **histogram, GLuint numCameras, Change *c, GLuint *dest) {
+	GLuint i, j, t, n = 0;
+
+	for (j=0; j<(GLuint)c->numDel; j++) {
+
+		t = c->deleted[j].id;
+
+		for (i=0; i<numCameras; i++) {
+
+			dest[n] = histogram[i][t + 1];
+			n++;
+		}
+	}
+
+	for (j=0; j<(GLuint)c->numMod; j++) { 
+
+		t = c->modified[j].id;
+
+		for (i=0; i<numCameras; i++) {
+
+			dest[n] = histogram[i][t + 1];
+			n++;
+		}   
+	}
+
+	// Save background area
+	for (i=0; i<numCameras; i++) {
+
+		dest[n] = histogram[i][0];
+		n++;
+	}
+}
+
+void loadProjectedAreas(GLuint *src, GLuint numCameras, Change *c, GLuint **histogram) {
+	GLuint i, j, t, n = 0;
+
+	for (j=0; j<(GLuint)c->numDel; j++) { 
+
+		t = c->deleted[j].id;
+
+		for (i=0; i<numCameras; i++) {
+
+			histogram[i][t + 1] = src[n];
+			n++;
+		}
+	}
+
+	for (j=0; j<(GLuint)c->numMod; j++) { 
+
+		t = c->modified[j].id;
+
+		for (i=0; i<numCameras; i++) {
+
+			histogram[i][t + 1] = src[n];
+			n++;
+		}
+	}
+
+	// Load background area
+	for (i=0; i<numCameras; i++) {
+
+		histogram[i][0] = src[n];
+		n++;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 GLdouble VMI::computeEdgeCost(Mesh *mesh, int e) {
-    GLdouble cost = 0.0, newI, sal = 1.0, /*length,*/ error;
-    GLuint i;
-    Change *c;
-
-    chooseBestEndPoints(mesh, e);
-    //getchar();
-
-    c = createChange(mesh, e);
-    
+	GLdouble cost = 0.0, sal = 1.0;
+#ifdef MI
+	GLdouble *auxIs = NULL;
+#else
+	GLdouble newI;
+#endif
+	GLuint i, *histoAux = NULL;
+	Change *c;
+
+	chooseBestEndPoints(mesh, e);
+	//getchar();
+
+	c = createChange(mesh, e);
+
+	// Compute cost only for boundary or manifold edges
+	if (c->numDel == 2
+			/*(c->numDel <3) && (c->numDel > 0)*/) {
+		// Allocate memory
+		histoAux = (GLuint *)malloc((c->numDel + c->numMod + 1) * numCameras * sizeof(GLuint));
+
+#ifdef MI // Mutual Information
+		///////////////////////////////////////////////////////////////////////////////
+		// Allocate memory
+		auxIs = (GLdouble *)malloc(numCameras * sizeof(GLdouble));
+
+		//printFullHistogram(histogram, numCameras, mesh->numTriangles);
+
+		for (i=0; i<numCameras; i++) {
+			// Copy old informations
+			auxIs[i] = initialIs[i];
+
+			initialIs[i] = decMI(initialIs[i], histogram, numCameras, i, c);
+		}
+
+		saveProjectedAreas(histogram, numCameras, c, histoAux);
     // Apply the edge collapse
-    computeChanges(mesh, c);
-    
-    // Compute cost only for boundary or manifold edges
-    if ((c->numDel <3) && (c->numDel > 0)) {
-
-        //length = computeEdgeLength(mesh->vertices, c->u, c->v);
-
-        doChange(mesh, c);
-        
-        // Compute the cost of an edge collapse
-        getProjectedAreas(histogram, numCameras);
-        //printFullHistogram(histogram, numCameras, mesh->numTriangles);
-        //getchar();
+		doChange(mesh, c);
+
+		// Compute the cost of an edge collapse
+		getProjectedAreasWin(histogram, numCameras, c);
+		//printFullHistogram(histogram, numCameras, mesh->numTriangles);
+		//getchar();
+
 #ifdef SALIENCY
-        sal = computeEdgeSaliency(mesh, c, percentile);
-        //printf("  e:%d s: %f\n", c->e, sal);
-#endif
-        for (i=0;i <numCameras; i++) {
+		sal = computeEdgeSaliency(mesh, c, percentile);
+		//printf("  e:%d s: %f\n", c->e, sal);
+#endif
+
+		for (i=0; i<numCameras; i++) {
+
+			initialIs[i] = incMI(initialIs[i], histogram, numCameras, i, c);
+			//printf("  I0:%f Is: %f\n", auxE[i], initialIs[i]);
+
+			cost += (ABS(auxIs[i] - initialIs[i]) * cameras[i].weight * sal);
+
+			// Restore old informations
+			initialIs[i] = auxIs[i];
+		}
+
+		undoChange(mesh, c);
+
+		loadProjectedAreas(histoAux, numCameras, c, histogram);
+		//printFullHistogram(histogram, numCameras, mesh->numTriangles);
+		//exit(1);
+
+		// Free memory
+		free(auxIs);
+#else
+		///////////////////////////////////////////////////////////////////////////////
+
+		saveProjectedAreas(histogram, numCameras, c, histoAux);
+
+		doChange(mesh, c);
+
+		// Compute the cost of an edge collapse
+		getProjectedAreasWin(histogram, numCameras, c);
+		//printFullHistogram(histogram, numCameras, mesh->numTriangles);
+
+#ifdef SALIENCY
+		sal = computeEdgeSaliency(mesh, c, percentile);
+		//printf("  e:%d s: %f\n", c->e, sal);
+#endif
+		for (i=0;i <numCameras; i++) {
 
 #ifdef KL // Kullback-Leibler
-            newI = computeKL(mesh, histogram[i]);
-#endif
-#ifdef MI // Mutual Information
-            newI = computeMI(mesh, histogram, numCameras, i);
+			newI = computeKL(mesh, histogram[i]);
 #endif
 #ifdef HE // Hellinger
-            newI = computeHE(mesh, histogram[i]);
+			newI = computeHE(mesh, histogram[i]);
 #endif
 #ifdef CS // Chi-Square
-            newI = computeCS(mesh, histogram[i]);
-#endif
-
-            error = ABS(initialIs[i] - newI);
-            
-            if (error > 0.0) 
-                cost += ((error * cameras[i].weight * sal) /*+ (length * 0.05)*/);
-        }
-
-        undoChange(mesh, c);
-
-    } else cost = FLT_MAX;
-
-
-    deleteChange(c);
-
-    return cost;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
+			newI = computeCS(mesh, histogram[i]);
+#endif
+			cost += (ABS(initialIs[i] - newI) * cameras[i].weight * sal);
+		}
+		undoChange(mesh, c);
+
+		loadProjectedAreas(histoAux, numCameras, c, histogram);
+		//printFullHistogram(histogram, numCameras, mesh->numTriangles);
+		//exit(1);
+
+		///////////////////////////////////////////////////////////////////////////////
+#endif
+		// Free memory
+		free(histoAux);
+
+	} else cost = FLT_MAX;
+
+	deleteChange(c);
+
+	return cost;
+}
+/* Get a valid edge from the heap */
+int getMinValidEdge(Mesh *mesh, bheap_t *h) {
+	int e;
+
+	/* pick the minimum-cost valid edge from heap */
+	e = bh_min(h);
+
+	while (mesh->edges[e].enable == FALSE) {
+		/* delete invalid edge */
+		bh_delete(h, e);
+		/* pick again*/
+		e = bh_min(h);
+	}
+
+	return e;
+}
+
+/* Get the mininum edge cost from the heap using lazy evaluation */
+int getMinEdge(Mesh *mesh, bheap_t *h) {
+	double cost;
+	int e;
+
+	/* pick the minimum-cost edge from heap */
+	e = getMinValidEdge(mesh, h);
+
+	while (bh_is_dirty(h, e)) {
+		/* delete edge from heap */
+		bh_delete(h, e);
+		mesh->edges[e].enable = FALSE;
+		/* recompute cost*/
+		cost = computeEdgeCost(mesh, e);
+
+		// Add only valid edges
+		if (cost != FLT_MAX) {
+			/* reinsert into the heap */
+			bh_insert(h, e, cost);
+			mesh->edges[e].enable = TRUE;
+			/* set dirty flag to FALSE */
+			bh_mark(h, e, FALSE);
+		}
+
+		/* pick again */
+		e = getMinValidEdge(mesh, h);
+	}
+
+	return e;
+}
+
+///////////////////////////////////////////////////////////////////////////
 void VMI::simplifyModel(Mesh *mesh, GLuint numDemandedTri)
 {
@@ -444,29 +493,7 @@
 	{
 #ifdef SALIENCY       
-#ifdef KL // Kullback-Leibler
-		sprintf(s,"%s_VKL_S.log", filename);
-#endif
-#ifdef MI // Mutual Information
-		sprintf(s,"%s_VMI_S.log", filename);
-#endif
-#ifdef HE // Hellinger
-		sprintf(s,"%s_VHE_S.log", filename);
-#endif
-#ifdef CS // Chi-Square
-		sprintf(s,"%s_VCS_S.log", filename);
-#endif
+		sprintf(s,"%s_%s_S.log", filename, EXT);
 #else
-#ifdef KL // Kullback-Leibler
-		sprintf(s,"%s_VKL.log", filename);
-#endif
-#ifdef MI // Mutual Information
-		sprintf(s,"%s_VMI.log", filename);
-#endif
-#ifdef HE // Hellinger
-		sprintf(s,"%s_VHE.log", filename);
-#endif
-#ifdef CS // Chi-Square
-		sprintf(s,"%s_VCS.log", filename);
-#endif
+		sprintf(s,"%s_%s.log", filename, EXT);
 #endif
 
@@ -475,5 +502,5 @@
 		/* open the file */
 		file = fopen(s, "a+");
-		
+
 		if (!file)
 		{
@@ -485,12 +512,12 @@
 	//	Open file of simplification sequence.
 	file_simp_seq	=	fopen("SimplifSequence.txt", "w");
-	
+
 	if (!file_simp_seq)
 	{
 		fprintf(stderr,
-						"simplifyModel() failed: ",
-						"can't open file \"SimplifSequence\" to write.\n");
-	}
-	
+				"simplifyModel() failed: ",
+				"can't open file \"SimplifSequence\" to write.\n");
+	}
+
 	h = initHeap(mesh);
 
@@ -500,29 +527,33 @@
 	{
 		// Get the edge that has the minimum cost
-		e = bh_min(h);
+		//e = getMinEdge(mesh, h);
+		e = extractValidEdge(mesh, h);
 
 		c = createChange(mesh, e);
 
 		// Apply the edge collapse
-		computeChanges(mesh, c);
 		doChange(mesh, c);
+		//deleteVertexOfMap(mesh, c->u);
+
+		// Write Simplification sequence.
+		saveSimplificationSequence(c,0);
+
+		//contractTwinVertices(mesh, c->u, c->v); // vertex u is removed
 
 		if (bSaveLog == TRUE) writeChange(file, c);
 
-		//	Write Simplification sequence.
-		saveSimplificationSequence(c);
-		
 		cost = h->a[h->p[e]].key;
-		
+
+		/*
 		printf(	"Edge collapse e%d(%d,%d) %f MIN d %d m %d\n",
-						c->e,
-						c->u,
-						c->v,
-						cost,
-						c->numDel,
-						c->numMod);
+				c->e,
+				c->u,
+				c->v,
+				cost,
+				c->numDel,
+				c->numMod);
+		*/
 
 		mesh->edges[e].enable = FALSE;
-		
 		bh_delete(h, e);
 
@@ -532,4 +563,7 @@
 		computeCameraIs(histogram, numCameras, initialIs);
 
+		deleteEdges(mesh, c);
+		modifyEdges(mesh, c);
+
 		// Update the heap according to the edge collapse
 		h = updateHeap(h, mesh, c);
@@ -539,6 +573,11 @@
 		deleteChange(c);
 
-		printf("t %d\n", mesh->currentNumTriangles);
-	}
+		//printf("t %d\n", mesh->currentNumTriangles);
+	}
+
+	//	Debug.
+	cout	<<	"Number of vertices: "
+		<<	mesh->currentNumVertices
+		<<	endl;
 
 	if (bSaveLog == TRUE)
@@ -554,2 +593,479 @@
 }
 
+///////////////////////////////////////////////////////////////////////////////
+//	Extract a correct edge of the heap.
+///////////////////////////////////////////////////////////////////////////////
+int VMI::extractValidEdge(Mesh *mesh,	bheap_t *h)
+{
+	int	e;
+
+	while((e	=	isValidEdge(mesh,getMinEdge(mesh, h))) == -1);
+
+	return	e;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//	Indicates if an edge is valid.
+///////////////////////////////////////////////////////////////////////////////
+int	VMI::isValidEdge(Mesh	*mesh,	int edge)
+{
+	int	result;
+	Vertex	*u;
+	Vertex	*v;
+	_float3_	fu;
+	_float3_	fv;
+
+	u	=	&mesh->vertices[mesh->edges[edge].u];
+	v	=	&mesh->vertices[mesh->edges[edge].v];
+
+	fu	=	_float3_(u->x,u->y,u->z);
+	fv	=	_float3_(v->x,v->y,v->z);
+
+	if ((mVertexMap.find(fu) != mVertexMap.end())
+			||
+			(mVertexMap.find(fv) != mVertexMap.end()))
+	{
+		result	= edge;
+	}
+	//	Edge is not valid.
+	else
+	{
+		result	=	-1;
+	}
+
+	return	result;
+}
+
+//-------------------------------------------------------------------------
+//	Inits the multimap of vertices.
+//-------------------------------------------------------------------------
+void	VMI::initVertexMultimap(Mesh *mesh,multimap<int,int> &vertexMultimap)
+{
+	Vertex	*vertex;
+	float		x,y,z;
+
+	//	Clears multimap of vertices.
+	mVertexMap.clear();
+	mVertices.clear();
+
+	mVertices	=	vertexMultimap;
+
+	//	Debug.
+	cout	<<	"Vertex Map Elements: "
+				<<	mVertices.size()
+				<<	endl;
+
+	//	For each vertex.
+	for (int	i	=	0;	i < mesh->numVertices;	i++)
+	{
+		vertex	=	&mesh->vertices[i];
+
+		x	=	vertex->x;
+		y	=	vertex->y;
+		z	=	vertex->z;
+
+		mVertexMap.insert(t_pair(_float3_(x,y,z),i));
+	}
+}
+
+//-------------------------------------------------------------------------
+//	Deletes a vertex in the multimap.
+//-------------------------------------------------------------------------
+void	VMI::deleteVertexOfMap(Mesh	*mesh, int u)
+{
+	_float3_	removed_vert;
+	t_map_str	lb;
+	t_map_str	ub;
+
+	//	Position of the vertex removed.
+	removed_vert	=	_float3_(	mesh->vertices[u].x,
+														mesh->vertices[u].y,
+														mesh->vertices[u].z);
+
+	//	If position of the removed vertex is found.
+	if (mVertexMap.end() != mVertexMap.find(removed_vert))
+	{
+		lb	=	mVertexMap.lower_bound(removed_vert);
+		ub	=	mVertexMap.upper_bound(removed_vert);
+
+		//	For each vertex.
+		while	(lb != ub)
+		{
+			//	If removed vertex is found.
+			if ((*lb).second == u)
+			{
+				//	Debug.
+				cout	<<	"Vertex erased: "
+							<<	(*lb).second
+							<<	endl;
+
+				//	Delete vertex that disappears.
+				mVertexMap.erase(lb);
+				
+				//	Break while.
+				lb	=	ub;
+			}
+			else
+			{
+				//	Next iteration.
+				lb++;
+			}
+		}
+	}
+}
+
+//-------------------------------------------------------------------------
+//	Compare the coordinates of two vertices.
+//-------------------------------------------------------------------------
+bool	VMI::compareVertices(Vertex *vertices,int	u,	int v)
+{
+	if ((vertices[u].x == vertices[v].x)
+			&&
+			(vertices[u].y == vertices[v].y)
+			&&
+			(vertices[u].z == vertices[v].z))
+	{
+		return	true;
+	}
+	else
+	{
+		return	false;
+	}
+}
+
+//-------------------------------------------------------------------------
+//	Find edge of the simplification sequence.
+//-------------------------------------------------------------------------
+void	VMI::contractInitialMesh(Mesh	*mesh)
+{
+	bool		edge_found;
+	Geometry::MeshSimplificationSequence::Step	step;
+
+	multimap<int,int>::iterator	it0;
+	multimap<int,int>::iterator	lb0;
+	multimap<int,int>::iterator	ub0;
+	multimap<int,int>::iterator	lb1;
+	multimap<int,int>::iterator	ub1;
+
+	std::vector<Geometry::MeshSimplificationSequence::Step> steps;
+
+	Edge		*econ;
+	float		x,y,z;
+	int			*lv1;
+	int			v0;
+	int			v1;
+	int			edge;
+	int			num_edges;
+	Change	*c;
+
+	//	Copy simplification steps of the joined mesh.
+	steps	=	mSequence->mSteps;
+
+	mSequence->mSteps.clear();
+
+	for	(size_t	i	=	0;	i < steps.size(); i++)
+	{
+		step	=	steps[i];
+
+		lb0	=	mVertices.lower_bound(steps[i].mV0);
+		ub0	=	mVertices.upper_bound(steps[i].mV0);
+		lb1	=	mVertices.lower_bound(steps[i].mV1);
+		ub1	=	mVertices.upper_bound(steps[i].mV1);
+
+		edge_found	=	false;
+
+		//	Debug.
+		cout	<<	"step "
+					<<	i
+					<<	" V0: "
+					<<	steps[i].mV0
+					<<	" V1: "
+					<<	steps[i].mV1
+					<<	endl;
+
+		//	Removed vertex.
+		while ((lb1 != ub1) && !edge_found)
+		{
+			//	Real index.
+			v1	=	(*lb1).second;
+
+			lv1	=	edgesAdjToVertex(mesh,v1,&num_edges);
+
+			//	Edje iterator.
+			edge	=	0;
+
+			while	((edge < num_edges) &&	!edge_found)
+			{
+				econ	=	&mesh->edges[lv1[edge]];
+
+				//	Begin of iteration v0.
+				it0	=	lb0;
+
+				//	Remaining vertex.
+				while ((it0 != ub0) &&	!edge_found)
+				{
+					//	Real index.
+					v0	=	(*it0).second;
+					
+					if (compareVertices(mesh->vertices,econ->v,v0))
+					{
+						c = newChange(mesh, econ->u, econ->v);
+
+						edge_found	=	true;
+					}
+					else if (compareVertices(mesh->vertices,econ->u,v0))
+					{
+						c = newChange(mesh, econ->v, econ->u);
+
+						edge_found	=	true;
+					}
+					else
+					{
+						it0++;
+					}
+				}
+
+				edge++;
+			}
+
+			lb1++;
+		}
+
+		if (edge_found)
+		{
+			//	Debug.
+			cout	<<	"Contracting edge of the initial mesh..."	
+						<<	endl
+						<<	"u: "
+						<<	c->u
+						<<	" v: "
+						<<	c->v
+						<<	endl;
+	
+			// Collapse new edge.
+			doChange(mesh, c); // the mesh has been updated.
+
+			// Write Simplification sequence.
+			saveSimplificationSequence(c,0);
+
+			deleteVertexOfMap(mesh, c->u);
+			deleteEdges(mesh, c);
+			modifyEdges(mesh, c);
+			deleteChange(c);
+
+			//	Contract twin vertices.
+			contractTwinVertices(mesh,v1,v0);
+		}
+	}
+}
+
+//-------------------------------------------------------------------------
+//	Find twin vertices and contract them.
+//-------------------------------------------------------------------------
+void VMI::contractTwinVertices(	Mesh	*mesh,
+																int		u,
+																int		v)
+{
+	bool					twin_found;
+	int						edge;
+	int						lonely_vert;
+	int						new_vert;
+	t_map_str			lb;
+	t_map_str			ub;
+	t_map_str			it;
+	_float3_			fu;
+	_float3_			fv;
+	Edge					*econ;
+	float					x,y,z;
+	int						*le;
+	int						num_edges;
+	Change				*c;
+
+	Geometry::GeoVertex	vertex_added;
+
+	if (!compareVertices(mesh->vertices,u,v))
+	{
+		//take_bone_from_vert = v;
+
+		fu	=	_float3_(	mesh->vertices[u].x,
+										mesh->vertices[u].y,
+										mesh->vertices[u].z);
+
+		fv	=	_float3_(	mesh->vertices[v].x,
+										mesh->vertices[v].y,
+										mesh->vertices[v].z);
+
+		//	Find vertices width u coordinates.
+		while ((it = mVertexMap.find(fu)) != mVertexMap.end())
+		{
+			twin_found	=	false;
+
+			lonely_vert	=	(*it).second;
+
+			le	=	edgesAdjToVertex(mesh,lonely_vert,&num_edges);
+
+			//	Find an edge width v coordinates.
+			int	i	=	0;
+
+			while((i < num_edges) && !twin_found)
+			{
+				econ	=	&mesh->edges[le[i]];
+
+				if (compareVertices(mesh->vertices,econ->u,v)
+						||
+						compareVertices(mesh->vertices,econ->v,v))
+				{
+					lb	=	mVertexMap.lower_bound(fv);
+					ub	=	mVertexMap.upper_bound(fv);
+
+					//	For each vertex.
+					while	(lb != ub)
+					{
+						//	If removed vertex is found.
+						if (((*lb).second == econ->u)
+								||
+								((*lb).second == econ->v))
+						{
+							twin_found	=	true;
+
+							//	Break while.
+							lb	=	ub;
+						}
+						else
+						{
+							//	Next iteration.
+							lb++;
+						}
+					}
+				}
+				i++;
+			}
+
+			//	If a twin edge has been found.
+			if (twin_found)
+			{
+				//	Debug.
+				cout	<<	"Twin Collapsed..."	<<	endl;
+
+				//	Compare vertices coordinates.
+				if (compareVertices(mesh->vertices,econ->u,v))
+				{
+					// New edge for the change
+					c = newChange(mesh, econ->v, econ->u);
+
+					//	Debug.
+					cout	<<	"--Reverse--"	<<	endl;
+				}
+				else
+				{
+					// New edge for the change
+					c = newChange (mesh, econ->u, econ->v);
+				}
+
+				// Collapse new edge.
+				doChange(mesh, c); // the mesh has been updated.
+
+				// Write Simplification sequence.
+				saveSimplificationSequence(c,1);
+
+				deleteVertexOfMap(mesh, c->u);
+				deleteEdges(mesh, c);
+				modifyEdges(mesh, c);
+				deleteChange(c);
+			}
+			else
+			{
+				//	Debug.
+				cout	<<	"Collapsing new edge..."	<<	endl;
+
+				x	=	mesh->vertices[v].x;
+				y	=	mesh->vertices[v].y;
+				z	=	mesh->vertices[v].z;
+
+				mesh->vertices = addVertex(	mesh->vertices,
+																		(int *)&mesh->numVertices,
+																		x,
+																		y,
+																		z,
+																		&new_vert);
+				
+				// When a new vertex is added to the mesh, not only the
+				// total number of vertices is increased but also current number
+				mesh->currentNumVertices++;
+
+				//	Adds new vertex to multimap.
+				mVertexMap.insert(t_pair(_float3_(x,y,z),new_vert));
+
+				//	Creates new edge.
+				mesh->edges	=	addEdge(mesh->edges,
+															(int *)&mesh->numEdges,
+															lonely_vert,
+															new_vert,
+															&edge);
+
+				/*
+				//	Debug.
+				cout	<<	"lonely_vert"
+					<<	lonely_vert
+					<<	"("
+					<<	mesh->vertices[lonely_vert].x
+					<<	","
+					<<	mesh->vertices[lonely_vert].y
+					<<	","
+					<<	mesh->vertices[lonely_vert].z
+					<<	")"
+					<<	endl;
+				//	Debug.
+				cout	<<	"new_vert"
+					<<	new_vert
+					<<	"("
+					<<	mesh->vertices[new_vert].x
+					<<	","
+					<<	mesh->vertices[new_vert].y
+					<<	","
+					<<	mesh->vertices[new_vert].z
+					<<	")"
+					<<	endl;
+				*/
+
+				//	We assume here there are the same number of vertices
+				//	and texture coordinates and normals.
+
+				//	Assigns the position of the vertex.
+				vPositions.push_back(Geometry::Vector3(x,y,z));
+
+				//	Assigns a texture coordinate for the vertex.
+				vTexCoords.push_back(vTexCoords[lonely_vert]);
+
+				//	Assigns a normal coordinate for the vertex.
+				vNormals.push_back(vNormals[lonely_vert]);
+
+				//	Adds new vertex information to simplification sequence.
+				vertex_added.id				=	new_vert;
+				vertex_added.bonefrom	=	v;
+
+				vertex_added.position	=	vPositions[new_vert];
+
+				vertex_added.texcoord	=	vTexCoords[new_vert];
+
+				vertex_added.normal	=	vNormals[new_vert];
+
+				mSequence->mNewVertices.push_back(vertex_added);
+
+				// Collapse new edge
+				c = newChange(mesh, lonely_vert, new_vert);
+
+				doChange(mesh, c); // the mesh has been updated
+
+				// Write Simplification sequence.
+				saveSimplificationSequence(c,1);
+
+				deleteVertexOfMap(mesh, c->u);
+				deleteEdges(mesh, c);
+				modifyEdges(mesh, c);
+				deleteChange(c);
+			}
+		}
+	}
+}
+
Index: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/histogram.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/histogram.cpp	(revision 983)
+++ GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/histogram.cpp	(revision 2090)
@@ -9,4 +9,6 @@
 #include "../include/histogram.h"
 #include "../include/metrics.h"
+
+#define WIN_MARGIN 2
 
 using namespace VMI;
@@ -185,7 +187,199 @@
 }
 
+void VMI::getBoundingBox(Change *c, GLfloat min[3], GLfloat max[3]) {
+    GLuint  i, j, t, v;
+    GLfloat maxx = 0.0f, minx = 0.0f, 
+            maxy = 0.0f, miny = 0.0f,
+            maxz = 0.0f, minz = 0.0f;
+    
+    /* get the max/mins */
+    for (i=0; i<(GLuint)c->numMod; i++) {
+        t = c->modified[i].id;
+        
+        for (j=0; j<3; j++) {
+            v = mesh->triangles[t].indices[j];
+            // v
+            if (maxx < mesh->vertices[v].x)
+                maxx = mesh->vertices[v].x;
+            if (minx > mesh->vertices[v].x)
+                minx = mesh->vertices[v].x;
+            
+            if (maxy < mesh->vertices[v].y)
+                maxy = mesh->vertices[v].y;
+            if (miny > mesh->vertices[v].y)
+                miny = mesh->vertices[v].y;
+            
+            if (maxz < mesh->vertices[v].z)
+                maxz = mesh->vertices[v].z;
+            if (minz > mesh->vertices[v].z)
+                minz = mesh->vertices[v].z;
+        }
+    }
+
+    for (i=0; i<(GLuint)c->numDel; i++) {
+        t = c->deleted[i].id;
+        
+        for (j=0; j<3; j++) {
+            v = mesh->triangles[t].indices[j];
+            // v
+            if (maxx < mesh->vertices[v].x)
+                maxx = mesh->vertices[v].x;
+            if (minx > mesh->vertices[v].x)
+                minx = mesh->vertices[v].x;
+            
+            if (maxy < mesh->vertices[v].y)
+                maxy = mesh->vertices[v].y;
+            if (miny > mesh->vertices[v].y)
+                miny = mesh->vertices[v].y;
+            
+            if (maxz < mesh->vertices[v].z)
+                maxz = mesh->vertices[v].z;
+            if (minz > mesh->vertices[v].z)
+                minz = mesh->vertices[v].z;
+        }
+    }
+
+    min[0] = minx;
+    min[1] = miny;
+    min[2] = minz;
+
+    max[0] = maxx;
+    max[1] = maxy;
+    max[2] = maxz;
+}
+
+void VMI::getWindow(GLfloat min[3], GLfloat max[3], int minw[2], int maxw[2]) {
+    GLdouble winx, winy, winz,
+             mv[16], pm[16];
+    GLint vp[4], minx, miny, maxx, maxy;
+
+    glGetDoublev(GL_MODELVIEW_MATRIX, mv);
+    glGetDoublev(GL_PROJECTION_MATRIX, pm);
+    glGetIntegerv(GL_VIEWPORT, vp);
+    
+    /* The eight points of the bounding box */
+    /* Point 1 (min,min,min) */
+    gluProject((GLdouble)min[0], (GLdouble)min[1], (GLdouble)min[2], mv, pm, vp, &winx, &winy, &winz);
+    minx = winx;
+    maxx = winx;
+    miny = winy;
+    maxy = winy;
+
+    /* Point 2 (max,min,min) */
+    gluProject((GLdouble)max[0], (GLdouble)min[1], (GLdouble)min[2], mv, pm, vp, &winx, &winy, &winz);
+    if (winx < minx) minx =winx;
+    if (winx > maxx) maxx =winx;
+    if (winy < miny) miny =winy;
+    if (winy > maxy) maxy =winy;
+
+    /* Point 3 (min,max,min) */
+    gluProject((GLdouble)min[0], (GLdouble)max[1], (GLdouble)min[2], mv, pm, vp, &winx, &winy, &winz);
+    if (winx < minx) minx =winx;
+    if (winx > maxx) maxx =winx;
+    if (winy < miny) miny =winy;
+    if (winy > maxy) maxy =winy;
+
+    /* Point 4 (max,max,min) */
+    gluProject((GLdouble)max[0], (GLdouble)max[1], (GLdouble)min[2], mv, pm, vp, &winx, &winy, &winz);
+    if (winx < minx) minx =winx;
+    if (winx > maxx) maxx =winx;
+    if (winy < miny) miny =winy;
+    if (winy > maxy) maxy =winy;
+
+    /* Point 5 (min,min,max) */
+    gluProject((GLdouble)min[0], (GLdouble)min[1], (GLdouble)max[2], mv, pm, vp, &winx, &winy, &winz);
+    if (winx < minx) minx =winx;
+    if (winx > maxx) maxx =winx;
+    if (winy < miny) miny =winy;
+    if (winy > maxy) maxy =winy;
+
+    /* Point 6 (max,min,max) */
+    gluProject((GLdouble)max[0], (GLdouble)min[1], (GLdouble)max[2], mv, pm, vp, &winx, &winy, &winz);
+    if (winx < minx) minx =winx;
+    if (winx > maxx) maxx =winx;
+    if (winy < miny) miny =winy;
+    if (winy > maxy) maxy =winy;
+
+    /* Point 7 (min,max,max) */
+    gluProject((GLdouble)min[0], (GLdouble)max[1], (GLdouble)max[2], mv, pm, vp, &winx, &winy, &winz);
+    if (winx < minx) minx =winx;
+    if (winx > maxx) maxx =winx;
+    if (winy < miny) miny =winy;
+    if (winy > maxy) maxy =winy;
+
+    /* Point 8 (max,max,max) */
+    gluProject((GLdouble)max[0], (GLdouble)max[1], (GLdouble)max[2], mv, pm, vp, &winx, &winy, &winz);
+    if (winx < minx) minx =winx;
+    if (winx > maxx) maxx =winx;
+    if (winy < miny) miny =winy;
+    if (winy > maxy) maxy =winy;
+
+    minw[0] = minx;
+    minw[1] = miny;
+
+    maxw[0] = maxx;
+    maxw[1] = maxy;
+}
+
+void VMI::getSWHistogramWin(GLuint *histogram, GLubyte *pixels, GLfloat min[3], GLfloat max[3], Change *c) {
+    GLubyte r, g, b, a;
+    GLuint i, t, p, numPixels,
+          *histoAux = (GLuint *)calloc(mesh->numTriangles + 1, sizeof(GLuint));
+    GLint minw[2], maxw[2], ox, oy, h, w;
+
+    getWindow(min, max, minw, maxw);
+
+    w = ABS(maxw[0] - minw[0]);
+    h = ABS(maxw[1] - minw[1]);
+    //printf("w:%d h:%d\n", w, h);
+
+    ox = minw[0];
+    oy = minw[1];
+
+    ox -= WIN_MARGIN;
+    if (ox < 0)  ox = 0;
+    oy -= WIN_MARGIN;
+    if (oy < 0)  oy = 0;
+
+    w += (WIN_MARGIN * 2);
+    if (w > width)  w = width;
+    h += (WIN_MARGIN * 2);
+    if (h > height) h = height;
+
+    //printf("(%d,%d)\n", ox, oy);
+    //printf("w:%d h:%d\n", w, h);
+    //getchar();
+
+    numPixels = w * h;
+    //printf("NumPixels: %d\n", numPixels);
+
+    glReadPixels(ox, oy, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+    for (i=0; i<numPixels; i++) { // pixel i
+        p = i << 2; // 4 * i
+        r = pixels[p];
+        g = pixels[p + 1];
+        b = pixels[p + 2];
+        a = pixels[p + 3];
+
+        t = r + (g << 8) + (b << 16) + (a << 24); // triangle color
+        //printf("pixel:%d (%d,%d,%d,%d) t %d\n", i, r, g, b, a, t);
+
+        histoAux[t]++;   
+    }
+
+    for (i=0; i<(GLuint)c->numMod; i++) {
+        t = (GLuint)c->modified[i].id;
+
+        histogram[t + 1] = histoAux[t + 1]; 
+    }
+
+    free(histoAux);
+    //getchar();
+}
+
 void VMI::getSWHistoByOcclusionQuery(Mesh *mesh, Color *colors, GLuint *histogram) {
     GLuint i, v1, v2, v3;
-    GLint area;
+    GLint area, totalArea = 0;
 
     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
@@ -196,5 +390,5 @@
             glBeginQueryARB(GL_SAMPLES_PASSED_ARB, queries[i]);
             
-            // Render triangle i
+            /* Render triangle i */
             glBegin(GL_TRIANGLES);
             v1= mesh->triangles[i].indices[0];
@@ -226,9 +420,14 @@
             } else {
                 histogram[i + 1] = area;
+
+                totalArea += area;
             }
         }
     }
-    histogram[0] = computeBackgroundArea(mesh, histogram); // Compute area of the background
-
+
+    /* Compute the background area */
+    histogram[0] = (width * height) - totalArea;
+
+    //printf("background area: %d\n", histogram[0]);
 }
 
Index: GTP/trunk/Lib/Geom/shared/GeoTool/include/GeoMeshViewUI.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GeoTool/include/GeoMeshViewUI.h	(revision 1554)
+++ GTP/trunk/Lib/Geom/shared/GeoTool/include/GeoMeshViewUI.h	(revision 2090)
@@ -88,4 +88,6 @@
 using	namespace	std;
 
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 class GeoToolIndexData : public Geometry::IndexData
 {
@@ -131,4 +133,7 @@
 };
 
+//-----------------------------------------------------------------------------
+//	Class User Interface of GeoTool.
+//-----------------------------------------------------------------------------
 class GeoMeshViewUI
 {
@@ -198,4 +203,6 @@
 	inline void cb_menuRenderSolid_i(fltk::Item*, void*);
 	static void cb_menuRenderSolid(fltk::Item*, void*);
+	inline void cb_menuRenderLighting_i(fltk::Item*, void*);
+	static void cb_menuRenderLighting(fltk::Item*, void*);
 	inline void cb_menuRenderCW_i(fltk::Item*, void*);
 	static void cb_menuRenderCW(fltk::Item*, void*);
@@ -361,4 +368,5 @@
 	fltk::Item					*menuRenderWire;
 	fltk::Item					*menuRenderSolid;
+	fltk::Item					*menuRenderLighting;
 	fltk::Item					*menuRenderCW;
 	fltk::Item					*menuRenderCCW;
Index: GTP/trunk/Lib/Geom/shared/GeoTool/include/GeoMeshView.h
===================================================================
--- GTP/trunk/Lib/Geom/shared/GeoTool/include/GeoMeshView.h	(revision 1549)
+++ GTP/trunk/Lib/Geom/shared/GeoTool/include/GeoMeshView.h	(revision 2090)
@@ -34,4 +34,5 @@
 	bool		mWire;
 	bool		mSolid;
+	bool		mLighting;
 	bool		mCW;
 	bool		mCCW;
@@ -95,4 +96,8 @@
 	void	activeSolid(){mSolid	=	true;};
 	void	deactiveSolid(){mSolid	=	false;};
+
+	//	Lighting.
+	void	activeLighting(){mLighting	=	true;};
+	void	deactiveLighting(){mLighting	=	false;};
 
 	//	Clockwise mode.
Index: GTP/trunk/Lib/Geom/shared/GeoTool/src/GeoMeshViewUI.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GeoTool/src/GeoMeshViewUI.cpp	(revision 1560)
+++ GTP/trunk/Lib/Geom/shared/GeoTool/src/GeoMeshViewUI.cpp	(revision 2090)
@@ -4,11 +4,12 @@
 #include "resource.h"
 #include "GeoLodTreeConstructor.h"
+#include <string.h>
 
 using	namespace	Geometry;
 using	namespace	std;
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Menu File Open Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuFileOpen_i(fltk::Item*, void*)
 {
@@ -101,7 +102,7 @@
 
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Repaint the FPS label.
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 void	GeoMeshViewUI::refreshFPS(int fps)
 {
@@ -124,7 +125,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Save callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuFileSave_i(fltk::Item*, void*)
 {
@@ -152,7 +153,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Save As Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuFileSaveAs_i(fltk::Item*, void*)
 {
@@ -215,5 +216,5 @@
 				//-------------------------------------
 
-				mesh_saver->save(mGeoMesh,filename_name(file_name));
+				mesh_saver->save(mGeoMesh,file_name);
 
 				delete	mesh_saver;
@@ -234,7 +235,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Mesh info callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuMeshInfo_i(fltk::Item*, void*)
 {
@@ -253,7 +254,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Mesh Export to OBJ callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuMeshExportOBJ_i(fltk::Item*, void*)
 {
@@ -278,7 +279,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Transform to Shared Vertex callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuTransformSharedVertex_i(fltk::Item*, void*)
 {
@@ -323,7 +324,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Quit Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuFileQuit_i(fltk::Item*, void*)
 {
@@ -338,7 +339,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Undo Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuEditUndo_i(fltk::Item*, void*)
 {
@@ -354,7 +355,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Fit Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuEditFit_i(fltk::Item*, void*)
 {
@@ -370,7 +371,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Rotate Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuEditRotate_i(fltk::Item	*item, void*)
 {	
@@ -402,7 +403,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Pan Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuEditPan_i(fltk::Item	*item, void*)
 {	
@@ -434,7 +435,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Zoom Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuEditZoom_i(fltk::Item*, void*)
 {
@@ -448,7 +449,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Wire Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuRenderWire_i(fltk::Item *item, void*)
 {
@@ -476,7 +477,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Solid Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuRenderSolid_i(fltk::Item	*item, void*)
 {
@@ -504,7 +505,32 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+//	Lighting Callback
+//-------------------------------------------------------------------------
+inline void GeoMeshViewUI::cb_menuRenderLighting_i(fltk::Item	*item, void*)
+{
+	if (item->value())
+	{
+		geoMeshView->activeLighting();
+	}
+	else
+	{
+		geoMeshView->deactiveLighting();
+	}
+									
+	//	Repaint the main window.
+	mMainWindow->redraw();
+}
+
+void GeoMeshViewUI::cb_menuRenderLighting(fltk::Item* o, void* v)
+{
+  ((GeoMeshViewUI*)	(o->parent()->parent()->parent()->user_data()))
+										->
+										cb_menuRenderLighting_i(o,v);
+}
+
+//-------------------------------------------------------------------------
 //	CW callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuRenderCW_i(fltk::Item	*item, void*)
 {
@@ -534,7 +560,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	CCW callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuRenderCCW_i(fltk::Item	*item, void*)
 {
@@ -564,7 +590,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Flat callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuRenderFlat_i(fltk::Item*, void*)
 {
@@ -586,7 +612,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Smooth Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuRenderSmooth_i(fltk::Item*, void*)
 {
@@ -608,7 +634,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Textures callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuRenderTextures_i(fltk::Item*, void*)
 {
@@ -628,7 +654,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Stripify Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuStripify_i(fltk::Item*, void*)
 {
@@ -657,7 +683,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Simplify Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuSimplify_i(fltk::ItemGroup*, void*)
 {
@@ -671,7 +697,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Edge collapse Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuSimplifyEdgeCollapse_i(fltk::Item*, void*)
 {
@@ -701,7 +727,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Leaves collapse Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuSimplifyLeavesCollapse_i(fltk::Item*, void*)
 {
@@ -730,7 +756,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Tree select leaves simplification Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuSelectLeaves_i(fltk::Item*, void*)
 {
@@ -751,7 +777,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Auto Generate LodStrips Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuLodStripsGenerate_i(fltk::Item*, void*)
 {
@@ -781,7 +807,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Auto Generate LodStrips Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuLodTreesGenerate_i(fltk::Item*, void*)
 {
@@ -812,7 +838,7 @@
 
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Visualize LodStrips Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuLodStripsVisualize_i(fltk::Item*, void*)
 {
@@ -874,17 +900,7 @@
 		if (geoMeshLoader->GetTreeSimpSeq() && geoMeshLoader->GetLodStripsData())
 		{
-/*			// select the first triangle-list submesh as leaves submesh
-			int leafsSubMeshID = -1;
-
-			for (int i=0; i<mGeoMesh->mSubMeshCount; i++)
-			{
-				if (mGeoMesh->mSubMesh[i].mType==GEO_TRIANGLE_LIST)
-				{
-					leafsSubMeshID=i;
-					break;
-				}
-			}*/
-
-			setLodTreesLibrary(geoMeshLoader->GetLodStripsData(), geoMeshLoader->GetTreeSimpSeq(), mGeoMesh/*, leafsSubMeshID*/);
+			setLodTreesLibrary(	geoMeshLoader->GetLodStripsData(),
+													geoMeshLoader->GetTreeSimpSeq(),
+													mGeoMesh);
 
 			//	Sets the aplication mode.
@@ -923,7 +939,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Open LodStrip trunk Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuLodTreesOpenLodStripTrunk_i(fltk::Item*, void*)
 {
@@ -937,7 +953,7 @@
 }
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Open leaves simplification Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuLodTreesOpenLeavesSimplification_i(fltk::Item*, void*)
 {
@@ -964,7 +980,7 @@
 
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	About Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_menuHelpAbout_i(fltk::Item*, void*)
 {
@@ -983,7 +999,7 @@
 Index *orig_indices					=	NULL;
 
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 //	Button Process Callback
-//---------------------------------------------------------------------------
+//-------------------------------------------------------------------------
 inline void GeoMeshViewUI::cb_mButtonProcess_i(fltk::Button*, void*)
 {
@@ -1043,7 +1059,4 @@
 					mGeoMesh	=	mesh_aux;
 
-					// Visualize mesh.
-					geoMeshView->setMesh(mGeoMesh);
-
 					//	Simplify the mesh object.
 					if(simplifyEdgeCollapse())
@@ -1051,4 +1064,8 @@
 						geoMeshView->restoreContext();
 					}
+
+					// Visualize mesh.
+					geoMeshView->setMesh(mGeoMesh);
+
 				}
 				break;
@@ -1074,9 +1091,14 @@
 				else
 				{
-					origSubMeshVB=mGeoMesh->mSubMesh[idMeshLeaves].mVertexBuffer->Clone();
-					orig_numindices=mGeoMesh->mSubMesh[idMeshLeaves].mIndexCount;
-					orig_indices=new Index[orig_numindices];
-					for (int i=0; i<orig_numindices; i++)
+					origSubMeshVB	=	mGeoMesh->
+														mSubMesh[idMeshLeaves].mVertexBuffer->Clone();
+
+					orig_numindices	=	mGeoMesh->mSubMesh[idMeshLeaves].mIndexCount;
+					orig_indices		=	new Index[orig_numindices];
+
+					for (int i = 0; i < orig_numindices; i++)
+					{
 						orig_indices[i]=mGeoMesh->mSubMesh[idMeshLeaves].mIndex[i];
+					}
 
 					std::cout << "Simplificando hojas...";
@@ -1102,6 +1124,4 @@
 					//	Gets the mesh Shared Vertex.
 					mGeoMesh	=	mesh_aux;
-
-					geoMeshView->setMesh(mGeoMesh);
 
 					//	Simplify the mesh object.
@@ -1115,4 +1135,5 @@
 					}
 
+					geoMeshView->setMesh(mGeoMesh);
 				}
 				
@@ -1147,7 +1168,4 @@
 					mGeoMesh	=	mesh_aux;
 
-					// Visualize mesh.
-					geoMeshView->setMesh(mGeoMesh);
-
 					//	Simplify the mesh object.
 					if (simplifyEdgeCollapse())
@@ -1159,4 +1177,7 @@
 						activeBuildProcess();
 					}
+
+					// Visualize mesh.
+					geoMeshView->setMesh(mGeoMesh);
 				}
 
@@ -1259,4 +1280,5 @@
 					delete mUndoMesh;
 
+
 					mUndoMesh	=	new Mesh();
 
@@ -1454,4 +1476,5 @@
 	mViewPointDriven->set_visible();
 	mViewPointDriven->activate();
+	mViewPointDriven->clear();
 
 	/*
@@ -1472,6 +1495,8 @@
 	mVerticesNumber->set_visible();
 	mVerticesNumber->activate();
+	mVerticesNumber->clear();
 
 	mMeshReduction->set_visible();
+	mMeshReduction->value(100);
 
 	// Allows floating point.
@@ -1658,5 +1683,5 @@
 
 	//	Deactive VMI option.
-	mViewPointDriven->deactivate();
+	//mViewPointDriven->deactivate();
 
 	mButtonBuild->set_visible();
@@ -1745,10 +1770,16 @@
 }
 
-//---------------------------------------------------------------------------
+//--------------------------------------------------------------------------
 //	Show the mesh info browser.
-//---------------------------------------------------------------------------
+//--------------------------------------------------------------------------
 void	GeoMeshViewUI::showMeshInfo()
 {
-	char	type[10];
+	char						type[10];
+	unsigned	int		group_index;
+	unsigned	int		group_count;
+	unsigned	int		bone_count;
+	fltk::ItemGroup **info_group;
+	
+	group_index	=	0;
 	
 	if (mGeoMesh)
@@ -1759,9 +1790,42 @@
 		ogeometry->begin();
 
-		fltk::ItemGroup **oprueba;
-		oprueba=new fltk::ItemGroup*[mGeoMesh->mSubMeshCount];
+		group_count	=	mGeoMesh->mSubMeshCount;
+
+		//	Add one group for skeleton info.
+		if (mGeoMesh->hasSkeleton)
+		{
+			group_count++;
+		}
+
+		info_group	=	new fltk::ItemGroup*[group_count];
+
+		//	Write skeleton info.
+		if (mGeoMesh->hasSkeleton)
+		{
+			char	*group_name		=	new char[256];
+			char	*skel_name		=	new char[256];
+			char	*bone_assig		=	new char[256];
+			sprintf(group_name,"Skeleton");
+			info_group[group_index]	= new fltk::ItemGroup(group_name);
+
+			info_group[group_index]->begin();
+			sprintf(skel_name,"Name: %s",mGeoMesh->mSkeletonName);
+			new fltk::Item(skel_name);
+			bone_count	=	mGeoMesh->mBones.size();
+			
+			for (int i	=	0;	i < mGeoMesh->mSubMeshCount;	i++)
+			{
+				bone_count	+=	mGeoMesh->mSubMesh[i].mBones.size();
+			}
+			sprintf(bone_assig,"Bone assignamets: %d",bone_count);
+			new fltk::Item(bone_assig);
+			info_group[group_index]->end();
+
+			group_index++;
+		}
+
 		for(int i=0; i<mGeoMesh->mSubMeshCount;i++)
 		{
-			char *cadena=new char[256];
+			char	*group_name	=	new char[256];
 
 			if (geoMeshView->getLeavesSubMesh() >= 0)
@@ -1782,8 +1846,8 @@
 
 			//	Submesh identifier.
-			sprintf(cadena,"SubMesh %d %s",i,type);
+			sprintf(group_name,"SubMesh %d %s",i,type);
 			
-			oprueba[i] = new fltk::ItemGroup(cadena);
-			oprueba[i]->begin();
+			info_group[group_index] = new fltk::ItemGroup(group_name);
+			info_group[group_index]->begin();
 			fltk::Item *sharedGeometry;
 			if (mGeoMesh->mSubMesh[i].mSharedVertexBuffer)
@@ -1838,5 +1902,5 @@
 
 
-			oprueba[i]->end();
+			info_group[group_index]->end();
 		}
 		ogeometry->end();
@@ -1851,7 +1915,7 @@
 }
 
-//---------------------------------------------------------------------------
+//--------------------------------------------------------------------------
 //	Hide the mesh info browser.
-//---------------------------------------------------------------------------
+//--------------------------------------------------------------------------
 void	GeoMeshViewUI::hideMeshInfo()
 {
@@ -1860,7 +1924,7 @@
 }
 
-//---------------------------------------------------------------------------
+//--------------------------------------------------------------------------
 //	Hide the right panel.
-//---------------------------------------------------------------------------
+//--------------------------------------------------------------------------
 void	GeoMeshViewUI::hideRightPanel()
 {
@@ -1875,7 +1939,7 @@
 }
 
-//---------------------------------------------------------------------------
+//--------------------------------------------------------------------------
 //	Get the number of vertices.
-//---------------------------------------------------------------------------
+//--------------------------------------------------------------------------
 size_t	GeoMeshViewUI::getVertexCount(Mesh	*geoMesh)
 {
@@ -2013,4 +2077,5 @@
 	}
 
+	//	Saves OpenGL contex.
 	geoMeshView->saveContext();
 
@@ -2046,4 +2111,5 @@
 
 			//	Simplifica el geomesh -> Parámetro es un factor LOD [0,1].
+
 			mMeshSimplifier->Simplify(percent);
 
@@ -2059,7 +2125,4 @@
 
 			mGeoMesh	=	mMeshSimplifier->GetMesh();
-
-			//	Visualize mesh.
-			geoMeshView->setMesh(mGeoMesh);
 		}
 		else
@@ -2090,7 +2153,4 @@
 
 		mGeoMesh	=	mMeshSimplifier->GetMesh();
-
-		//	Visualize the mesh.
-		geoMeshView->setMesh(mGeoMesh);
 	}
 
@@ -2263,14 +2323,11 @@
 void	GeoMeshViewUI::undo()
 {
+	Mesh	*aux_mesh;
+
 	//	if the undo mesh is not initialized.
 	if	(mUndoMesh != NULL)
 	{
-		//	Deletes the actual mesh.
-		delete	mGeoMesh;
-
-		mGeoMesh	=	new Mesh();
-
-		//	Restore the previous mesh.
-		*mGeoMesh	=	*mUndoMesh;
+		aux_mesh	=	mGeoMesh;
+		mGeoMesh	=	mUndoMesh;
 
 		//	Visualize the mesh.
@@ -2282,4 +2339,9 @@
 		//	Repaint the window.
 		mMainWindow->redraw();
+
+		//	Deletes the actual mesh.
+		delete	aux_mesh;
+
+		mUndoMesh	=	NULL;
 	}
 }
@@ -2466,6 +2528,8 @@
 			menuRenderSolid->clear_value();
 			menuRenderWire->clear_value();
+			menuRenderLighting->set_value();
 			geoMeshView->deactiveSolid();
 			geoMeshView->deactiveWire();
+			geoMeshView->activeLighting();
 
 			//	Fit model in midle.
@@ -2808,4 +2872,9 @@
 
 				{
+					fltk::Item* o = new fltk::Item("Transform to SV");
+					o->callback((fltk::Callback*)cb_menuFileTransformSharedVertex);
+				}
+
+				{
 					menuLoadTextures = new fltk::ItemGroup("Load Textures");
 					o->add(menuLoadTextures);
@@ -2833,5 +2902,4 @@
 					fltk::Item* o = menuEditFit = new fltk::Item("Fit");
 					o->callback((fltk::Callback*)cb_menuEditFit);
-
 				}
 
@@ -2879,4 +2947,10 @@
 					o->type(fltk::Item::RADIO);
 					o->callback((fltk::Callback*)cb_menuRenderSolid);
+				}
+
+				{
+					fltk::Item* o = menuRenderLighting = new fltk::Item("Lighting");
+					o->type(fltk::Item::RADIO);
+					o->callback((fltk::Callback*)cb_menuRenderLighting);
 				}
 
Index: GTP/trunk/Lib/Geom/shared/GeoTool/src/GeoMeshView.cpp
===================================================================
--- GTP/trunk/Lib/Geom/shared/GeoTool/src/GeoMeshView.cpp	(revision 1554)
+++ GTP/trunk/Lib/Geom/shared/GeoTool/src/GeoMeshView.cpp	(revision 2090)
@@ -6,5 +6,5 @@
 
 //---------------------------------------------------------------------------
-//	Hanle events.
+//	Handle events.
 //---------------------------------------------------------------------------
 int	GeoMeshView::handle(int event)
@@ -46,5 +46,5 @@
 						if (mPan)
 						{
-							xshift	=	xshift	+	(x	-	mMouseX);
+							xshift	=	xshift	+	0.01;
 						}
 						else
@@ -59,5 +59,5 @@
 							if (mPan)
 							{
-								xshift	=	xshift	-	(mMouseX	-	x);
+								xshift	=	xshift	-	0.01;
 							}
 							else
@@ -72,5 +72,5 @@
 						if (mPan)
 						{
-							yshift	=	yshift	-	(y - mMouseY);
+							yshift	=	yshift	-	0.01;
 						}
 						else
@@ -85,5 +85,5 @@
 							if (mPan)
 							{
-								yshift	=	yshift	+	(mMouseY	-	y);
+								yshift	=	yshift	+	0.01;
 							}
 							else
@@ -884,4 +884,5 @@
 			geosubmesh->mIndexCount,
 			GL_UNSIGNED_INT,
+
 			mIndexArray[submesh]);
 
@@ -1146,6 +1147,4 @@
 	glLoadIdentity();
 
-	glEnable(GL_LIGHTING);
-
 	//	Frustrum.
 	glViewport(0,0,w(),h());
@@ -1213,11 +1212,15 @@
 	{
 		enableColorStrips();
-		//glDisable(GL_LIGHTING);
 		glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
 		drawGeoMesh(false);
 	}
+
+	if (mLighting)
+	{
+		glEnable(GL_LIGHTING);
+	}
 	else
 	{
-		glEnable(GL_LIGHTING);
+		glDisable(GL_LIGHTING);
 	}
 
@@ -1225,6 +1228,4 @@
 	{
 		disableColorStrips();
-
-		//glDisable(GL_LIGHTING);
 
 		GLfloat color[4];
@@ -1257,5 +1258,4 @@
 		{
 			disableColorStrips();
-			//glEnable(GL_LIGHTING);
 			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 			drawGeoMesh(false);
@@ -1279,8 +1279,8 @@
 	current_texture = ilutGLLoadImage((const ILstring)imgfile);
 
-	if (!current_texture)
-	{
-		fltk::alert("Error loading texture!");
-	}
+//	if (!current_texture)
+//	{
+//		fltk::alert("Error loading texture!");
+//	}
 
 	ilShutDown();
@@ -1295,8 +1295,8 @@
 	current_texture_submesh[isubmesh] = ilutGLLoadImage((const ILstring)imgfile);
 
-	if (!current_texture_submesh[isubmesh])
-	{
-		fltk::alert("Error loading texture!");
-	}
+//	if (!current_texture_submesh[isubmesh])
+//	{
+//		fltk::alert("Error loading texture!");
+//	}
 
 	ilShutDown();
