[Bf-blender-cvs] [31dd6110033] uv_unwrapping_slim_algorithm: UV Unwrapping SLIM: adding harmonic and mvc to uvinitializer

Aurel Gruber noreply at git.blender.org
Tue Mar 14 09:43:06 CET 2017


Commit: 31dd6110033e3f3708efffa1bfb2de53736c1541
Author: Aurel Gruber
Date:   Sun Mar 5 22:43:03 2017 +0100
Branches: uv_unwrapping_slim_algorithm
https://developer.blender.org/rB31dd6110033e3f3708efffa1bfb2de53736c1541

UV Unwrapping SLIM: adding harmonic and mvc to uvinitializer

===================================================================

M	intern/SLIM/src/UVInitializer.cpp
M	intern/SLIM/src/UVInitializer.h
M	intern/SLIM/src/slim_parametrizer.cpp

===================================================================

diff --git a/intern/SLIM/src/UVInitializer.cpp b/intern/SLIM/src/UVInitializer.cpp
index f77fd16ca63..339dcc6c3d5 100644
--- a/intern/SLIM/src/UVInitializer.cpp
+++ b/intern/SLIM/src/UVInitializer.cpp
@@ -7,134 +7,206 @@
 //
 
 #include "UVInitializer.h"
+#include<Eigen/SparseLU>
 
-#include <Eigen/Sparse>
 #include "igl/Timer.h"
 #include "igl/harmonic.h"
+#include "cotmatrix.h"
+#include <iostream>
 
+using namespace std;
+
+double computeAngle(const Eigen::Vector3d &a,const Eigen::Vector3d &b){
+	cout << "points for angle " << a << "   and    " << b << endl;
+	double angle = acos(a.dot(b) / (a.norm() * b.norm()));
+	return angle;
+}
+
+void findVertexToOppositeAnglesCorrespondence(const Eigen::MatrixXi &F,const Eigen::MatrixXd &V, Eigen::SparseMatrix<double> &vertexToFaceIndices){
+
+	typedef Eigen::Triplet<double> T;
+	std::vector<T> coefficients;
+
+	for (int i = 0; i < F.rows(); i++){
+
+		int vertexIndex1 = F(i,0); // retrieve vertex index that is part of face
+		int vertexIndex2 = F(i,1); // retrieve vertex index that is part of face
+		int vertexIndex3 = F(i,2); // retrieve vertex index that is part of face
+
+		double angle1 = computeAngle(V.row(vertexIndex2) - V.row(vertexIndex1), V.row(vertexIndex3) - V.row(vertexIndex1));
+		double angle2 = computeAngle(V.row(vertexIndex3) - V.row(vertexIndex2), V.row(vertexIndex1) - V.row(vertexIndex2));
+		double angle3 = computeAngle(V.row(vertexIndex1) - V.row(vertexIndex3), V.row(vertexIndex2) - V.row(vertexIndex3));
+
+		cout << "vertex " << V.row(vertexIndex1) << " has angle " << angle1 << "for neighbors " << V.row(vertexIndex2) << " and" << V.row(vertexIndex3) << endl << endl;
+		cout << "vertex " << V.row(vertexIndex2) << " has angle " << angle2 << "for neighbors " << V.row(vertexIndex3) << " and" << V.row(vertexIndex1) << endl << endl;
+		cout << "vertex " << V.row(vertexIndex3) << " has angle " << angle3 << "for neighbors " << V.row(vertexIndex1) << " and" << V.row(vertexIndex2) << endl << endl;
+
+		coefficients.push_back(T(vertexIndex1, 2*vertexIndex2, angle3));
+		coefficients.push_back(T(vertexIndex1, 2*vertexIndex3 + 1, angle2));
+
+		coefficients.push_back(T(vertexIndex2, 2*vertexIndex1 + 1, angle3));
+		coefficients.push_back(T(vertexIndex2, 2*vertexIndex3, angle1));
+
+		coefficients.push_back(T(vertexIndex3, 2*vertexIndex1, angle2));
+		coefficients.push_back(T(vertexIndex3, 2*vertexIndex2 + 1, angle1));
+
+	}
+
+	vertexToFaceIndices.setFromTriplets(coefficients.begin(), coefficients.end());
+}
+
+void findVertexToItsAnglesCorrespondence(const Eigen::MatrixXi &F,const Eigen::MatrixXd &V, Eigen::SparseMatrix<double> &vertexToFaceIndices){
+
+	typedef Eigen::Triplet<double> T;
+	std::vector<T> coefficients;
+
+	for (int i = 0; i < F.rows(); i++){
+
+		int vertexIndex1 = F(i,0); // retrieve vertex index that is part of face
+		int vertexIndex2 = F(i,1); // retrieve vertex index that is part of face
+		int vertexIndex3 = F(i,2); // retrieve vertex index that is part of face
+
+		double angle1 = computeAngle(V.row(vertexIndex2) - V.row(vertexIndex1), V.row(vertexIndex3) - V.row(vertexIndex1));
+		double angle2 = computeAngle(V.row(vertexIndex3) - V.row(vertexIndex2), V.row(vertexIndex1) - V.row(vertexIndex2));
+		double angle3 = computeAngle(V.row(vertexIndex1) - V.row(vertexIndex3), V.row(vertexIndex2) - V.row(vertexIndex3));
+
+		coefficients.push_back(T(vertexIndex1, 2*vertexIndex2, angle1));
+		coefficients.push_back(T(vertexIndex1, 2*vertexIndex3 + 1, angle1));
+
+		coefficients.push_back(T(vertexIndex2, 2*vertexIndex1 + 1, angle2));
+		coefficients.push_back(T(vertexIndex2, 2*vertexIndex3, angle2));
+
+		coefficients.push_back(T(vertexIndex3, 2*vertexIndex1, angle3));
+		coefficients.push_back(T(vertexIndex3, 2*vertexIndex2 + 1, angle3));
+
+	}
+
+	vertexToFaceIndices.setFromTriplets(coefficients.begin(), coefficients.end());
+}
 
 /*	AUREL THESIS
 	My own implementation of unfirom laplacian parameterization, for speed comparison and curiosity. Mine is faster then the libigl implementation.
 	Unfortunatly it is a very bad initialisation for our use.
  */
-void UVInitializer::uniform_laplacian(const Eigen::MatrixXi &E, const Eigen::VectorXd &EL, const Eigen::VectorXi &bnd, Eigen::MatrixXd &bnd_uv, Eigen::MatrixXd &UV){
+void UVInitializer::uniform_laplacian(const Eigen::MatrixXi &F, const Eigen::MatrixXd &V, const Eigen::MatrixXi &E, const Eigen::VectorXd &EL, const Eigen::VectorXi &bnd, Eigen::MatrixXd &bnd_uv, Eigen::MatrixXd &UV, Eigen::MatrixXd &CotMatrix){
 
-	igl::Timer timer;
-	timer.start();
+	enum Method{TUTTE, HARMONIC, MVC};
+	Method method = HARMONIC;
 
 	int nVerts = UV.rows();
 	int nEdges = E.rows();
 
+	Eigen::SparseMatrix<double> vertexToAngles(nVerts, nVerts*2);
+
+	switch (method){
+		case HARMONIC:
+			findVertexToOppositeAnglesCorrespondence(F, V, vertexToAngles);
+			break;
+		case MVC:
+			findVertexToItsAnglesCorrespondence(F, V, vertexToAngles);
+			break;
+		case TUTTE:
+			break;
+	}
+
 	int nUnknowns = nVerts - bnd.size();
 	int nKnowns = bnd.size();
 
-	Eigen::SparseMatrix<double> Aint(2 * nUnknowns, 2 * nUnknowns);
-	Eigen::SparseMatrix<double> Abnd(2 * nUnknowns, 2 * nKnowns);
-	Eigen::VectorXd	z(2 * nKnowns);
+	Eigen::SparseMatrix<double> Aint(nUnknowns, nUnknowns);
+	Eigen::SparseMatrix<double> Abnd(nUnknowns, nKnowns);
+	Eigen::VectorXd	z(nKnowns);
 
 	std::vector<Eigen::Triplet<double>> intTripletVector;
 	std::vector<Eigen::Triplet<double>> bndTripletVector;
 
 	int rowindex;
 	int columnindex;
-	int i;
-	int e;
-	double edgeWeight;
-
-
-	int first, second;
-
-	//cout << "		" << timer.getElapsedTime() << " edge-iteration started" << endl;
-
-	for (e = 0; e < nEdges; e++){
-		Eigen::RowVector2i r = E.row(e);
-
-		for (i = 0; i < 2; i++){
-
-			first = r(i);
-			second = r((i + 1) % 2);
-
-			if (first >= nKnowns){//into Aint
-				rowindex = first - nKnowns;
-				edgeWeight = 1; //EL(e);
-
-				intTripletVector.push_back(Eigen::Triplet<double>(rowindex, rowindex, edgeWeight));
-				intTripletVector.push_back(Eigen::Triplet<double>(rowindex + nUnknowns, rowindex + nUnknowns, edgeWeight));
+	double edgeWeight, edgeLength;
+	Eigen::RowVector2i edge;
+
+	int firstVertex, secondVertex;
+
+	for (int e = 0; e < nEdges; e++){
+		edge = E.row(e);
+		edgeLength = EL(e);
+		firstVertex = edge(0);
+		secondVertex = edge(1);
+
+		if (firstVertex >= nKnowns){//into Aint
+
+			rowindex = firstVertex - nKnowns;
+
+			double angle1 = vertexToAngles.coeff(firstVertex, 2*secondVertex);
+			double angle2 = vertexToAngles.coeff(firstVertex, 2*secondVertex+1);
+
+			switch (method){
+				case HARMONIC:
+					edgeWeight = 1/tan(angle1) + 1/tan(angle2);
+					break;
+				case MVC:
+					edgeWeight = tan(angle1/2) + tan(angle2/2);
+					edgeWeight /= edgeLength;
+					break;
+				case TUTTE:
+					edgeWeight = 1;
+					break;
+			}
 
-				//cout << "inserted into INT cc: " << rowindex << ", " << rowindex << endl;
+			cout << "edgeWeight " << edgeWeight << "r.norm: "<< edgeLength << endl;
 
-				if (second >= nKnowns){
-					columnindex = second - nKnowns;
+			intTripletVector.push_back(Eigen::Triplet<double>(rowindex, rowindex, edgeWeight));
 
-					intTripletVector.push_back(Eigen::Triplet<double>(rowindex, columnindex, -edgeWeight));
-					intTripletVector.push_back(Eigen::Triplet<double>(rowindex + nUnknowns, columnindex + nUnknowns, -edgeWeight));
+			if (secondVertex >= nKnowns){ // also an unknown point in the interior
+				columnindex = secondVertex - nKnowns;
 
-					//cout << "inserted into INT rc: " << rowindex << ", " << columnindex << endl;
-				} else {
-					columnindex = second;
-					bndTripletVector.push_back(Eigen::Triplet<double>(rowindex, columnindex, -edgeWeight));
-					bndTripletVector.push_back(Eigen::Triplet<double>(rowindex + nUnknowns, columnindex + nKnowns, -edgeWeight));
+				intTripletVector.push_back(Eigen::Triplet<double>(rowindex, columnindex, -edgeWeight));
 
-					//cout << "inserted into BND rc: " << rowindex << ", " << columnindex << endl;
-				}
+			} else { // known point on the border
+				columnindex = secondVertex;
+				bndTripletVector.push_back(Eigen::Triplet<double>(rowindex, columnindex, edgeWeight));
 			}
+
 		}
 	}
 
 
-	//cout << "		" << timer.getElapsedTime() << " edge-iteration ended" << endl;
-
 	Aint.setFromTriplets(intTripletVector.begin(), intTripletVector.end());
 	Aint.makeCompressed();
 
-	//cout << "		" << timer.getElapsedTime() << " Aint set & compressed" << endl;
-
 	Abnd.setFromTriplets(bndTripletVector.begin(), bndTripletVector.end());
 	Abnd.makeCompressed();
 
-	//cout << "		" << timer.getElapsedTime() << " Abnd set & compressed" << endl;
-
-	//cout << " bnd " << endl << bnd << endl;
+	//cout << "Aint before: " << endl << Aint.toDense() << endl;
+	//cout << "Abnd before: " << endl << Abnd.toDense() << endl;
 
-	//cout << " bnd_uv " << endl << bnd_uv << endl;
-
-	for (int zindex = 0; zindex < nKnowns; zindex++){
-		z(zindex) = bnd_uv(bnd(zindex), 0);
-		z(zindex + nKnowns) = bnd_uv(bnd(zindex), 1);
+	for (int i = 0; i < nUnknowns; i++){
+		double factor = Aint.coeff(i, i);
+		Aint.row(i) /= factor;
+		Abnd.row(i) /= factor;
 	}
 
-	//cout << "		" << timer.getElapsedTime() << " z created" << endl;
+	//cout << "Aint: " << endl << Aint.toDense() << endl;
+	//cout << "Abnd: " << endl << Abnd.toDense() << endl;
 
-	Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
+	Eigen::SparseLU<Eigen::SparseMatrix<double>> solver;
 	solver.compute(Aint);
 
+	for (int i = 0; i<2; i++){// solve for u and v coordinates
 
-	//cout << "		" << timer.getElapsedTime() << " solver precomputed" << endl;
-
-	Eigen::VectorXd b = Abnd*z;
-
-
-	//cout << "		" << timer.getElapsedTime() << " b cast" << endl;
+		for (int zindex = 0; zindex < nKnowns; zindex++){
+			z(zindex) = bnd_uv(bnd(zindex), i);
+		}
 
-	Eigen::VectorXd uvs;
-	uvs = solver.solve(-b);
+		Eigen::VectorXd b = Abnd*z;
 
-	//cout << "		" << timer.getElapsedTime() << " solved!" << endl;
+		Eigen::VectorXd uvs;
+		uvs = solver.solve(b);
 
-	Eigen::VectorXd bnd_x = bnd_uv.col(0);
-	Eigen::VectorXd bnd_y = bnd_uv.col(1);
-	Eigen::VectorXd int_x = uvs.head(uvs.size() / 2);
-	Eigen::VectorXd int_y = uvs.tail(uvs.size() / 2);
+		Eigen::VectorXd boundary = bnd_uv.col(i);
+

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list