[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [40544] branches/bmesh/blender/source/ blender/bmesh: Fix dissolve crashes.

Andrew Wiggin ender79bl at gmail.com
Mon Sep 26 05:37:16 CEST 2011


Revision: 40544
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=40544
Author:   ender79
Date:     2011-09-26 03:37:12 +0000 (Mon, 26 Sep 2011)
Log Message:
-----------
Fix dissolve crashes.

For some cases, this will make dissolve work as expected. For other cases dissolve will fail gracefully (it will report unable to dissolve, but not crash). To get dissolve to work in these cases we need to define what happens when you dissolve a disk that has faces which share more than one edge.

Modified Paths:
--------------
    branches/bmesh/blender/source/blender/bmesh/bmesh.h
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c

Modified: branches/bmesh/blender/source/blender/bmesh/bmesh.h
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/bmesh.h	2011-09-26 00:32:45 UTC (rev 40543)
+++ branches/bmesh/blender/source/blender/bmesh/bmesh.h	2011-09-26 03:37:12 UTC (rev 40544)
@@ -181,7 +181,7 @@
                                            struct BMLoop **nl, struct BMEdge *example );
 
 /*dissolves a vert shared only by two edges*/
-void BM_Collapse_Vert ( struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv,
+BMEdge* BM_Collapse_Vert ( struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv,
                         float fac );
 
 /*splits an edge.  ne is set to the new edge created.*/

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c	2011-09-26 00:32:45 UTC (rev 40543)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c	2011-09-26 03:37:12 UTC (rev 40544)
@@ -110,16 +110,22 @@
 		if (!BM_Split_Face(bm, loop->f, v, loop->v, NULL, NULL))
 			return 0;
 
-		BM_Dissolve_Disk(bm, v);
+		if (!BM_Dissolve_Disk(bm, v)) {
+			return 0;
+		}
 		return 1;
 	} else if (keepedge == NULL && len == 2) {
+		/*collapse the vertex*/
+		e = BM_Collapse_Vert(bm, v->e, v, 1.0);
+
+		if (!e) {
+			return 0;
+		}
+
 		/*handle two-valence*/
-		f = v->e->l->f;
-		f2 = v->e->l->radial_next->f;
+		f = e->l->f;
+		f = e->l->radial_next->f;
 		
-		/*collapse the vertex*/
-		BM_Collapse_Vert(bm, v->e, v, 1.0);
-		
 		if (f != f2 && !BM_Join_TwoFaces(bm, f, f2, NULL))
 			return 0;
 
@@ -150,16 +156,22 @@
 			}while(e != v->e);
 		}
 
+		/*collapse the vertex*/
+		e = BM_Collapse_Vert(bm, baseedge, v, 1.0);
+
+		if (!e) {
+			return 0;
+		}
+		
 		/*get remaining two faces*/
-		f = v->e->l->f;
-		f2 = v->e->l->radial_next->f;
+		f = e->l->f;
+		f2 = e->l->radial_next->f;
 
-		/*collapse the vertex*/
-		BM_Collapse_Vert(bm, baseedge, v, 1.0);
-		
 		if (f != f2) {
 			/*join two remaining faces*/
-			if (!BM_Join_TwoFaces(bm, f, f2, NULL)) return 0;
+			if (!BM_Join_TwoFaces(bm, f, f2, NULL)) {
+				return 0;
+			}
 		}
 	}
 
@@ -199,16 +211,21 @@
 #endif
 
 /**
- *			bmesh_join_faces
+ * BM_Join_TwoFaces
  *
- *  joins two adjacenct faces togather.
+ *  Joins two adjacenct faces togather.
  * 
- *  Returns -
- *	BMFace pointer
+ *  Because this method calls to BM_Join_Faces to do its work, ff a pair
+ *  of faces share multiple edges, the pair of faces will be joined at
+ *  every edge (not just edge e). This part of the functionality might need
+ *  to be reconsidered.
+ *
+ * Returns:
+ *	 pointer to the combined face
  */
  
-BMFace *BM_Join_TwoFaces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) {
-
+BMFace *BM_Join_TwoFaces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
+{
 	BMLoop *l1, *l2;
 	BMEdge *jed=NULL;
 	BMFace *faces[2] = {f1, f2};
@@ -279,12 +296,21 @@
 }
 
 /**
- *			BM_split_face
+ * BM_Split_Face
  *
  *  Splits a single face into two.
- * 
+ *
+ *   f - the original face
+ *   v1 & v2 - vertices which define the split edge, must be different
+ *   nl - pointer which will receive the BMLoop for the split edge in the new face
+ *
+ *  Notes: the 
+
  *  Returns -
- *	BMFace pointer
+ *	  Pointer to the newly created face representing one side of the split
+ *   if the split is successful (and the original original face will be the
+ *   other side). NULL if the split fails.
+ *
  */
 
 BMFace *BM_Split_Face(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl, BMEdge *UNUSED(example))
@@ -344,15 +370,19 @@
  *	Nothing
  */
  
-void BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac){
+BMEdge* BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac){
 	BMFace **faces = NULL, *f;
 	BLI_array_staticdeclare(faces, 8);
 	BMIter iter;
 	BMLoop *l=NULL, *kvloop=NULL, *tvloop=NULL;
+	BMEdge *ne = NULL;
 	BMVert *tv = bmesh_edge_getothervert(ke,kv);
 	void *src[2];
 	float w[2];
 
+	/* Only intended to be called for 2-valence vertices */
+	BLI_assert(bmesh_disk_count(kv) <= 2);
+
 	w[0] = 1.0f - fac;
 	w[1] = fac;
 
@@ -383,13 +413,16 @@
 		BMEdge *e2;
 		BMVert *tv2;
 
-		/*ok, no faces, means we have a wire edge*/
 		e2 = bmesh_disk_nextedge(ke, kv);
 		tv2 = BM_OtherEdgeVert(e2, kv);
 
 		f2 = BM_Join_Faces(bm, faces, BLI_array_count(faces));
-		if (f2) 
-			BM_Split_Face(bm, f2, tv, tv2, NULL, NULL);
+		if (f2) {
+			BMLoop *nl = NULL;
+			if (BM_Split_Face(bm, f2, tv, tv2, &nl, NULL)) {
+				ne = nl->e;
+			}
+		}
 	} else if (faces && BLI_array_count(faces) == 1) {
 		BMLoop **loops = NULL;
 		BMEdge *e;
@@ -413,14 +446,19 @@
 					BLI_array_append(edges, l->e);
 				} else {
 					BMVert *v2;
+
+					/* Create a single edge to replace the two edges incident on kv */
 					
 					if (BM_Vert_In_Edge(l->next->e, kv))
 						v2 = BM_OtherEdgeVert(l->next->e, kv);
 					else
 						v2 = BM_OtherEdgeVert(l->prev->e, kv);
-						
-					e = BM_Make_Edge(bm, BM_OtherEdgeVert(l->e, kv), v2, l->e, 1);
-					BLI_array_append(edges, e);
+
+					/* Only one new edge should be created */
+					BLI_assert(ne == NULL);
+
+					ne = BM_Make_Edge(bm, BM_OtherEdgeVert(l->e, kv), v2, l->e, 1);
+					BLI_array_append(edges, ne);
 				}
 
 				BLI_array_append(loops, l);
@@ -459,6 +497,8 @@
 	}
 
 	BLI_array_free(faces);
+
+	return ne;
 }
 
 /**

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c	2011-09-26 00:32:45 UTC (rev 40543)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c	2011-09-26 03:37:12 UTC (rev 40544)
@@ -702,8 +702,17 @@
 
 /* Midlevel Topology Manipulation Functions */
 
-/*joins a collected group of faces into one.  only restriction on
-  the input data is that the faces must be connected to each other.*/
+/*
+ * BM_Join_Faces
+ *
+ * Joins a collected group of faces into one. Only restriction on
+ * the input data is that the faces must be connected to each other.
+ *
+ * If a pair of faces share multiple edges, the pair of
+ * faces will be joined at every edge.
+ *
+ * Returns a pointer to the combined face.
+ */
 BMFace *BM_Join_Faces(BMesh *bm, BMFace **faces, int totface)
 {
 	BMFace *f, *newf;
@@ -902,7 +911,7 @@
  *
  *     Before:               After:
  *	 ----------           ----------
- *	 |		  |           |        |
+ *	 |        |           |        |
  *	 |        |           |   f1   |
  *	v1   f1   v2          v1======v2
  *	 |        |           |   f2   |
@@ -1340,7 +1349,7 @@
  *	
  *        A                   B
  *	 ----------           ----------
- *	 |		  |           |        | 
+ *	 |        |           |        | 
  *	 |   f1   |           |   f1   |
  *	v1========v2 = Ok!    v1==V2==v3 == Wrong!
  *	 |   f2   |           |   f2   |




More information about the Bf-blender-cvs mailing list