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

Andrew Wiggin ender79bl at gmail.com
Mon Sep 26 02:27:28 CEST 2011


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

For some cases, this will make dissolve work. For others dissolve will still fail (report unable to dissolve, not crash) in some cases. 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/bmesh_walkers.h
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mesh.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_walkers.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_walkers_impl.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_walkers_private.h
    branches/bmesh/blender/source/blender/editors/mesh/bmesh_select.c

Modified: branches/bmesh/blender/source/blender/bmesh/bmesh.h
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/bmesh.h	2011-09-25 20:03:03 UTC (rev 40541)
+++ branches/bmesh/blender/source/blender/bmesh/bmesh.h	2011-09-26 00:27:25 UTC (rev 40542)
@@ -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/bmesh_walkers.h
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/bmesh_walkers.h	2011-09-25 20:03:03 UTC (rev 40541)
+++ branches/bmesh/blender/source/blender/bmesh/bmesh_walkers.h	2011-09-26 00:27:25 UTC (rev 40542)
@@ -7,19 +7,26 @@
   NOTE: do NOT modify topology while walking a mesh!
 */
 
+typedef enum {
+	BMW_DEPTH_FIRST,
+	BMW_BREADTH_FIRST,
+} BMWOrder;
+
 /*Walkers*/
 typedef struct BMWalker {
 	void (*begin) (struct BMWalker *walker, void *start);
 	void *(*step) (struct BMWalker *walker);
 	void *(*yield)(struct BMWalker *walker);
 	int structsize;
+	BMWOrder order;
 	int flag;
 
 	BMesh *bm;
-	BLI_mempool *stack;
-	void *currentstate;
+	BLI_mempool *worklist;
+	ListBase states;
 	int restrictflag;
 	GHash *visithash;
+	int depth;
 } BMWalker;
 
 /*initialize a walker.  searchmask restricts some (not all) walkers to
@@ -28,10 +35,12 @@
 void *BMW_Begin(BMWalker *walker, void *start);
 void *BMW_Step(struct BMWalker *walker);
 void BMW_End(struct BMWalker *walker);
+int BMW_CurrentDepth(BMWalker *walker);
 
 /*these are used by custom walkers*/
-void BMW_pushstate(BMWalker *walker);
-void BMW_popstate(BMWalker *walker);
+void *BMW_currentstate(BMWalker *walker);
+void *BMW_addstate(BMWalker *walker);
+void BMW_removestate(BMWalker *walker);
 void *BMW_walk(BMWalker *walker);
 void BMW_reset(BMWalker *walker);
 
@@ -75,6 +84,8 @@
 	BMW_ISLANDBOUND,
 	/*walk over all faces in an island of tool flagged faces.*/
 	BMW_ISLAND,
+	/*walk from a vertex to all connected vertices.*/
+	BMW_CONNECTED_VERTEX,
 	/*do not intitialze function pointers and struct size in BMW_Init*/
 	BMW_CUSTOM,
 	BMW_MAXWALKERS

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mesh.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mesh.c	2011-09-25 20:03:03 UTC (rev 40541)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mesh.c	2011-09-26 00:27:25 UTC (rev 40542)
@@ -59,6 +59,7 @@
 /*bmesh_error stub*/
 void bmesh_error(void)
 {
+	BLI_assert(0);
 	printf("BM modelling error!");
 }
 

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c	2011-09-25 20:03:03 UTC (rev 40541)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c	2011-09-26 00:27:25 UTC (rev 40542)
@@ -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-25 20:03:03 UTC (rev 40541)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c	2011-09-26 00:27:25 UTC (rev 40542)
@@ -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   |

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_walkers.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_walkers.c	2011-09-25 20:03:03 UTC (rev 40541)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_walkers.c	2011-09-26 00:27:25 UTC (rev 40542)
@@ -51,14 +51,14 @@
  design notes:
 
  original desing: walkers directly emulation recursive functions.
- functions save their state onto a stack, and also push new states
+ functions save their state onto a worklist, and also add new states
  to implement recursive or looping behaviour.  generally only one
  state push per call with a specific state is desired.
 
  basic design pattern: the walker step function goes through it's
  list of possible choices for recursion, and recurses (by pushing a new state)
  using the first non-visited one.  this choise is the flagged as visited using
- the ghash.  each step may push multiple new states onto the stack at once.
+ the ghash.  each step may push multiple new states onto the worklist at once.
 
  * walkers use tool flags, not header flags
  * walkers now use ghash for storing visited elements, 
@@ -68,17 +68,10 @@
    for if walkers fail.
 */
 
-
-/* Pointer hiding*/
-typedef struct bmesh_walkerGeneric{
-	struct bmesh_walkerGeneric *prev;

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list