[Bf-blender-cvs] [5afe4c787f0] master: BMesh: add BM_mesh_separate_faces

Campbell Barton noreply at git.blender.org
Sat Mar 11 10:46:36 CET 2017


Commit: 5afe4c787f0ed3ac30f7609c7f07c5092a20eac9
Author: Campbell Barton
Date:   Sat Mar 11 20:39:28 2017 +1100
Branches: master
https://developer.blender.org/rB5afe4c787f0ed3ac30f7609c7f07c5092a20eac9

BMesh: add BM_mesh_separate_faces

Fast-path for bmesh split operator which duplicates and deletes.
Use when only separating faces, currently used by the intersect tool.

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

M	source/blender/bmesh/CMakeLists.txt
M	source/blender/bmesh/bmesh_tools.h
M	source/blender/bmesh/operators/bmo_dupe.c
A	source/blender/bmesh/tools/bmesh_separate.c
A	source/blender/bmesh/tools/bmesh_separate.h
M	source/blender/editors/mesh/editmesh_intersect.c

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

diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 30fefe37f0e..ea24da86626 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -152,6 +152,8 @@ set(SRC
 	tools/bmesh_path_region.h
 	tools/bmesh_region_match.c
 	tools/bmesh_region_match.h
+	tools/bmesh_separate.c
+	tools/bmesh_separate.h
 	tools/bmesh_triangulate.c
 	tools/bmesh_triangulate.h
 	tools/bmesh_wireframe.c
diff --git a/source/blender/bmesh/bmesh_tools.h b/source/blender/bmesh/bmesh_tools.h
index 23212dd085e..a537c3b872c 100644
--- a/source/blender/bmesh/bmesh_tools.h
+++ b/source/blender/bmesh/bmesh_tools.h
@@ -43,6 +43,7 @@ extern "C" {
 #include "tools/bmesh_path.h"
 #include "tools/bmesh_path_region.h"
 #include "tools/bmesh_region_match.h"
+#include "tools/bmesh_separate.h"
 #include "tools/bmesh_triangulate.h"
 
 #ifdef __cplusplus
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 56639a097b6..8048add84d4 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -378,6 +378,10 @@ void BMO_dupe_from_flag(BMesh *bm, int htype, const char hflag)
  * BMOP_DUPE_VOUTPUT: Buffer containing pointers to the split mesh vertices
  * BMOP_DUPE_EOUTPUT: Buffer containing pointers to the split mesh edges
  * BMOP_DUPE_FOUTPUT: Buffer containing pointers to the split mesh faces
+ *
+ * \note Lower level uses of this operator may want to use #BM_mesh_separate_faces
+ * Since it's faster for the 'use_only_faces' case.
+ *
  */
 void bmo_split_exec(BMesh *bm, BMOperator *op)
 {
diff --git a/source/blender/bmesh/tools/bmesh_separate.c b/source/blender/bmesh/tools/bmesh_separate.c
new file mode 100644
index 00000000000..571da2ff94c
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_separate.c
@@ -0,0 +1,131 @@
+/*
+ * ***** 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/bmesh/tools/bmesh_separate.c
+ *  \ingroup bmesh
+ *
+ * BMesh separate, disconnects a set of faces from all others,
+ * so they don't share any vertices/edges with other faces.
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_buffer.h"
+
+#include "bmesh.h"
+#include "intern/bmesh_private.h"
+#include "bmesh_separate.h"  /* own include */
+
+/**
+ * Split all faces that match `filter_fn`.
+ * \note
+ */
+void BM_mesh_separate_faces(
+        BMesh *bm,
+        BMFaceFilterFunc filter_fn, void *user_data)
+{
+	BMFace **faces_array_all = MEM_mallocN(bm->totface * sizeof(BMFace *), __func__);
+	/*
+	 * - Create an array of faces based on 'filter_fn'.
+	 *   First part of array for match, for non-match.
+	 *
+	 * - Clear all vertex tags, then tag all vertices from 'faces_b'.
+	 *
+	 * - Loop over 'faces_a', checking each vertex,
+	 *   splitting out any which are tagged (and therefor shared).
+	 */
+
+	BMFace *f;
+	BMIter iter;
+
+	unsigned int faces_a_len = 0;
+	unsigned int faces_b_len = 0;
+	{
+		int i_a = 0;
+		int i_b = bm->totface;
+		BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+			faces_array_all[filter_fn(f, user_data) ? i_a++ : --i_b] = f;
+		}
+		faces_a_len = i_a;
+		faces_b_len = bm->totface - i_a;
+	}
+
+	BMFace **faces_a = faces_array_all;
+	BMFace **faces_b = faces_array_all + faces_a_len;
+
+	/* Enable for all  */
+	BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+
+	/* Disable vert tag on faces_b */
+	for (unsigned int i = 0; i < faces_b_len; i++) {
+		BMLoop *l_iter, *l_first;
+		l_iter = l_first = BM_FACE_FIRST_LOOP(faces_b[i]);
+		do {
+			BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
+		} while ((l_iter = l_iter->next) != l_first);
+	}
+
+
+	BLI_buffer_declare_static(BMLoop **, loop_split, 0, 128);
+
+	/* Check shared verts ('faces_a' tag and disable) */
+	for (unsigned int i = 0; i < faces_a_len; i++) {
+		BMLoop *l_iter, *l_first;
+		l_iter = l_first = BM_FACE_FIRST_LOOP(faces_a[i]);
+		do {
+			if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
+				BMVert *v = l_iter->v;
+				/* Disable, since we may visit this vertex again on other faces */
+				BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+				/* We know the vertex is shared, collect all vertices and split them off. */
+
+				/* Fill 'loop_split' */
+				{
+					BMEdge *e_first, *e_iter;
+					e_iter = e_first = l_iter->e;
+					do {
+						BMLoop *l_radial_first, *l_radial_iter;
+						l_radial_first = l_radial_iter = e_iter->l;
+						do {
+							if (l_radial_iter->v == v) {
+								if (filter_fn(l_radial_iter->f, user_data)) {
+									BLI_buffer_append(&loop_split, BMLoop *, l_radial_iter);
+								}
+							}
+						} while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
+					} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+				}
+
+				/* Perform the split */
+				bmesh_urmv_loop_multi(bm, loop_split.data, loop_split.count);
+
+				BLI_buffer_empty(&loop_split);
+			}
+		} while ((l_iter = l_iter->next) != l_first);
+	}
+
+	BLI_buffer_free(&loop_split);
+
+	MEM_freeN(faces_array_all);
+}
diff --git a/source/blender/bmesh/bmesh_tools.h b/source/blender/bmesh/tools/bmesh_separate.h
similarity index 55%
copy from source/blender/bmesh/bmesh_tools.h
copy to source/blender/bmesh/tools/bmesh_separate.h
index 23212dd085e..91b2b71c872 100644
--- a/source/blender/bmesh/bmesh_tools.h
+++ b/source/blender/bmesh/tools/bmesh_separate.h
@@ -15,38 +15,18 @@
  * 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):
- *
  * ***** END GPL LICENSE BLOCK *****
  */
 
-#ifndef __BMESH_TOOLS_H__
-#define __BMESH_TOOLS_H__
+#ifndef __BMESH_SEPARATE_H__
+#define __BMESH_SEPARATE_H__
 
-/** \file blender/bmesh/bmesh_tools.h
+/** \file blender/bmesh/tools/bmesh_separate.h
  *  \ingroup bmesh
- *
- * Utility functions that operate directly on the BMesh,
- * These can be used by both Modifiers and BMesh-Operators.
  */
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "tools/bmesh_beautify.h"
-#include "tools/bmesh_bevel.h"
-#include "tools/bmesh_bisect_plane.h"
-#include "tools/bmesh_decimate.h"
-#include "tools/bmesh_edgenet.h"
-#include "tools/bmesh_edgesplit.h"
-#include "tools/bmesh_path.h"
-#include "tools/bmesh_path_region.h"
-#include "tools/bmesh_region_match.h"
-#include "tools/bmesh_triangulate.h"
-
-#ifdef __cplusplus
-}
-#endif
+void BM_mesh_separate_faces(
+        BMesh *bm,
+        BMFaceFilterFunc filter_fn, void *user_data);
 
-#endif /* __BMESH_TOOLS_H__ */
+#endif /* __BMESH_SEPARATE_H__ */
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index bc9088401db..49bfde77032 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -51,6 +51,7 @@
 #include "mesh_intern.h"  /* own include */
 
 #include "tools/bmesh_intersect.h"
+#include "tools/bmesh_separate.h"
 
 
 /* detect isolated holes and fill them */
@@ -196,13 +197,9 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
 
 	if (use_separate_cut) {
 		/* detach selected/un-selected faces */
-		BMOperator bmop;
-		EDBM_op_init(em, &bmop, op, "split geom=%hf use_only_faces=%b", BM_ELEM_SELECT, true);
-		BMO_op_exec(em->bm, &bmop);
-		if (!EDBM_op_finish(em, &bmop, op, true)) {
-			/* should never happen! */
-			BKE_report(op->reports, RPT_ERROR, "Error separating");
-		}
+		BM_mesh_separate_faces(
+		        bm,
+		        BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
 	}
 
 	if (has_isect) {




More information about the Bf-blender-cvs mailing list