[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [59826] trunk/blender/source/blender/ editors/mesh/editmesh_tools.c: grid-fill can now fill a single, closed edge loop.

Campbell Barton ideasman42 at gmail.com
Thu Sep 5 13:07:49 CEST 2013


Revision: 59826
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=59826
Author:   campbellbarton
Date:     2013-09-05 11:07:49 +0000 (Thu, 05 Sep 2013)
Log Message:
-----------
grid-fill can now fill a single, closed edge loop.
the active vertex is used when possible, else the corner vertex is detected.

this should replace the grid-fill-manager addon by Alexander Nedovizin.

Modified Paths:
--------------
    trunk/blender/source/blender/editors/mesh/editmesh_tools.c

Modified: trunk/blender/source/blender/editors/mesh/editmesh_tools.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_tools.c	2013-09-05 11:07:30 UTC (rev 59825)
+++ trunk/blender/source/blender/editors/mesh/editmesh_tools.c	2013-09-05 11:07:49 UTC (rev 59826)
@@ -29,6 +29,8 @@
  *  \ingroup edmesh
  */
 
+#include <stddef.h>
+
 #include "MEM_guardedalloc.h"
 
 #include "DNA_key_types.h"
@@ -2832,6 +2834,101 @@
 	RNA_def_boolean(ot->srna, "use_beauty", true, "Beauty", "Use best triangulation division");
 }
 
+/* -------------------------------------------------------------------- */
+/* Grid Fill (and helper functions) */
+
+static bool bm_edge_test_fill_grid_cb(BMEdge *e, void *UNUSED(bm_v))
+{
+	return BM_elem_flag_test_bool(e, BM_ELEM_TAG);
+}
+
+static float edbm_fill_grid_vert_tag_angle(BMVert *v)
+{
+	BMIter iter;
+	BMEdge *e_iter;
+	BMVert *v_pair[2];
+	int i = 0;
+	BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
+		if (BM_elem_flag_test(e_iter, BM_ELEM_TAG)) {
+			v_pair[i++] = BM_edge_other_vert(e_iter, v);
+		}
+	}
+	BLI_assert(i == 2);
+
+	return fabsf((float)M_PI - angle_v3v3v3(v_pair[0]->co, v->co, v_pair[1]->co));
+}
+
+/**
+ * non-essential utility function to select 2 open edge loops from a closed loop.
+ */
+static void edbm_fill_grid_prepare(BMesh *bm, int span, int offset)
+{
+	BMEdge *e;
+	BMIter iter;
+	int count;
+
+	ListBase eloops = {NULL};
+	struct BMEdgeLoopStore *el_store;
+	// LinkData *el_store;
+
+	/* select -> tag */
+	BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+		BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
+	}
+
+	count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_fill_grid_cb, bm);
+	el_store = eloops.first;
+
+	if (count == 1 && BM_edgeloop_is_closed(el_store) && (BM_edgeloop_length_get(el_store) & 1) == 0) {
+		/* be clever! detect 2 edge loops from one closed edge loop */
+		const int verts_len = BM_edgeloop_length_get(el_store);
+		ListBase *verts = BM_edgeloop_verts_get(el_store);
+		BMVert *v_act = BM_mesh_active_vert_get(bm);
+		LinkData *v_act_link;
+		BMEdge **edges = MEM_mallocN(sizeof(*edges) * verts_len, __func__);
+		int i;
+
+		if (v_act && (v_act_link = BLI_findptr(verts, v_act, offsetof(LinkData, data)))) {
+			/* pass */
+		}
+		else {
+			/* find the vertex with the best angle (a corner vertex) */
+			LinkData *v_link, *v_link_best = NULL;
+			float angle_best = -1.0f;
+			for (v_link = verts->first; v_link; v_link = v_link->next) {
+				const float angle = edbm_fill_grid_vert_tag_angle(v_link->data);
+				if ((angle > angle_best) || (v_link_best == NULL)) {
+					angle_best = angle;
+					v_link_best = v_link;
+				}
+			}
+
+			v_act_link = v_link_best;
+			v_act = v_act_link->data;
+		}
+
+		if (offset != 0) {
+			v_act_link = BLI_findlink(verts, offset);
+			v_act = v_act_link->data;
+		}
+
+		/* set this vertex first */
+		BLI_rotatelist(verts, v_act_link);
+		BM_edgeloop_edges_get(el_store, edges);
+
+		/* un-flag 'rails' */
+		for (i = 0; i < span; i++) {
+			BM_elem_flag_disable(edges[i], BM_ELEM_TAG);
+			BM_elem_flag_disable(edges[(verts_len / 2) + i], BM_ELEM_TAG);
+		}
+
+		MEM_freeN(edges);
+	}
+	/* else let the bmesh-operator handle it */
+
+	BM_mesh_edgeloops_free(&eloops);
+}
+
 static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
 {
 	BMOperator bmop;
@@ -2841,9 +2938,36 @@
 	const int totedge_orig = em->bm->totedge;
 	const int totface_orig = em->bm->totface;
 
+	const bool use_prepare = true;
+
+	if (use_prepare) {
+		/* use when we have a single loop selected */
+		PropertyRNA *prop_span = RNA_struct_find_property(op->ptr, "span");
+		PropertyRNA *prop_offset = RNA_struct_find_property(op->ptr, "offset");
+
+		const int clamp = em->bm->totvertsel;
+		int span;
+		int offset;
+
+		if (RNA_property_is_set(op->ptr, prop_span)) {
+			span = RNA_property_int_get(op->ptr, prop_span);
+			span = min_ii(span, (clamp / 2) - 1);
+		}
+		else {
+			span = clamp / 4;
+		}
+		RNA_property_int_set(op->ptr, prop_span, span);
+
+		offset = RNA_property_int_get(op->ptr, prop_offset);
+		offset = positive_mod(offset, clamp);
+
+		/* in simple cases, move selection for tags, but also support more advanced cases */
+		edbm_fill_grid_prepare(em->bm, span, offset);
+	}
+
 	if (!EDBM_op_init(em, &bmop, op,
 	                  "grid_fill edges=%he mat_nr=%i use_smooth=%b",
-	                  BM_ELEM_SELECT, em->mat_nr, use_smooth))
+	                  use_prepare ? BM_ELEM_TAG : BM_ELEM_SELECT, em->mat_nr, use_smooth))
 	{
 		return OPERATOR_CANCELLED;
 	}
@@ -2871,6 +2995,8 @@
 
 void MESH_OT_fill_grid(wmOperatorType *ot)
 {
+	PropertyRNA *prop;
+
 	/* identifiers */
 	ot->name = "Grid Fill";
 	ot->description = "Fill grid from two loops";
@@ -2882,6 +3008,12 @@
 
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+	/* properties */
+	prop = RNA_def_int(ot->srna, "span", 1, 1, INT_MAX, "Span", "Number of sides (zero disables)", 1, 100);
+	RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+	prop = RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "Number of sides (zero disables)", -100, 100);
+	RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 
 static int edbm_fill_holes_exec(bContext *C, wmOperator *op)




More information about the Bf-blender-cvs mailing list