[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [39238] branches/soc-2011-onion/source/ blender/editors/sculpt_paint/paint_uv.c: Add laplacian relaxation code by farsthary with some renames and removes of inneeded code such as mirror modifier and mirror rditing handling .

Antony Riakiotakis kalast at gmail.com
Wed Aug 10 00:55:10 CEST 2011


Revision: 39238
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=39238
Author:   psy-fi
Date:     2011-08-09 22:55:10 +0000 (Tue, 09 Aug 2011)
Log Message:
-----------
Add laplacian relaxation code by farsthary with some renames and removes of inneeded code such as mirror modifier and mirror rditing handling. I am going to adapt this to uvs but biggest problem is lack of edge data for uv islands. This is going to introduce a big setup step in operator initialization so that this can be implemented. Maybe uv smoothing should be its own mode instead so that this happens only once(during mode switch)?

Modified Paths:
--------------
    branches/soc-2011-onion/source/blender/editors/sculpt_paint/paint_uv.c

Modified: branches/soc-2011-onion/source/blender/editors/sculpt_paint/paint_uv.c
===================================================================
--- branches/soc-2011-onion/source/blender/editors/sculpt_paint/paint_uv.c	2011-08-09 21:32:46 UTC (rev 39237)
+++ branches/soc-2011-onion/source/blender/editors/sculpt_paint/paint_uv.c	2011-08-09 22:55:10 UTC (rev 39238)
@@ -78,8 +78,279 @@
 typedef struct UvAdjacencyEdge {
 	UvAdjacencyElement *uv1;
 	UvAdjacencyElement *uv2;
+	/* flag whether edge is boundary */
+	char flag;
 }UvAdjacencyEdge;
 
+/*********** Improved Laplacian Relaxation Operator ************************/
+/* Original code by Raul "farsthary"
+ * adapted to uv smoothing by Antony Riakiatakis
+ */
+
+typedef struct Temp_VertexData{
+	float sum_co[3], p[3], b[3], sum_b[3];
+	int ncounter;
+}Temp_VertexData;
+
+void set_border_flag(struct EditMesh *em){
+	EditFace *efa;
+	EditEdge *eed;
+
+	/* clear flag */
+	for (efa=em->faces.first;efa;efa=efa->next){
+		efa->e1->f2 = 0;
+		efa->e2->f2 = 0;
+		efa->e3->f2 = 0;
+		if (efa->e4) efa->e4->f2 = 0;
+	}
+	/* find frontier edges, not shared by other faces */
+	for (efa=em->faces.first;efa;efa=efa->next){
+		efa->e1->f2++;
+		efa->e2->f2++;
+		efa->e3->f2++;
+		if (efa->e4) efa->e4->f2++;
+	}
+
+	/* clear flag verts */
+	for (eed = em->edges.first; eed; eed = eed->next){
+		eed->v1->f2 = 0;
+			eed->v2->f2 = 0;
+	}
+	/* propagate fromtier selection to verts */
+	for (eed = em->edges.first; eed; eed = eed->next){
+		if (eed->f2 == 1){ //is frontier
+			eed->v1->f2 = 1;
+			eed->v2->f2 = 1;
+		}
+	}
+}
+
+
+void HC_relaxation(bContext *C, wmOperator *op, int edges){
+	Object *obedit= CTX_data_edit_object(C);
+	EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+	EditVert *eve, *eve_mir = NULL;
+	EditEdge *eed;
+	Temp_VertexData *adr, *adror, *data;
+	float fvec[3], diff[3], end[3], delta[3], prev_co[3];
+	int index;
+
+	if (edges) set_border_flag(em);
+
+	adr=adror=(Temp_VertexData *)MEM_callocN((em->totvert)* sizeof(Temp_VertexData), "Temporal data");
+
+	/* asigning memory */
+	eve= em->verts.first;
+	while(eve) {
+		eve->tmp.p = adr;
+		adr++;
+		eve= eve->next;
+	}
+
+	/* clear editvert old_co */
+	eve= em->verts.first;
+	while(eve){
+		data = ((Temp_VertexData *)eve->tmp.p);
+		zero_v3(data->sum_co);
+		zero_v3(data->sum_b);
+		zero_v3(data->p);
+
+		data->ncounter = 0; //count
+
+		eve= eve->next;
+	}
+
+	/* counting neighbors */
+	for (eed = em->edges.first; eed; eed = eed->next){
+		((Temp_VertexData *)eed->v1->tmp.p)->ncounter++;
+		((Temp_VertexData *)eed->v2->tmp.p)->ncounter++;
+
+		add_v3_v3(((Temp_VertexData *)eed->v2->tmp.p)->sum_co, eed->v1->co);
+		add_v3_v3(((Temp_VertexData *)eed->v1->tmp.p)->sum_co, eed->v2->co);
+	}
+
+	for (eve = em->verts.first; eve; eve = eve->next){
+		data = ((Temp_VertexData *)eve->tmp.p);
+
+		copy_v3_v3(diff,data->sum_co);
+		mul_v3_fl(diff,1.f/data->ncounter);
+		copy_v3_v3(data->p,diff);
+
+		data->b[0] = diff[0] - eve->co[0];
+		data->b[1] = diff[1] - eve->co[1];
+		data->b[2] = diff[2] - eve->co[2];
+	}
+
+	for (eed = em->edges.first; eed; eed = eed->next){
+		add_v3_v3(((Temp_VertexData *)eed->v1->tmp.p)->sum_b, ((Temp_VertexData *)eed->v2->tmp.p)->b);
+		add_v3_v3(((Temp_VertexData *)eed->v2->tmp.p)->sum_b, ((Temp_VertexData *)eed->v1->tmp.p)->b);
+	}
+
+	for (eve = em->verts.first; eve; eve = eve->next){
+		data = ((Temp_VertexData *)eve->tmp.p);
+
+		if (!eve->f2 && (eve->f & SELECT)){
+			eve->co[0] = data->p[0] - 0.5f*(data->b[0] + data->sum_b[0]/data->ncounter);
+			eve->co[1] = data->p[1] - 0.5f*(data->b[1] + data->sum_b[1]/data->ncounter);
+			eve->co[2] = data->p[2] - 0.5f*(data->b[2] + data->sum_b[2]/data->ncounter);
+		}
+
+		/* clip if needed by mirror modifier */
+		if (eve->f2) {
+			if (eve->f2 & 4) {
+				eve->co[0]= 0.0f;
+			}
+			if (eve->f2 & 8) {
+				eve->co[1]= 0.0f;
+			}
+			if (eve->f2 & 16) {
+				eve->co[2]= 0.0f;
+			}
+		}
+
+		eve->tmp.p= NULL;
+		index++;
+	}
+
+	BKE_mesh_end_editmesh(obedit->data, em);
+	MEM_freeN(adror);
+
+	DAG_id_tag_update(obedit->data, 0);
+	WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+	return OPERATOR_FINISHED;
+}
+
+static int smooth_laplacian_uv(bContext *C, wmOperator *op, int edges)
+{
+	Object *obedit= CTX_data_edit_object(C);
+	EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+	EditVert *eve, *eve_mir = NULL;
+	EditEdge *eed;
+	Temp_VertexData *adr, *adror, *data;
+	float fvec[3], diff[3], end[3], delta[3], prev_co[3];
+	int index =0;
+
+	adr=adror=(Temp_VertexData *)MEM_callocN((em->totvert)* sizeof(Temp_VertexData), "Temporal data");
+
+	/* asigning memory */
+	eve= em->verts.first;
+	while(eve) {
+		eve->tmp.p = adr;
+		adr++;
+		eve= eve->next;
+	}
+	if (edges) set_border_flag(em);
+
+	/* clear editvert old_co */
+	eve= em->verts.first;
+	while(eve){
+		data = ((Temp_VertexData *)eve->tmp.p);
+		zero_v3(data->sum_co);
+		data->ncounter = 0;
+
+		eve= eve->next;
+	}
+
+	eed= em->edges.first;
+	while(eed){
+		((Temp_VertexData *)eed->v1->tmp.p)->ncounter++;
+		((Temp_VertexData *)eed->v2->tmp.p)->ncounter++;
+
+		add_v3_v3(((Temp_VertexData *)eed->v2->tmp.p)->sum_co, eed->v1->co);
+		add_v3_v3(((Temp_VertexData *)eed->v1->tmp.p)->sum_co, eed->v2->co);
+
+		eed = eed->next;
+	}
+
+	index= 0;
+	eve= em->verts.first;
+	while(eve){
+		if (!eve->f2 && (eve->f & SELECT)){
+			data = ((Temp_VertexData *)eve->tmp.p);
+			copy_v3_v3(prev_co,eve->co);
+			mul_v3_fl(data->sum_co, 1.f/data->ncounter);
+			copy_v3_v3(eve->co, data->sum_co);
+
+			/* remove movement along vertex normal */
+			sub_v3_v3v3(delta, eve->co,prev_co);
+			project_v3_v3v3(delta, delta, eve->no);
+			sub_v3_v3v3(eve->co,eve->co,delta);
+		}
+
+		/* clip if needed by mirror modifier */
+		if (eve->f2) {
+			if (eve->f2 & 4) {
+				eve->co[0]= 0.0f;
+			}
+			if (eve->f2 & 8) {
+				eve->co[1]= 0.0f;
+			}
+			if (eve->f2 & 16) {
+				eve->co[2]= 0.0f;
+			}
+		}
+
+		eve->tmp.p= NULL;
+		eve= eve->next;
+		index++;
+	}
+
+	BKE_mesh_end_editmesh(obedit->data, em);
+	MEM_freeN(adror);
+
+	DAG_id_tag_update(obedit->data, 0);
+	WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+	return OPERATOR_FINISHED;
+}
+
+static int relaxation_vertex_exec(bContext *C, wmOperator *op)
+{
+	int repeat = RNA_int_get(op->ptr, "repeat");
+	int edges = RNA_int_get(op->ptr, "edges");
+	int relax = RNA_int_get(op->ptr, "relax");
+	int i;
+
+	if (!repeat) repeat = 1;
+
+	for (i=0; i<repeat; i++) {
+		if (relax == 1) HC_relaxation(C, op, edges);
+		else smooth_laplacian_uv(C, op, edges); //default
+	}
+
+	return OPERATOR_FINISHED;
+}
+
+#define SEL_LAPLACIAN 0
+#define SEL_HC        1
+
+static EnumPropertyItem select_all_smothings[] = {
+		{SEL_LAPLACIAN, "LAPLACIAN", 0, "Laplacian", "Improved laplacian relaxation with no shrinkage"},
+		{SEL_HC, "HC", 0, "HC Relaxation", "HC Relaxation with low shrinkage"},
+		{0, NULL, 0, NULL, NULL}
+	};
+
+void MESH_OT_relaxation_smooth(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Laplacian Smooth";
+	ot->description= "Vertices relaxation with low shrinkage";
+	ot->idname= "MESH_OT_relaxation_smooth";
+
+	/* api callbacks */
+	ot->exec= relaxation_vertex_exec;
+	ot->poll= ED_operator_editmesh;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+	RNA_def_enum(ot->srna, "relax", select_all_smothings, SEL_LAPLACIAN, "Relaxation schemes", "Select relaxation scheme to execute");
+	RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Smooth Iterations", "", 1, INT_MAX);
+	RNA_def_boolean(ot->srna, "edges", 1, "Preserve border", "Preserves shape's edges");
+}
+
+
 /* custom data for uv smoothing brush */
 typedef struct SmoothBrushData{
 	/* All uvs of the mesh */




More information about the Bf-blender-cvs mailing list