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-07-25 22:43:05 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-07-25 22:43:05 +0400
commit4bc32d5ded4362cd5cef36456946428bf099148d (patch)
tree7aee88699dbf963c94e3a237ef21c0977c4011b0
parent66d9c0def922db300cda6d1987f2e0c0d5abd782 (diff)
mesh tool to fill in holes, added in mesh clean menu,
unlike other face creation tools it copies data from surrounding faces.
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py10
-rw-r--r--source/blender/bmesh/CMakeLists.txt1
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c5
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c24
-rw-r--r--source/blender/bmesh/intern/bmesh_operators_private.h1
-rw-r--r--source/blender/bmesh/operators/bmo_fill_holes.c137
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c36
-rw-r--r--source/blender/editors/mesh/mesh_intern.h1
-rw-r--r--source/blender/editors/mesh/mesh_ops.c1
9 files changed, 214 insertions, 2 deletions
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 0ad8cdccca8..18008553368 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -1822,6 +1822,7 @@ class VIEW3D_MT_edit_mesh(Menu):
layout.menu("VIEW3D_MT_edit_mesh_edges")
layout.menu("VIEW3D_MT_edit_mesh_faces")
layout.menu("VIEW3D_MT_edit_mesh_normals")
+ layout.menu("VIEW3D_MT_edit_mesh_clean")
layout.separator()
@@ -2084,6 +2085,15 @@ class VIEW3D_MT_edit_mesh_normals(Menu):
layout.operator("mesh.flip_normals")
+class VIEW3D_MT_edit_mesh_clean(Menu):
+ bl_label = "Clean"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("mesh.fill_holes")
+
+
class VIEW3D_MT_edit_mesh_delete(Menu):
bl_label = "Delete"
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 350c1d71a43..c49c290e81e 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -51,6 +51,7 @@ set(SRC
operators/bmo_extrude.c
operators/bmo_fill_edgeloop.c
operators/bmo_fill_grid.c
+ operators/bmo_fill_holes.c
operators/bmo_hull.c
operators/bmo_inset.c
operators/bmo_join_triangles.c
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index 40c1c956a2e..4d3653b1a82 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -324,6 +324,7 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, c
BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
unsigned int winding[2] = {0, 0};
int i, i_prev = len - 1;
+ BMVert *v_winding[2] = {vert_arr[i_prev], vert_arr[0]};
BLI_assert(len > 2);
@@ -375,8 +376,8 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, c
/* create the face */
return BM_face_create_ngon(
bm,
- vert_arr[(len - 2) + winding[0]],
- vert_arr[(len - 1) + winding[1]],
+ v_winding[winding[0]],
+ v_winding[winding[1]],
edge_arr, len, create_flag);
}
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 784732295ed..70ce3d528c9 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -552,6 +552,29 @@ static BMOpDefine bmo_grid_fill_def = {
BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
};
+
+/*
+ * Fill Holes.
+ *
+ * Fill boundary edges with faces, copying surrounding customdata.
+ */
+static BMOpDefine bmo_holes_fill_def = {
+ "holes_fill",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {"sides", BMO_OP_SLOT_INT}, /* number of face sides to fill */
+ {{'\0'}},
+ },
+ /* slots_out */
+ /* maps new faces to the group numbers they came from */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
+ {{'\0'}},
+ },
+ bmo_holes_fill_exec,
+ BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+};
+
+
/*
* Edge Loop Fill.
*
@@ -1724,6 +1747,7 @@ const BMOpDefine *bmo_opdefines[] = {
&bmo_dissolve_limit_def,
&bmo_dissolve_verts_def,
&bmo_duplicate_def,
+ &bmo_holes_fill_def,
&bmo_edgeloop_fill_def,
&bmo_edgenet_fill_def,
&bmo_edgenet_prepare_def,
diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h
index e6a4760060c..e029ad0d124 100644
--- a/source/blender/bmesh/intern/bmesh_operators_private.h
+++ b/source/blender/bmesh/intern/bmesh_operators_private.h
@@ -58,6 +58,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op);
void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op);
void bmo_duplicate_exec(BMesh *bm, BMOperator *op);
void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op);
+void bmo_holes_fill_exec(BMesh *bm, BMOperator *op);
void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op);
void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op);
void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op);
diff --git a/source/blender/bmesh/operators/bmo_fill_holes.c b/source/blender/bmesh/operators/bmo_fill_holes.c
new file mode 100644
index 00000000000..dca86445219
--- /dev/null
+++ b/source/blender/bmesh/operators/bmo_fill_holes.c
@@ -0,0 +1,137 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Campbell Barton.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/operators/bmo_fill_holes.c
+ * \ingroup bmesh
+ *
+ * Fill boundary edge loop(s) with faces.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_array.h"
+#include "BLI_math.h"
+
+#include "bmesh.h"
+
+#include "intern/bmesh_operators_private.h" /* own include */
+
+#define EDGE_MARK 2
+#define ELE_OUT 4
+
+/**
+ * Clone of BM_face_find_longest_loop that ensures the loop has an adjacent face
+ */
+static BMLoop *bm_face_find_longest_loop_manifold(BMFace *f)
+{
+ BMLoop *longest_loop = NULL;
+ float longest_len = 0.0f;
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+
+ do {
+ if (BM_edge_is_wire(l_iter->e) == false) {
+ const float len = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
+ if (len >= longest_len) {
+ longest_loop = l_iter;
+ longest_len = len;
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ return longest_loop;
+}
+
+static BMFace *bm_face_from_eloop(BMesh *bm, struct BMEdgeLoopStore *el_store)
+{
+ LinkData *node = BM_edgeloop_verts_get(el_store)->first;
+ const int len = BM_edgeloop_length_get(el_store);
+ BMVert **f_verts = BLI_array_alloca(f_verts, len);
+ BMFace *f;
+ BMLoop *l;
+ unsigned int i = 0;
+
+ do {
+ f_verts[i++] = node->data;
+ } while ((node = node->next));
+
+ f = BM_face_create_ngon_verts(bm, f_verts, len, 0, true, false);
+ BM_face_copy_shared(bm, f);
+
+ l = bm_face_find_longest_loop_manifold(f);
+ if (l) {
+ BMFace *f_other = l->radial_next->f;
+ BLI_assert(l->radial_next != l);
+ BM_elem_attrs_copy(bm, bm, f_other, f);
+ }
+
+ return f;
+}
+
+static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
+{
+ return BMO_elem_flag_test((BMesh *)bm_v, e, EDGE_MARK);
+}
+
+void bmo_holes_fill_exec(BMesh *bm, BMOperator *op)
+{
+ ListBase eloops = {NULL, NULL};
+ LinkData *el_store;
+
+ BMEdge *e;
+ int count;
+
+ BMOIter siter;
+
+ const int sides = BMO_slot_int_get(op->slots_in, "sides");
+
+ /* clear tags */
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+
+ /* tag edges that may be apart of loops */
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ BMO_elem_flag_set(bm, e, EDGE_MARK, BM_edge_is_boundary(e));
+ }
+
+ count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, (void *)bm);
+
+ for (el_store = eloops.first; el_store; el_store = el_store->next) {
+ if (BM_edgeloop_is_closed((struct BMEdgeLoopStore *)el_store)) {
+ const int len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store);
+ if ((sides == 0) || (len <= sides)) {
+ BMFace *f;
+
+ f = bm_face_from_eloop(bm, (struct BMEdgeLoopStore *)el_store);
+ BMO_elem_flag_enable(bm, f, ELE_OUT);
+ }
+ }
+ }
+
+ (void)count;
+
+ BM_mesh_edgeloops_free(&eloops);
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_OUT);
+}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 1586138a4d3..538ed862e4e 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -2752,7 +2752,43 @@ void MESH_OT_fill_grid(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+static int edbm_fill_holes_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const int sides = RNA_int_get(op->ptr, "sides");
+
+ if (!EDBM_op_call_and_selectf(
+ em, op,
+ "faces.out", true,
+ "holes_fill edges=%he sides=%i",
+ BM_ELEM_SELECT, sides))
+ {
+ return OPERATOR_CANCELLED;
+ }
+
+ EDBM_update_generic(em, true, true);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_fill_holes(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Fill Holes";
+ ot->idname = "MESH_OT_fill_holes";
+ ot->description = "Fill in holes (boundary edge loops)";
+
+ /* api callbacks */
+ ot->exec = edbm_fill_holes_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "sides", 4, 0, INT_MAX, "Sides", "Number of sides (zero disables)", 0, 100);
+}
static int edbm_beautify_fill_exec(bContext *C, wmOperator *op)
{
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 66079e37b91..c76b9819f75 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -196,6 +196,7 @@ void MESH_OT_knife_cut(struct wmOperatorType *ot);
void MESH_OT_separate(struct wmOperatorType *ot);
void MESH_OT_fill(struct wmOperatorType *ot);
void MESH_OT_fill_grid(struct wmOperatorType *ot);
+void MESH_OT_fill_holes(struct wmOperatorType *ot);
void MESH_OT_beautify_fill(struct wmOperatorType *ot);
void MESH_OT_quads_convert_to_tris(struct wmOperatorType *ot);
void MESH_OT_tris_convert_to_quads(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 4f2924293ea..74aaa58d32d 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -102,6 +102,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_fill);
WM_operatortype_append(MESH_OT_fill_grid);
+ WM_operatortype_append(MESH_OT_fill_holes);
WM_operatortype_append(MESH_OT_beautify_fill);
WM_operatortype_append(MESH_OT_quads_convert_to_tris);
WM_operatortype_append(MESH_OT_tris_convert_to_quads);