[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [49473] branches/soc-2012-bratwurst/source /blender/editors/uvedit: Isomap Unwrapper

Antony Riakiotakis kalast at gmail.com
Wed Aug 1 19:54:15 CEST 2012


Revision: 49473
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=49473
Author:   psy-fi
Date:     2012-08-01 17:54:14 +0000 (Wed, 01 Aug 2012)
Log Message:
-----------
Isomap Unwrapper
=================
* Numerical part, still not functional though.
* eigenvalues seem to be very high I think it's to be expected since I
use MAX_FLOAT for non connected points in the code. Investigating theory
and code to fix. Paper states "for non connected points set distance to
infinite"

Modified Paths:
--------------
    branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer.c
    branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer_isomap.cpp
    branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer_isomap.h

Modified: branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer.c
===================================================================
--- branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer.c	2012-08-01 17:54:08 UTC (rev 49472)
+++ branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer.c	2012-08-01 17:54:14 UTC (rev 49473)
@@ -202,7 +202,7 @@
 			float size[2], trans[2];
 		} pack;
 		struct PChartIsomap {
-			int solverindex;
+			unsigned int do_solution;
 		} isomap;
 	} u;
 
@@ -430,7 +430,7 @@
 	               ((v3->uv[0] - v1->uv[0]) * (v2->uv[1] - v1->uv[1])));
 }
 
-static float p_edge_length(PEdge *e)
+static float p_edge_length_squared(PEdge *e)
 {
 	PVert *v1 = e->vert, *v2 = e->next->vert;
 	float d[3];
@@ -439,8 +439,12 @@
 	d[1] = v2->co[1] - v1->co[1];
 	d[2] = v2->co[2] - v1->co[2];
 
-	return sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
+	return d[0] * d[0] + d[1] * d[1] + d[2] * d[2];
 }
+static float p_edge_length(PEdge *e)
+{
+	return sqrt(p_edge_length_squared(e));
+}
 
 static float p_edge_uv_length(PEdge *e)
 {
@@ -3022,7 +3026,10 @@
 	}
 
 	if ((live && (!select || !deselect)) || (npins == 1)) {
-		chart->u.lscm.context = NULL;
+		if (isomap)
+			chart->u.isomap.do_solution = TRUE;
+		else
+			chart->u.lscm.context = NULL;
 	}
 	else {
 #if 0
@@ -3034,9 +3041,6 @@
 			if (!p_chart_abf_solve(chart))
 				param_warning("ABF solving failed: falling back to LSCM.\n");
 		}
-		if (isomap) {
-			param_new_solver_pool();
-		}
 
 		if (npins <= 1) {
 			/* not enough pins, lets find some ourself */
@@ -3065,23 +3069,58 @@
 
 			chart->u.lscm.context = nlGetCurrent();
 		} else {
-			chart->u.isomap.solverindex = param_new_isomap_solver(chart->nverts);
+			chart->u.isomap.do_solution = TRUE;
 		}
 	}
 }
 
 static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
 {
-	PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
-	PFace *f;
-	float *alpha = chart->u.lscm.abf_alpha;
-	int row;
 	enum UnwrapMethods method = handle->method;
 
 	if (method == UNWRAP_ISOMAP) {
+		PEdge *e;
+		PVert *v;
+		int nverts = chart->nverts;
+		int i, j;
 
+		/* create matrix with squared edge distances */
+		float *dist_map = MEM_mallocN(sizeof(*dist_map)*nverts*nverts, "isomap_distance_map");
 
+		param_isomap_new_solver(nverts);
+
+		/* initialize every point to "infinity" according to the paper.
+		 * since this will make every inner product give infinity as well, initialize to some
+		 * large number instead */
+		for (i = 0; i < nverts; i++)
+			for (j = 0; i < nverts; i++)
+				*(dist_map + i*nverts + j) = (i == j)? 0 : -MAXFLOAT;
+
+		/* for each edge, put the squared distance to the appropriate matrix positions
+		 * for interior edges this will unfortunately be computed twice */
+		for (e = chart->edges; e; e = e->nextlink) {
+			*(dist_map + e->vert->u.id*nverts + e->next->vert->u.id) =
+			*(dist_map + e->next->vert->u.id*nverts + e->vert->u.id) =
+			        -0.5*p_edge_length_squared(e);
+		}
+		if(!param_isomap_solve(dist_map)) {
+			param_warning("ISOMAP failure, matrix solution did not converge.\n");
+		}
+
+		/* load the solution back to pverts */
+		for (v = chart->verts; v; v = v->nextlink)
+			param_isomap_load_uv_solution(v->u.id, v->uv);
+
+		/* cleanup */
+		param_isomap_delete_solver();
+		MEM_freeN(dist_map);
+
 	} else {
+		PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
+		PFace *f;
+		float *alpha = chart->u.lscm.abf_alpha;
+		int row;
+
 		nlMakeCurrent(chart->u.lscm.context);
 
 		nlBegin(NL_SYSTEM);
@@ -3216,10 +3255,7 @@
 
 static void p_chart_lscm_end(PChart *chart, enum UnwrapMethods method)
 {
-	if (method == UNWRAP_ISOMAP) {
-		if (chart->u.isomap.solverindex)
-			;
-	} else {
+	if (method != UNWRAP_ISOMAP) {
 		if (chart->u.lscm.context)
 			nlDeleteContext(chart->u.lscm.context);
 
@@ -3227,11 +3263,11 @@
 			MEM_freeN(chart->u.lscm.abf_alpha);
 			chart->u.lscm.abf_alpha = NULL;
 		}
+
+		chart->u.lscm.context = NULL;
+		chart->u.lscm.pin1 = NULL;
+		chart->u.lscm.pin2 = NULL;
 	}
-
-	chart->u.lscm.context = NULL;
-	chart->u.lscm.pin1 = NULL;
-	chart->u.lscm.pin2 = NULL;
 }
 
 /* Stretch */
@@ -4277,23 +4313,29 @@
 void param_lscm_solve(ParamHandle *handle)
 {
 	PHandle *phandle = (PHandle *)handle;
+	enum UnwrapMethods method = phandle->method;
 	PChart *chart;
 	int i;
 	PBool result;
+	PBool isomap = method == UNWRAP_ISOMAP;
 
 	param_assert(phandle->state == PHANDLE_STATE_LSCM);
 
 	for (i = 0; i < phandle->ncharts; i++) {
+		int do_solution;
 		chart = phandle->charts[i];
 
-		if (chart->u.lscm.context) {
+		do_solution = (isomap)?
+		    chart->u.isomap.do_solution : (chart->u.lscm.context != NULL);
+
+		if (do_solution) {
 			result = p_chart_lscm_solve(phandle, chart);
 
 			if (result && !(chart->flag & PCHART_NOPACK))
 				p_chart_rotate_minimum_area(chart);
 
 			if (!result || (chart->u.lscm.pin1))
-				p_chart_lscm_end(chart, phandle->method);
+				p_chart_lscm_end(chart, method);
 		}
 	}
 }
@@ -4301,8 +4343,8 @@
 void param_lscm_end(ParamHandle *handle)
 {
 	PHandle *phandle = (PHandle *)handle;
+	int i;
 	enum UnwrapMethods method = phandle->method;
-	int i;
 
 	param_assert(phandle->state == PHANDLE_STATE_LSCM);
 
@@ -4313,10 +4355,6 @@
 #endif
 	}
 
-	if (method == UNWRAP_ISOMAP) {
-		param_delete_solver_pool();
-	}
-
 	phandle->state = PHANDLE_STATE_CONSTRUCTED;
 }
 

Modified: branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer_isomap.cpp
===================================================================
--- branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer_isomap.cpp	2012-08-01 17:54:08 UTC (rev 49472)
+++ branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer_isomap.cpp	2012-08-01 17:54:14 UTC (rev 49473)
@@ -23,63 +23,81 @@
 #include <Eigen/Dense>
 #include "uvedit_parametrizer_isomap.h"
 #include <vector>
+#include <iostream>
 
 using namespace std;
+using namespace Eigen;
 
 /**
   containt the Eigen solver and does the actual solving
 */
 class IsomapSolver {
 	public:
-		IsomapSolver (int nverts){}
+		IsomapSolver (int nverts);
 		~IsomapSolver () {}
-};
+		int solve(float dist_matrix[]);
+		void load_uv_solution(int index, float uv[2]);
 
-
-/**
-  maintain the pool of solvers for each chart
-*/
-class SolverPool {
-	public:
-		SolverPool() {}
-		~SolverPool ();
-		IsomapSolver *getSolverAtIndex(int index) {return chart_solvers[index];}
-		int addNewSolver(int nverts);
 	private:
-		vector <IsomapSolver *> chart_solvers;
+		int size;
+		SelfAdjointEigenSolver <MatrixXf> eigensolver;
 };
 
-static SolverPool *solver_pool = NULL;
 
+static IsomapSolver *solver = NULL;
 
 
-/************************ SolverPool Implementation *********************************/
-SolverPool::~SolverPool ()
+
+/************************ Solver Implementation *********************************/
+IsomapSolver::IsomapSolver(int nverts): size(nverts), eigensolver()
 {
-	for (int i = 0; i < chart_solvers.size(); i++) {
-		delete chart_solvers[i];
-	}
 }
 
-int SolverPool::addNewSolver(int nverts)
+int IsomapSolver::solve(float dist_matrix[])
 {
-	chart_solvers.push_back(new IsomapSolver(nverts));
-	return chart_solvers.size() - 1;
+	/* use Map class to reuse memory from C */
+	Map <MatrixXf> map_matrix(dist_matrix, size, size);
+	MatrixXf final;
+	MatrixXf centering_transform;
+
+	centering_transform.setConstant(size, size, 1.0/size);
+	centering_transform = MatrixXf::Identity(size, size) - centering_transform;
+
+	/* in the paper there's also a -1/2 factor but we incorporate this in  dist_matrix
+	 * construction */
+	final = centering_transform * map_matrix * centering_transform;
+
+	eigensolver.compute(final);
+
+	 if (eigensolver.info() != Success)
+		 return false;
+
+	cout << eigensolver.eigenvalues() << endl;
+
+	 return true;
 }
 
+void IsomapSolver::load_uv_solution(int index, float uv[2])
+{
+	uv[0] = eigensolver.eigenvectors()(index, size - 1)*sqrt(eigensolver.eigenvalues()(size - 1));
+	uv[1] = eigensolver.eigenvectors()(index, size - 2)*sqrt(eigensolver.eigenvalues()(size - 2));
+}
 
-int param_new_isomap_solver (int nverts)
+void param_isomap_new_solver(int nverts)
 {
-	return solver_pool->addNewSolver(nverts);
+	solver = new IsomapSolver(nverts);
 }
 
-void param_new_solver_pool (void)
+void param_isomap_delete_solver(void)
 {
-	solver_pool = new SolverPool;
+	delete solver;
 }
 
-void param_delete_solver_pool(void)
+int param_isomap_solve(float dist_matrix[]) {
+	return solver->solve(dist_matrix);
+}
+
+void param_isomap_load_uv_solution(int index, float uv[2])
 {
-	delete solver_pool;
-	solver_pool = 0;
+	solver->load_uv_solution(index, uv);
 }

Modified: branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer_isomap.h
===================================================================
--- branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer_isomap.h	2012-08-01 17:54:08 UTC (rev 49472)
+++ branches/soc-2012-bratwurst/source/blender/editors/uvedit/uvedit_parametrizer_isomap.h	2012-08-01 17:54:14 UTC (rev 49473)
@@ -20,6 +20,11 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/**
+  C interface for isomap unwrapper. The unwrapper utilizes eigen for eigenvalue solving
+  and this file provides the needed funtions to initialize/cleanup/solve/load the solution
+*/
+
 #ifndef UVEDIT_PARAMETRIZER_ISOMAP_H
 #define UVEDIT_PARAMETRIZER_ISOMAP_H
 
@@ -27,9 +32,10 @@
 extern "C" {
 #endif
 
-void param_new_solver_pool(void);
-void param_delete_solver_pool(void);
-int param_new_isomap_solver(int nverts);
+void param_isomap_new_solver(int nverts);
+int param_isomap_solve(float dist_matrix[]);
+void param_isomap_delete_solver(void);
+void param_isomap_load_uv_solution(int index, float uv[2]);
 
 #ifdef __cplusplus
 }




More information about the Bf-blender-cvs mailing list