[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