[Bf-blender-cvs] [2aca720] master: Fix T40813: Dissolve verts with adjacent regions, removes the dividing edge

Campbell Barton noreply at git.blender.org
Thu Jun 26 21:40:54 CEST 2014


Commit: 2aca720bff109861e2e617940f6e95076458ef71
Author: Campbell Barton
Date:   Fri Jun 27 05:11:02 2014 +1000
https://developer.blender.org/rB2aca720bff109861e2e617940f6e95076458ef71

Fix T40813: Dissolve verts with adjacent regions, removes the dividing edge

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

M	source/blender/bmesh/intern/bmesh_error.h
M	source/blender/bmesh/intern/bmesh_operators.c
M	source/blender/bmesh/operators/bmo_dissolve.c

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

diff --git a/source/blender/bmesh/intern/bmesh_error.h b/source/blender/bmesh/intern/bmesh_error.h
index 0f23f87..6cd3701 100644
--- a/source/blender/bmesh/intern/bmesh_error.h
+++ b/source/blender/bmesh/intern/bmesh_error.h
@@ -59,17 +59,20 @@ void BMO_error_clear(BMesh *bm);
 /*------ error code defines -------*/
 
 /*error messages*/
-#define BMERR_SELF_INTERSECTING			1
-#define BMERR_DISSOLVEDISK_FAILED		2
-#define BMERR_CONNECTVERT_FAILED		3
-#define BMERR_WALKER_FAILED				4
-#define BMERR_DISSOLVEFACES_FAILED		5
-#define BMERR_DISSOLVEVERTS_FAILED		6
-#define BMERR_TESSELLATION				7
-#define BMERR_NONMANIFOLD				8
-#define BMERR_INVALID_SELECTION			9
-#define BMERR_MESH_ERROR				10
-#define BMERR_CONVEX_HULL_FAILED		11
+enum {
+	BMERR_SELF_INTERSECTING = 1,
+	BMERR_DISSOLVEDISK_FAILED,
+	BMERR_CONNECTVERT_FAILED,
+	BMERR_WALKER_FAILED,
+	BMERR_DISSOLVEFACES_FAILED,
+	BMERR_TESSELLATION,
+	BMERR_NONMANIFOLD,
+	BMERR_INVALID_SELECTION,
+	BMERR_MESH_ERROR,
+	BMERR_CONVEX_HULL_FAILED,
+
+	BMERR_TOTAL,
+};
 
 /* BMESH_ASSERT */
 #ifdef WITH_ASSERT_ABORT
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index dc419fa..7f87261 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -54,13 +54,13 @@ static const char *bmo_error_messages[] = {
 	N_("Could not connect vertices"),
 	N_("Could not traverse mesh"),
 	N_("Could not dissolve faces"),
-	N_("Could not dissolve vertices"),
 	N_("Tessellation error"),
 	N_("Cannot deal with non-manifold geometry"),
 	N_("Invalid selection"),
 	N_("Internal mesh error"),
 };
 
+BLI_STATIC_ASSERT(ARRAY_SIZE(bmo_error_messages) + 1 == BMERR_TOTAL, "message mismatch");
 
 /* operator slot type information - size of one element of the type given. */
 const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = {
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index 59a7803..36a936c 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -335,126 +335,85 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
 	}
 }
 
-static bool test_extra_verts(BMesh *bm, BMVert *v)
-{
-	BMIter fiter, liter, eiter, fiter_sub;
-	BMFace *f;
-	BMLoop *l;
-	BMEdge *e;
-
-	/* test faces around verts for verts that would be wrongly killed
-	 * by dissolve faces. */
-	BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
-		BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
-			if (!BMO_elem_flag_test(bm, l->v, VERT_MARK)) {
-				/* if an edge around a vert is a boundary edge,
-				 * then dissolve faces won't destroy it.
-				 * also if it forms a boundary with one
-				 * of the face region */
-				bool found = false;
-				BM_ITER_ELEM (e, &eiter, l->v, BM_EDGES_OF_VERT) {
-					BMFace *f_iter;
-					if (BM_edge_is_boundary(e)) {
-						found = true;
-					}
-					else {
-						BM_ITER_ELEM (f_iter, &fiter_sub, e, BM_FACES_OF_EDGE) {
-							if (!BMO_elem_flag_test(bm, f_iter, FACE_MARK)) {
-								found = true;
-								break;
-							}
-						}
-					}
-					if (found == true) {
-						break;
-					}
-				}
-				if (found == false) {
-					return false;
-				}
-			}
-		}
-	}
-
-	return true;
-}
 void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
 {
-	BMIter iter, fiter;
+	BMOIter oiter;
+	BMIter iter;
 	BMVert *v, *v_next;
-	BMFace *f;
+	BMEdge *e, *e_next;
+	BMFace *act_face = bm->act_face;
 
 	const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
 
+	BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+		BMIter itersub;
+
+		BMO_elem_flag_enable(bm, v, VERT_MARK | VERT_ISGC);
+
+		BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) {
+			BMO_elem_flag_enable(bm, e, EDGE_ISGC);
+		}
+	}
 
-	BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_MARK);
-	
 	if (use_face_split) {
 		bm_face_split(bm, VERT_MARK);
 	}
 
-	BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
-		if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
-			/* check if it's a two-valence ver */
-			if (BM_vert_edge_count(v) == 2) {
+	BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+		BMIter itersub;
+		BMLoop *l_first;
+		BM_ITER_ELEM (l_first, &itersub, v, BM_LOOPS_OF_VERT) {
+			BMLoop *l_iter;
+			l_iter = l_first;
+			do {
+				BMO_elem_flag_enable(bm, l_iter->v, VERT_ISGC);
+				BMO_elem_flag_enable(bm, l_iter->e, EDGE_ISGC);
+			} while ((l_iter = l_iter->next) != l_first);
+		}
+	}
 
-				/* collapse the ver */
-				/* previously the faces were joined, but collapsing between 2 edges
-				 * gives some advantage/difference in using vertex-dissolve over edge-dissolve */
-#if 0
-				BM_vert_collapse_faces(bm, v->e, v, 1.0f, true, true);
-#else
-				BM_vert_collapse_edge(bm, v->e, v, true);
-#endif
+	BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+		BMIter itersub;
 
-				continue;
-			}
+		if (BM_vert_edge_count(v) != 2) {
+			BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) {
+				BMFace *fa, *fb;
+				if (BM_edge_face_pair(e, &fa, &fb)) {
+					BMFace *f_new;
 
-			BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
-				BMO_elem_flag_enable(bm, f, FACE_MARK | FACE_ORIG);
-			}
-			
-			/* check if our additions to the input to face dissolve
-			 * will destroy nonmarked vertices. */
-			if (!test_extra_verts(bm, v)) {
-				BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
-					if (BMO_elem_flag_test(bm, f, FACE_ORIG)) {
-						BMO_elem_flag_disable(bm, f, FACE_MARK | FACE_ORIG);
+					/* join faces */
+					f_new = BM_faces_join_pair(bm, fa, fb, e, false);
+
+					/* maintain active face */
+					if (act_face && bm->act_face == NULL) {
+						bm->act_face = f_new;
 					}
 				}
 			}
-			else {
-				BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
-					BMO_elem_flag_disable(bm, f, FACE_ORIG);
-				}
-			}
 		}
 	}
 
-	BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_MARK);
-	if (BMO_error_occurred(bm)) {
-		const char *msg;
-
-		BMO_error_get(bm, &msg, NULL);
-		BMO_error_clear(bm);
-		BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, msg);
+	/* Cleanup geometry (#BM_faces_join_pair, but it removes geometry we're looping on)
+	 * so do this in a separate pass instead. */
+	BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
+		if ((e->l == NULL) && BMO_elem_flag_test(bm, e, EDGE_ISGC)) {
+			BM_edge_kill(bm, e);
+		}
 	}
-	
-	/* clean up any remaining */
-	/* note: don't use BM_ITER_MESH_MUTABLE here, even though vertices are removed (T37559) */
-	BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+	BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+		if ((v->e == NULL) && BMO_elem_flag_test(bm, v, VERT_ISGC)) {
+			BM_vert_kill(bm, v);
+		}
+	}
+	/* done with cleanup */
+
+	BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
 		if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
-			if (!BM_vert_dissolve(bm, v)) {
-				BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, NULL);
-				return;
+			if (BM_vert_edge_count(v) == 2) {
+				BM_vert_collapse_edge(bm, v->e, v, true);
 			}
-#ifdef DEBUG
-			/* workaround debug assert */
-			iter.count = bm->totvert;
-#endif
 		}
 	}
-
 }
 
 /* Limited Dissolve */




More information about the Bf-blender-cvs mailing list