[Bf-blender-cvs] [7bb2599] soc-2013-paint: Add mesh tool to split faces by wire edges (face menu)

Campbell Barton noreply at git.blender.org
Sat Jul 12 12:44:52 CEST 2014


Commit: 7bb2599c75cd44a0395b0bd13b76f82f7ad38fab
Author: Campbell Barton
Date:   Fri Jul 11 10:32:33 2014 +1000
https://developer.blender.org/rB7bb2599c75cd44a0395b0bd13b76f82f7ad38fab

Add mesh tool to split faces by wire edges (face menu)

This can be used in a similar way to the knife tool, but the edges are manually setup first.

===================================================================

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/editors/mesh/CMakeLists.txt
A	source/blender/editors/mesh/editmesh_intersect.c
M	source/blender/editors/mesh/mesh_intern.h
M	source/blender/editors/mesh/mesh_ops.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index e249303..1079c50 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2278,6 +2278,7 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
         layout.operator("mesh.poke")
         layout.operator("mesh.quads_convert_to_tris")
         layout.operator("mesh.tris_convert_to_quads")
+        layout.operator("mesh.face_split_by_edges")
 
         layout.separator()
 
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 6bf9d5a..0cb2dd1 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -45,6 +45,7 @@ set(SRC
 	editmesh_bisect.c
 	editmesh_extrude.c
 	editmesh_inset.c
+	editmesh_intersect.c
 	editmesh_knife.c
 	editmesh_knife_project.c
 	editmesh_loopcut.c
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
new file mode 100644
index 0000000..f11ef66
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -0,0 +1,276 @@
+/*
+ * ***** 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/mesh/editmesh_intersect.c
+ *  \ingroup edmesh
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+
+#include "BLI_math.h"
+#include "BLI_array.h"
+#include "BLI_linklist_stack.h"
+
+
+#include "BKE_context.h"
+#include "BKE_editmesh.h"
+
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+
+#include "intern/bmesh_private.h"
+
+#include "mesh_intern.h"  /* own include */
+
+
+
+/* -------------------------------------------------------------------- */
+/* Face Split by Edges */
+
+
+/** \name Face/Edge Split
+ * \{ */
+
+static void bm_face_split_by_edges(BMesh *bm, BMFace *f, const char hflag)
+{
+	BMEdge **edge_net = NULL;
+	BLI_array_declare(edge_net);
+
+	const int f_index = BM_elem_index_get(f);
+
+	BMLoop *l_iter;
+	BMLoop *l_first;
+	BMVert *v;
+
+	BMFace **face_arr;
+	int face_arr_len;
+
+	/* likely this will stay very small
+	 * all verts pushed into this stack _must_ have their previous edges set! */
+	BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
+	BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
+
+
+	/* collect all edges */
+	l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+	do {
+		BMIter iter;
+		BMEdge *e;
+
+		BM_ITER_ELEM (e, &iter, l_iter->v, BM_EDGES_OF_VERT) {
+			if (BM_elem_flag_test(e, hflag) &&
+			    (BM_elem_index_get(e) == f_index))
+			{
+				BMVert *v;
+				v = BM_edge_other_vert(e, l_iter->v);
+				v->e = e;
+
+				BLI_SMALLSTACK_PUSH(vert_stack, v);
+				BLI_array_append(edge_net, e);
+			}
+		}
+	} while ((l_iter = l_iter->next) != l_first);
+
+
+
+	/* now assign all */
+	/* pop free values into the next stack */
+	while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
+		BMIter eiter;
+		BMEdge *e_next;
+
+		BM_ITER_ELEM (e_next, &eiter, v, BM_EDGES_OF_VERT) {
+			if (BM_elem_flag_test(e_next, hflag) &&
+			    (BM_elem_index_get(e_next) == -1))
+			{
+				BMVert *v_next;
+				v_next = BM_edge_other_vert(e_next, v);
+				BM_elem_index_set(e_next, f_index);
+				BLI_SMALLSTACK_PUSH(vert_stack_next, v_next);
+				BLI_array_append(edge_net, e_next);
+			}
+		}
+
+		if (BLI_SMALLSTACK_IS_EMPTY(vert_stack)) {
+			BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
+		}
+	}
+
+	BM_face_split_edgenet(bm, f, edge_net, BLI_array_count(edge_net), &face_arr, &face_arr_len);
+	BLI_array_free(edge_net);
+
+	if (face_arr_len) {
+		int i;
+		for (i = 0; i < face_arr_len; i++) {
+			BM_face_select_set(bm, face_arr[i], true);
+			BM_elem_flag_disable(face_arr[i], hflag);
+		}
+	}
+
+	if (face_arr) {
+		MEM_freeN(face_arr);
+	}
+}
+
+static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
+{
+	Object *obedit = CTX_data_edit_object(C);
+	BMEditMesh *em = BKE_editmesh_from_object(obedit);
+	BMesh *bm = em->bm;
+	const char hflag = BM_ELEM_TAG;
+
+	BMVert *v;
+	BMEdge *e;
+	BMFace *f;
+	BMIter iter;
+
+	BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
+
+	BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+		BM_elem_flag_disable(v, hflag);
+	}
+
+	/* edge index is set to -1 then used to assosiate them with faces */
+	BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+		if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
+			BM_elem_flag_enable(e, hflag);
+
+			BM_elem_flag_enable(e->v1, hflag);
+			BM_elem_flag_enable(e->v2, hflag);
+
+		}
+		else {
+			BM_elem_flag_disable(e, hflag);
+		}
+		BM_elem_index_set(e, -1);  /* set_dirty */
+	}
+
+	BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+		if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+			BM_elem_flag_enable(f, hflag);
+		}
+		else {
+			BM_elem_flag_disable(f, hflag);
+		}
+	}
+
+	BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+		if (BM_elem_flag_test(e, hflag)) {
+			BMIter viter;
+			BMVert *v;
+			BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
+				BMIter liter;
+				BMLoop *l;
+
+				unsigned int loop_stack_len;
+				BMLoop *l_best = NULL;
+
+				BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
+				loop_stack_len = 0;
+
+				BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+					if (BM_elem_flag_test(l->f, hflag)) {
+						BLI_SMALLSTACK_PUSH(loop_stack, l);
+						loop_stack_len++;
+					}
+				}
+
+				if (loop_stack_len == 0) {
+					/* pass */
+				}
+				else if (loop_stack_len == 1) {
+					l_best = BLI_SMALLSTACK_POP(loop_stack);
+				}
+				else {
+					/* complicated case, match the edge with a face-loop */
+
+					BMVert *v_other = BM_edge_other_vert(e, v);
+					float e_dir[3];
+
+					/* we wan't closest to zero */
+					float dot_best = FLT_MAX;
+
+					sub_v3_v3v3(e_dir, v_other->co, v->co);
+					normalize_v3(e_dir);
+
+					while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
+						float dot_test;
+
+						/* Check dot first to save on expensive angle-comparison.
+						 * ideal case is 90d difference == 0.0 dot */
+						dot_test = fabsf(dot_v3v3(e_dir, l->f->no));
+						if (dot_test < dot_best) {
+
+							/* check we're in the correct corner (works with convex loops too) */
+							if (angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, v_other->co,    l->f->no) <
+							    angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, l->next->v->co, l->f->no))
+							{
+								dot_best = dot_test;
+								l_best = l;
+							}
+						}
+					}
+				}
+
+				if (l_best) {
+					BM_elem_index_set(e, BM_elem_index_get(l_best->f));  /* set_dirty */
+				}
+			}
+		}
+	}
+
+	bm->elem_index_dirty |= BM_EDGE;
+
+
+	BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+		if (BM_elem_flag_test(f, hflag)) {
+			bm_face_split_by_edges(bm, f, hflag);
+		}
+	}
+
+	EDBM_mesh_normals_update(em);
+	EDBM_update_generic(em, true, true);
+
+	return OPERATOR_FINISHED;
+}
+
+
+void MESH_OT_face_split_by_edges(struct wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Split by Edges";
+	ot->description = "Split faces by loose edges";
+	ot->idname = "MESH_OT_face_split_by_edges";
+
+	/* api callbacks */
+	ot->exec = edbm_face_split_by_edges_exec;
+	ot->poll = ED_operator_editmesh;
+
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 655d96a..2ce19fe 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -112,6 +112,9 @@ void MESH_OT_screw(struct wmOperatorType *ot);
 /* *** editmesh_inset.c *** */
 void MESH_OT_inset(struct wmOperatorType *ot);
 
+/* *** editmesh_intersect.c *** */
+void MESH_OT_face_split_by_edges(struct wmOperatorType *ot);
+
 
 /* *** editmesh_knife.c *** */
 void MESH_OT_knife_tool(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 0f65ed2..55dd97d 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -170,6 +170,7 @@ void ED_operatortypes_mesh(void)
 
 	WM_operatortype_append(MESH_OT_bridge_edge_loops);
 	WM_operatortype_append(MESH_OT_inset);
+	WM_operatortype_append(MESH_OT_face_split_by_edges);
 	WM_operatortype_append(MESH_OT_poke);
 	WM_operatortype_append(MESH_OT_wireframe);
 	WM_operatortype_append(MESH_OT_edge_split);




More information about the Bf-blender-cvs mailing list