[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [47242] branches/soc-2012-sushi/source/ blender: Ready methods to calculate the Laplacian Matrix.

Alexander Pinzon apinzonf at gmail.com
Wed May 30 20:49:45 CEST 2012


Revision: 47242
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=47242
Author:   apinzonf
Date:     2012-05-30 18:49:45 +0000 (Wed, 30 May 2012)
Log Message:
-----------
Ready methods to calculate the Laplacian Matrix.
The OpenNL was use for solve sparse syste,.
Ready method which constructs the system of equations.
Ready method to solve the sparse linear system.

Modified Paths:
--------------
    branches/soc-2012-sushi/source/blender/bmesh/CMakeLists.txt
    branches/soc-2012-sushi/source/blender/bmesh/intern/bmesh_opdefines.c
    branches/soc-2012-sushi/source/blender/bmesh/operators/bmo_smooth_laplacian.c
    branches/soc-2012-sushi/source/blender/editors/mesh/editmesh_tools.c

Modified: branches/soc-2012-sushi/source/blender/bmesh/CMakeLists.txt
===================================================================
--- branches/soc-2012-sushi/source/blender/bmesh/CMakeLists.txt	2012-05-30 18:40:35 UTC (rev 47241)
+++ branches/soc-2012-sushi/source/blender/bmesh/CMakeLists.txt	2012-05-30 18:49:45 UTC (rev 47242)
@@ -30,6 +30,7 @@
 	../blenlib
 	../makesdna
 	../../../intern/guardedalloc
+	../../../intern/opennl/extern
 )
 
 set(SRC

Modified: branches/soc-2012-sushi/source/blender/bmesh/intern/bmesh_opdefines.c
===================================================================
--- branches/soc-2012-sushi/source/blender/bmesh/intern/bmesh_opdefines.c	2012-05-30 18:40:35 UTC (rev 47241)
+++ branches/soc-2012-sushi/source/blender/bmesh/intern/bmesh_opdefines.c	2012-05-30 18:49:45 UTC (rev 47242)
@@ -118,6 +118,7 @@
 static BMOpDefine bmo_vertexsmoothlaplacian_def = {
 	"vertexsmoothlaplacian",
 	{{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices
+	 {BMO_OP_SLOT_FLT, "lambda"}, //lambda param
 	 {BMO_OP_SLOT_BOOL, "mirror_clip_x"}, //set vertices close to the x axis before the operation to 0
 	 {BMO_OP_SLOT_BOOL, "mirror_clip_y"}, //set vertices close to the y axis before the operation to 0
 	 {BMO_OP_SLOT_BOOL, "mirror_clip_z"}, //set vertices close to the z axis before the operation to 0

Modified: branches/soc-2012-sushi/source/blender/bmesh/operators/bmo_smooth_laplacian.c
===================================================================
--- branches/soc-2012-sushi/source/blender/bmesh/operators/bmo_smooth_laplacian.c	2012-05-30 18:40:35 UTC (rev 47241)
+++ branches/soc-2012-sushi/source/blender/bmesh/operators/bmo_smooth_laplacian.c	2012-05-30 18:49:45 UTC (rev 47242)
@@ -31,65 +31,166 @@
 #include "BLI_array.h"
 #include "BLI_heap.h"
 #include "BLI_math.h"
+#include "BLI_math_geom.h"
 #include "BLI_smallhash.h"
 
 #include "BKE_customdata.h"
+#include "BKE_mesh.h"
 
 #include "bmesh.h"
 
+#include "ONL_opennl.h"
+
 #include "intern/bmesh_operators_private.h" /* own include */
 
+void init_index(BMesh *bm);
+void compute_weight(BMFace *f, int vid, float lambda);
+float compute_weight_return( BMFace *f, int vid, float lambda);
+static float cotan_weight(float *v1, float *v2, float *v3);
+
 void bmo_vertexsmoothlaplacian_exec(BMesh *bm, BMOperator *op)
 {
 	BMOIter siter;
 	BMIter iter;
 	BMVert *v;
-	BMEdge *e;
-	BLI_array_declare(cos);
-	float (*cos)[3] = NULL;
-	float *co, *co2, clipdist = BMO_slot_float_get(op, "clipdist");
-	int i, j, clipx, clipy, clipz;
-	
-	clipx = BMO_slot_bool_get(op, "mirror_clip_x");
-	clipy = BMO_slot_bool_get(op, "mirror_clip_y");
-	clipz = BMO_slot_bool_get(op, "mirror_clip_z");
+	BMFace *f;
+	int m_vertex_id;
+	NLContext *context;
+	float lambda = BMO_slot_float_get(op, "lambda");
+	float we;
 
-	i = 0;
-	BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) {
-		BLI_array_grow_one(cos);
-		co = cos[i];
+	init_index(bm);
+
+		nlNewContext();
+		context = nlGetCurrent();
+		nlSolverParameteri(NL_NB_VARIABLES, bm->totvert);
+		nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
+		nlSolverParameteri(NL_NB_ROWS, bm->totvert);
+		nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3);
+		nlBegin(NL_SYSTEM);
+		BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) {
+			m_vertex_id = BM_elem_index_get(v);
+			nlSetVariable(0,m_vertex_id, v->co[0]);
+			nlSetVariable(1,m_vertex_id, v->co[1]);
+			nlSetVariable(2,m_vertex_id, v->co[2]);
+		}
+		nlBegin(NL_MATRIX);
+		BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) {
+			m_vertex_id = BM_elem_index_get(v);
+			nlRightHandSideAdd(0, m_vertex_id, v->co[0]);
+			nlRightHandSideAdd(1, m_vertex_id, v->co[1]);
+			nlRightHandSideAdd(2, m_vertex_id, v->co[2]);
+			
+			nlMatrixAdd(m_vertex_id, m_vertex_id, 1.0f);
+			
+			BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+				we = compute_weight_return(f,m_vertex_id,  lambda);
+			}
+
+			BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+				compute_weight(f,m_vertex_id,  lambda/we);
+			}
+		}
 		
-		j  = 0;
-		BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
-			co2 = BM_edge_other_vert(e, v)->co;
-			add_v3_v3v3(co, co, co2);
-			j += 1;
+		nlEnd(NL_MATRIX);
+		nlEnd(NL_SYSTEM);
+		nlSolveAdvanced(NULL, NL_TRUE);
+		BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) {
+			m_vertex_id = BM_elem_index_get(v);
+			v->co[0] =  nlGetVariable(0, m_vertex_id);
+			v->co[1] =  nlGetVariable(1, m_vertex_id);
+			v->co[2] =  nlGetVariable(2, m_vertex_id);
 		}
 		
-		if (!j) {
-			copy_v3_v3(co, v->co);
-			i++;
-			continue;
-		}
+		nlDeleteContext(context);
+}
 
-		mul_v3_fl(co, 1.0f / (float)j);
-		mid_v3_v3v3(co, co, v->co);
+void init_index(BMesh *bm){
+	BM_mesh_elem_index_ensure(bm, BM_VERT);
+}
 
-		if (clipx && fabsf(v->co[0]) <= clipdist)
-			co[0] = 0.0f;
-		if (clipy && fabsf(v->co[1]) <= clipdist)
-			co[1] = 0.0f;
-		if (clipz && fabsf(v->co[2]) <= clipdist)
-			co[2] = 0.0f;
-
-		i++;
+/*
+ *        v_i *
+ *          / | \
+ *         /  |  \
+ *  v_beta*   |   * v_alpha
+ *         \  |  /
+ *          \ | /
+ *            * v_neighbor
+*/
+void compute_weight( BMFace *f, int vid, float lambda){
+	BMIter iter;
+	BMVert *v;
+	BMVert *vf[3];
+	int i;
+	float wa = 0.0f;
+	i = 0;
+	BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) {
+		vf[i] = v;
+		i = i + 1;
 	}
+	
+	for(i=0; i<3; i++){
+		int va = i;
+		int vb = (i+1)%3;
+		int vc = (i+2)%3;
+		int va_id = BM_elem_index_get(vf[va]);
+		int vb_id = BM_elem_index_get(vf[vb]);
+		int vc_id = BM_elem_index_get(vf[vc]);
+		if(va_id == vid ){
+			int vb_id = BM_elem_index_get(vf[vb]);
+			int vc_id = BM_elem_index_get(vf[vc]);
+			wa = lambda*cotan_weight(vf[vb]->co, vf[vc]->co, vf[va]->co);
+			nlMatrixAdd(vid, vc_id, -wa);
+			nlMatrixAdd(vid, vid, wa);
+			wa = lambda*cotan_weight(vf[vc]->co, vf[va]->co, vf[vb]->co);
+			nlMatrixAdd(vid, vb_id, -wa);
+			nlMatrixAdd(vid, vid, wa);
+		}
+	}
+}
 
+float compute_weight_return( BMFace *f, int vid, float lambda){
+	BMIter iter;
+	BMVert *v;
+	BMVert *vf[3];
+	int i;
+	float wa = 0.0f;
 	i = 0;
-	BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) {
-		copy_v3_v3(v->co, cos[i]);
-		i++;
+	BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) {
+		vf[i] = v;
+		i = i + 1;
 	}
+	
+	for(i=0; i<3; i++){
+		int va = i;
+		int vb = (i+1)%3;
+		int vc = (i+2)%3;
+		int va_id = BM_elem_index_get(vf[va]);
+		int vb_id = BM_elem_index_get(vf[vb]);
+		int vc_id = BM_elem_index_get(vf[vc]);
+		if(va_id == vid ){
+			int vb_id = BM_elem_index_get(vf[vb]);
+			int vc_id = BM_elem_index_get(vf[vc]);
+			wa = cotan_weight(vf[vb]->co, vf[vc]->co, vf[va]->co); 
+			wa = wa + cotan_weight(vf[vc]->co, vf[va]->co, vf[vb]->co);
+		}
+	}
+	return wa;
+}
 
-	BLI_array_free(cos);
+static float cotan_weight(float *v1, float *v2, float *v3)
+{
+	float a[3], b[3], c[3], clen;
+
+	sub_v3_v3v3(a, v2, v1);
+	sub_v3_v3v3(b, v3, v1);
+	cross_v3_v3v3(c, a, b);
+
+	clen = len_v3(c);
+
+	if (clen == 0.0f)
+		return 0.0f;
+	
+	return dot_v3v3(a, b) / clen;
 }

Modified: branches/soc-2012-sushi/source/blender/editors/mesh/editmesh_tools.c
===================================================================
--- branches/soc-2012-sushi/source/blender/editors/mesh/editmesh_tools.c	2012-05-30 18:40:35 UTC (rev 47241)
+++ branches/soc-2012-sushi/source/blender/editors/mesh/editmesh_tools.c	2012-05-30 18:49:45 UTC (rev 47242)
@@ -1603,6 +1603,7 @@
 	int mirrx = FALSE, mirry = FALSE, mirrz = FALSE;
 	int i, repeat;
 	float clipdist = 0.0f;
+	float lambda = 0.1f;
 
 	/* mirror before smooth */
 	if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
@@ -1630,13 +1631,14 @@
 	}
 
 	repeat = RNA_int_get(op->ptr, "repeat");
+	lambda = RNA_float_get(op->ptr, "lambda");
 	if (!repeat)
 		repeat = 1;
 	
 	for (i = 0; i < repeat; i++) {
 		if (!EDBM_op_callf(em, op,
-		                   "vertexsmoothlaplacian verts=%hv mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clipdist=%f",
-		                   BM_ELEM_SELECT, mirrx, mirry, mirrz, clipdist))
+		                   "vertexsmoothlaplacian verts=%hv lambda=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clipdist=%f",
+		                   BM_ELEM_SELECT, lambda, mirrx, mirry, mirrz, clipdist))
 		{
 			return OPERATOR_CANCELLED;
 		}
@@ -1667,7 +1669,8 @@
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
-	RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Number of iterations to smooth the mesh", "", 1, INT_MAX);
+	RNA_def_int(ot->srna, "repeat", 1, 1, 50, "Number of iterations to smooth the mesh", "", 1, 50);
+	RNA_def_float(ot->srna, "lambda", 0.1f, 0.001f, 100.0f, "Lambda factor", "", 0.001, 100.0f);
 
 }
 




More information about the Bf-blender-cvs mailing list