Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2013-09-05 15:07:49 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-09-05 15:07:49 +0400
commit8f49054b77f4006779a45b4d6977af383662722a (patch)
tree3bd0422b74aff8cbe3086ac3db7ca7e27ef4266b /source/blender/editors/mesh/editmesh_tools.c
parent4228463caada293d7de02d18b630c11a8b0c5479 (diff)
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.
Diffstat (limited to 'source/blender/editors/mesh/editmesh_tools.c')
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c134
1 files changed, 133 insertions, 1 deletions
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 1f5ea9f7b0f..fe9da4b4f1d 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -29,6 +29,8 @@
* \ingroup edmesh
*/
+#include <stddef.h>
+
#include "MEM_guardedalloc.h"
#include "DNA_key_types.h"
@@ -2832,6 +2834,101 @@ void MESH_OT_fill(wmOperatorType *ot)
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 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
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 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
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 @@ void MESH_OT_fill_grid(wmOperatorType *ot)
/* 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)