[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [60523] trunk/blender/source/blender/bmesh : fix [#36923] Merge / Delete vertices crashes for some meshes

Campbell Barton ideasman42 at gmail.com
Thu Oct 3 09:06:56 CEST 2013


Revision: 60523
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=60523
Author:   campbellbarton
Date:     2013-10-03 07:06:56 +0000 (Thu, 03 Oct 2013)
Log Message:
-----------
fix [#36923] Merge / Delete vertices crashes for some meshes

add BM_ITER_MESH_MUTABLE which steps before entering the for() loop body and prevents the assert from complaining about removing mesh data while iterating as well as the crash.

this was done in quite a few areas, more may turn up.

Modified Paths:
--------------
    trunk/blender/source/blender/bmesh/intern/bmesh_construct.c
    trunk/blender/source/blender/bmesh/intern/bmesh_iterators.c
    trunk/blender/source/blender/bmesh/intern/bmesh_iterators.h
    trunk/blender/source/blender/bmesh/operators/bmo_dissolve.c
    trunk/blender/source/blender/bmesh/operators/bmo_join_triangles.c
    trunk/blender/source/blender/bmesh/tools/bmesh_bevel.c
    trunk/blender/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_construct.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_construct.c	2013-10-03 07:02:52 UTC (rev 60522)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_construct.c	2013-10-03 07:06:56 UTC (rev 60523)
@@ -500,10 +500,10 @@
  */
 void BMO_remove_tagged_faces(BMesh *bm, const short oflag)
 {
-	BMFace *f;
+	BMFace *f, *f_next;
 	BMIter iter;
 
-	BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+	BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) {
 		if (BMO_elem_flag_test(bm, f, oflag)) {
 			BM_face_kill(bm, f);
 		}
@@ -512,10 +512,10 @@
 
 void BMO_remove_tagged_edges(BMesh *bm, const short oflag)
 {
-	BMEdge *e;
+	BMEdge *e, *e_next;
 	BMIter iter;
 
-	BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+	BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
 		if (BMO_elem_flag_test(bm, e, oflag)) {
 			BM_edge_kill(bm, e);
 		}
@@ -524,10 +524,10 @@
 
 void BMO_remove_tagged_verts(BMesh *bm, const short oflag)
 {
-	BMVert *v;
+	BMVert *v, *v_next;
 	BMIter iter;
 
-	BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+	BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
 		if (BMO_elem_flag_test(bm, v, oflag)) {
 			BM_vert_kill(bm, v);
 		}

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_iterators.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_iterators.c	2013-10-03 07:02:52 UTC (rev 60522)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_iterators.c	2013-10-03 07:06:56 UTC (rev 60523)
@@ -54,6 +54,31 @@
 };
 
 /**
+ * Utility function.
+ */
+int BM_iter_mesh_count(BMesh *bm, const char itype)
+{
+	int count;
+
+	switch (itype) {
+		case BM_VERTS_OF_MESH:
+			count = bm->totvert;
+			break;
+		case BM_EDGES_OF_MESH:
+			count = bm->totedge;
+			break;
+		case BM_FACES_OF_MESH:
+			count = bm->totface;
+			break;
+		default:
+			count = 0;
+			BLI_assert(0);
+	}
+
+	return count;
+}
+
+/**
  * \note Use #BM_vert_at_index / #BM_edge_at_index / #BM_face_at_index for mesh arrays.
  */
 void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_iterators.h
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_iterators.h	2013-10-03 07:02:52 UTC (rev 60522)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_iterators.h	2013-10-03 07:06:56 UTC (rev 60523)
@@ -89,6 +89,20 @@
 #define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar) \
 	for (ele = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; ele; ele = BM_iter_step(iter), (indexvar)++)
 
+/* a version of BM_ITER_MESH which keeps the next item in storage
+ * so we can delete the current item, see bug [#36923] */
+#ifdef DEBUG
+#  define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
+	for (ele = BM_iter_new(iter, bm, itype, NULL); \
+	ele ? ((void)((iter)->count = BM_iter_mesh_count(bm, itype)), \
+	       (void)(ele_next = BM_iter_step(iter)), 1) : 0; \
+	ele = ele_next)
+#else
+#  define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
+	for (ele = BM_iter_new(iter, bm, itype, NULL); ele ? ((ele_next = BM_iter_step(iter)), 1) : 0; ele = ele_next)
+#endif
+
+
 #define BM_ITER_ELEM(ele, iter, data, itype) \
 	for (ele = BM_iter_new(iter, NULL, itype, data); ele; ele = BM_iter_step(iter))
 
@@ -182,6 +196,7 @@
 	char itype;
 } BMIter;
 
+int     BM_iter_mesh_count(BMesh *bm, const char itype);
 void   *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT;
 int     BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len);
 void   *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,

Modified: trunk/blender/source/blender/bmesh/operators/bmo_dissolve.c
===================================================================
--- trunk/blender/source/blender/bmesh/operators/bmo_dissolve.c	2013-10-03 07:02:52 UTC (rev 60522)
+++ trunk/blender/source/blender/bmesh/operators/bmo_dissolve.c	2013-10-03 07:06:56 UTC (rev 60523)
@@ -293,7 +293,8 @@
 	}
 
 	if (use_verts) {
-		BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+		BMVert *v_next;
+		BM_ITER_MESH_MUTABLE (v, v_next, &viter, bm, BM_VERTS_OF_MESH) {
 			if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
 				if (BM_vert_edge_count(v) == 2) {
 					BM_vert_collapse_edge(bm, v->e, v, true);
@@ -349,7 +350,7 @@
 void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
 {
 	BMIter iter, fiter;
-	BMVert *v;
+	BMVert *v, *v_next;
 	BMFace *f;
 
 	const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
@@ -409,7 +410,7 @@
 	}
 	
 	/* clean up any remainin */
-	BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+	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);

Modified: trunk/blender/source/blender/bmesh/operators/bmo_join_triangles.c
===================================================================
--- trunk/blender/source/blender/bmesh/operators/bmo_join_triangles.c	2013-10-03 07:02:52 UTC (rev 60522)
+++ trunk/blender/source/blender/bmesh/operators/bmo_join_triangles.c	2013-10-03 07:06:56 UTC (rev 60523)
@@ -203,7 +203,7 @@
 	BMIter iter;
 	BMOIter siter;
 	BMFace *f;
-	BMEdge *e;
+	BMEdge *e, *e_next;
 	/* data: edge-to-join, sort_value: error weight */
 	struct SortPointerByFloat *jedges;
 	unsigned i, totedge;
@@ -291,7 +291,7 @@
 	MEM_freeN(jedges);
 
 	/* join best weighted */
-	BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+	BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
 		BMFace *f_new;
 		BMFace *f_a, *f_b;
 

Modified: trunk/blender/source/blender/bmesh/tools/bmesh_bevel.c
===================================================================
--- trunk/blender/source/blender/bmesh/tools/bmesh_bevel.c	2013-10-03 07:02:52 UTC (rev 60522)
+++ trunk/blender/source/blender/bmesh/tools/bmesh_bevel.c	2013-10-03 07:06:56 UTC (rev 60523)
@@ -2375,7 +2375,7 @@
                    const struct MDeformVert *dvert, const int vertex_group)
 {
 	BMIter iter;
-	BMVert *v;
+	BMVert *v, *v_next;
 	BMEdge *e;
 	BevelParams bp = {NULL};
 
@@ -2418,7 +2418,7 @@
 			}
 		}
 
-		BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+		BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
 			if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
 				BLI_assert(find_bevvert(&bp, v) != NULL);
 				BM_vert_kill(bm, v);

Modified: trunk/blender/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
===================================================================
--- trunk/blender/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c	2013-10-03 07:02:52 UTC (rev 60522)
+++ trunk/blender/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c	2013-10-03 07:06:56 UTC (rev 60523)
@@ -197,7 +197,7 @@
 	}
 
 	for (iter_step = 0; iter_step < iterations; iter_step++) {
-		BMVert *v;
+		BMVert *v, *v_next;
 		bool iter_done;
 
 		BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@@ -318,7 +318,7 @@
 
 		/* now we tagged all verts -1 for removal, lets loop over and rebuild faces */
 		iter_done = false;
-		BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+		BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
 			if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) {
 				if (bm_vert_dissolve_fan(bm, v)) {
 					iter_done = true;




More information about the Bf-blender-cvs mailing list