[Bf-blender-cvs] [488b342] master: BMesh: optimize selection flushing

Campbell Barton noreply at git.blender.org
Tue Feb 3 10:00:30 CET 2015


Commit: 488b342741ea96ef8e80dab7a7bcf3b9a0be5bcd
Author: Campbell Barton
Date:   Tue Feb 3 19:54:34 2015 +1100
Branches: master
https://developer.blender.org/rB488b342741ea96ef8e80dab7a7bcf3b9a0be5bcd

BMesh: optimize selection flushing

De-selecting a face would do flushing checks on each vertex 3 times, now only do once.

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

M	source/blender/bmesh/intern/bmesh_marking.c
M	source/blender/bmesh/intern/bmesh_marking.h

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

diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index ffbd2bf..8aa6490 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -70,6 +70,69 @@ static void recount_totsels(BMesh *bm)
 	}
 }
 
+/** \name BMesh helper functions for selection flushing.
+ * \{ */
+
+static bool bm_vert_is_edge_select_any_other(BMVert *v, BMEdge *e_first)
+{
+	BMEdge *e_iter = e_first;
+
+	/* start by stepping over the current edge */
+	while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first) {
+		if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
+			return true;
+		}
+	}
+	return false;
+}
+
+#if 0
+static bool bm_vert_is_edge_select_any(BMVert *v)
+{
+	if (v->e) {
+		BMEdge *e_iter, *e_first;
+		e_iter = e_first = v->e;
+		do {
+			if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
+				return true;
+			}
+		} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+	}
+	return false;
+}
+#endif
+
+static bool bm_edge_is_face_select_any_other(BMLoop *l_first)
+{
+	BMLoop *l_iter = l_first;
+
+	/* start by stepping over the current face */
+	while ((l_iter = l_iter->radial_next) != l_first) {
+		if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
+			return true;
+		}
+	}
+	return false;
+}
+
+#if 0
+static bool bm_edge_is_face_select_any(BMEdge *e)
+{
+	if (e->l) {
+		BMLoop *l_iter, *l_first;
+		l_iter = l_first = e->l;
+		do {
+			if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
+				return true;
+			}
+		} while ((l_iter = l_iter->radial_next) != l_first);
+	}
+	return false;
+}
+#endif
+
+/** \} */
+
 /**
  * \brief Select Mode Clean
  *
@@ -386,19 +449,8 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
 
 			/* check if the vert is used by a selected edge */
 			for (i = 0; i < 2; i++) {
-				bool deselect = true;
 				BMVert *v = *((&e->v1) + i);
-				BMEdge *e_other = e;
-
-				/* start by stepping over the current edge */
-				while ((e_other = bmesh_disk_edge_next(e_other, v)) != e) {
-					if (BM_elem_flag_test(e_other, BM_ELEM_SELECT)) {
-						deselect = false;
-						break;
-					}
-				}
-
-				if (deselect) {
+				if (bm_vert_is_edge_select_any_other(v, e) == false) {
 					BM_vert_select_set(bm, v, false);
 				}
 			}
@@ -441,8 +493,6 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
 		} while ((l_iter = l_iter->next) != l_first);
 	}
 	else {
-		BMIter liter;
-		BMLoop *l;
 
 		if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
 			BM_elem_flag_disable(f, BM_ELEM_SELECT);
@@ -450,35 +500,73 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
 		}
 
 		/* flush down to edges */
-		BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
-			BMIter fiter;
-			BMFace *f2;
-			BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) {
-				if (BM_elem_flag_test(f2, BM_ELEM_SELECT))
-					break;
+		l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+		do {
+			/* vertex flushing is handled below */
+			if (bm_edge_is_face_select_any_other(l_iter) == false) {
+				BM_edge_select_set_noflush(bm, l_iter->e, false);
 			}
+		} while ((l_iter = l_iter->next) != l_first);
 
-			if (!f2) {
-				BM_edge_select_set(bm, l->e, false);
+		/* flush down to verts */
+		l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+		do {
+			if (bm_vert_is_edge_select_any_other(l_iter->v, l_iter->e) == false) {
+				BM_vert_select_set(bm, l_iter->v, false);
 			}
+		} while ((l_iter = l_iter->next) != l_first);
+	}
+}
+
+/** \name Non flushing versions element selection.
+ * \{ */
+
+void BM_edge_select_set_noflush(BMesh *bm, BMEdge *e, const bool select)
+{
+	BLI_assert(e->head.htype == BM_EDGE);
+
+	if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+		return;
+	}
+
+	if (select) {
+		if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+			BM_elem_flag_enable(e, BM_ELEM_SELECT);
+			bm->totedgesel += 1;
 		}
+	}
+	else {
+		if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+			BM_elem_flag_disable(e, BM_ELEM_SELECT);
+			bm->totedgesel -= 1;
+		}
+	}
+}
 
-		/* flush down to verts */
-		BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
-			BMIter eiter;
-			BMEdge *e;
-			BM_ITER_ELEM (e, &eiter, l->v, BM_EDGES_OF_VERT) {
-				if (BM_elem_flag_test(e, BM_ELEM_SELECT))
-					break;
-			}
+void BM_face_select_set_noflush(BMesh *bm, BMFace *f, const bool select)
+{
+	BLI_assert(f->head.htype == BM_FACE);
 
-			if (!e) {
-				BM_vert_select_set(bm, l->v, false);
-			}
+	if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+		return;
+	}
+
+	if (select) {
+		if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+			BM_elem_flag_enable(f, BM_ELEM_SELECT);
+			bm->totfacesel += 1;
+		}
+	}
+	else {
+		if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+			BM_elem_flag_disable(f, BM_ELEM_SELECT);
+			bm->totfacesel -= 1;
 		}
 	}
 }
 
+/** \} */
+
 /**
  * Select Mode Set
  *
diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h
index 9e0c092..15f972c 100644
--- a/source/blender/bmesh/intern/bmesh_marking.h
+++ b/source/blender/bmesh/intern/bmesh_marking.h
@@ -59,6 +59,10 @@ void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select);
 void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select);
 void BM_face_select_set(BMesh *bm, BMFace *f, const bool select);
 
+/* lower level functions which don't do flushing */
+void BM_edge_select_set_noflush(BMesh *bm, BMEdge *e, const bool select);
+void BM_face_select_set_noflush(BMesh *bm, BMFace *e, const bool select);
+
 void BM_mesh_select_mode_clean_ex(BMesh *bm, const short selectmode);
 void BM_mesh_select_mode_clean(BMesh *bm);




More information about the Bf-blender-cvs mailing list