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);

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to