[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [45248] trunk/blender/source/blender: Partial fix for array modifier vertex merge (bug 30195).

Nicholas Bishop nicholasbishop at gmail.com
Thu Mar 29 00:03:58 CEST 2012


Revision: 45248
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=45248
Author:   nicholasbishop
Date:     2012-03-28 22:03:46 +0000 (Wed, 28 Mar 2012)
Log Message:
-----------
Partial fix for array modifier vertex merge (bug 30195).

Two fixes:

* The find-doubles operator was overriding the "dirty" element
  indices, so vertices were not being mapped correctly.

* In some cases a vertex can be set to merge with a vertex that is
  also set to be merged, so added a loop to find the first unmerged
  vert in this case.

Not yet working is the "First Last" merge option.

Also made some cleanups and added comments in the array/remove doubles
code.

Modified Paths:
--------------
    trunk/blender/source/blender/bmesh/operators/bmo_removedoubles.c
    trunk/blender/source/blender/modifiers/intern/MOD_array.c

Modified: trunk/blender/source/blender/bmesh/operators/bmo_removedoubles.c
===================================================================
--- trunk/blender/source/blender/bmesh/operators/bmo_removedoubles.c	2012-03-28 19:56:11 UTC (rev 45247)
+++ trunk/blender/source/blender/bmesh/operators/bmo_removedoubles.c	2012-03-28 22:03:46 UTC (rev 45248)
@@ -103,6 +103,7 @@
 	BMFace *f, *f2;
 	int a, b;
 
+	/* mark merge verts for deletion */
 	BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
 		if ((v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", v))) {
 			BMO_elem_flag_enable(bm, v, ELE_DEL);
@@ -112,10 +113,12 @@
 		}
 	}
 
+	/* check if any faces are getting their own corners merged
+	   together, split face if so */
 	BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
 		remdoubles_splitface(f, bm, op);
 	}
-	
+
 	BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
 		if (BMO_elem_flag_test(bm, e->v1, ELE_DEL) || BMO_elem_flag_test(bm, e->v2, ELE_DEL)) {
 			v = BMO_slot_map_ptr_get(bm, op, "targetmap", e->v1);
@@ -149,6 +152,8 @@
 	}
 	bm->elem_index_dirty |= BM_FACE;
 
+	/* faces get "modified" by creating new faces here, then at the
+	   end the old faces are deleted */
 	BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
 		if (!BMO_elem_flag_test(bm, f, FACE_MARK))
 			continue;

Modified: trunk/blender/source/blender/modifiers/intern/MOD_array.c
===================================================================
--- trunk/blender/source/blender/modifiers/intern/MOD_array.c	2012-03-28 19:56:11 UTC (rev 45247)
+++ trunk/blender/source/blender/modifiers/intern/MOD_array.c	2012-03-28 22:03:46 UTC (rev 45248)
@@ -185,13 +185,60 @@
 	}
 }
 
+
+static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op,
+								   const ArrayModifierData *amd,
+								   int *index_map_length)
+{
+	BMOperator find_op;
+	BMOIter oiter;
+	BMVert *v, *v2;
+	BMElem *ele;
+	int *index_map, i;
+
+	BMO_op_initf(bm, &find_op,
+				 "finddoubles verts=%av dist=%f keepverts=%s",
+				 amd->merge_dist, dupe_op, "geom");
+
+	BMO_op_exec(bm, &find_op);
+			
+	i = 0;
+	BMO_ITER(ele, &oiter, bm, dupe_op, "geom", BM_ALL) {
+		BM_elem_index_set(ele, i); /* set_dirty */
+		i++;
+	}
+
+	BMO_ITER(ele, &oiter, bm, dupe_op, "newout", BM_ALL) {
+		BM_elem_index_set(ele, i); /* set_dirty */
+		i++;
+	}
+	/* above loops over all, so set all to dirty, if this is somehow
+	 * setting valid values, this line can be remvoed - campbell */
+	bm->elem_index_dirty |= BM_VERT | BM_EDGE | BM_FACE;
+
+	(*index_map_length) = i;
+	index_map = MEM_callocN(sizeof(int) * (*index_map_length), "index_map");
+
+	/*element type argument doesn't do anything here*/
+	BMO_ITER(v, &oiter, bm, &find_op, "targetmapout", 0) {
+		v2 = BMO_iter_map_value_p(&oiter);
+
+		index_map[BM_elem_index_get(v)] = BM_elem_index_get(v2) + 1;
+	}
+
+	BMO_op_finish(bm, &find_op);
+
+	return index_map;
+}
+
+
 static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
                                           Scene *scene, Object *ob, DerivedMesh *dm,
                                           int UNUSED(initFlags))
 {
 	DerivedMesh *result;
 	BMEditMesh *em = DM_to_editbmesh(dm, NULL, FALSE);
-	BMOperator op, oldop, weldop;
+	BMOperator dupe_op, old_dupe_op, weld_op;
 	int i, j, indexLen;
 	/* offset matrix */
 	float offset[4][4];
@@ -290,65 +337,29 @@
 	BMO_push(em->bm, NULL);
 	bmesh_edit_begin(em->bm, 0);
 
-	BMO_op_init(em->bm, &weldop, "weldverts");
-	BMO_op_initf(em->bm, &op, "dupe geom=%avef");
-	oldop = op;
+	BMO_op_init(em->bm, &weld_op, "weldverts");
+	BMO_op_initf(em->bm, &dupe_op, "dupe geom=%avef");
+	old_dupe_op = dupe_op;
 	for (j=0; j < count - 1; j++) {
-		BMVert *v, *v2;
+		BMVert *v, *v2, *v3;
 		BMOpSlot *s1;
 		BMOpSlot *s2;
 
-		BMO_op_initf(em->bm, &op, "dupe geom=%s", &oldop, j==0 ? "geom" : "newout");
-		BMO_op_exec(em->bm, &op);
+		BMO_op_initf(em->bm, &dupe_op, "dupe geom=%s", &old_dupe_op, j==0 ? "geom" : "newout");
+		BMO_op_exec(em->bm, &dupe_op);
 
-		s1 = BMO_slot_get(&op, "geom");
-		s2 = BMO_slot_get(&op, "newout");
+		s1 = BMO_slot_get(&dupe_op, "geom");
+		s2 = BMO_slot_get(&dupe_op, "newout");
 
-		BMO_op_callf(em->bm, "transform mat=%m4 verts=%s", offset, &op, "newout");
+		BMO_op_callf(em->bm, "transform mat=%m4 verts=%s", offset, &dupe_op, "newout");
 
-		#define _E(s, i) ((BMVert **)(s)->data.buf)[i]
-
 		/*calculate merge mapping*/
 		if (j == 0) {
-			BMOperator findop;
-			BMOIter oiter;
-			BMVert *v, *v2;
-			BMElem *ele;
-
-			BMO_op_initf(em->bm, &findop,
-			             "finddoubles verts=%av dist=%f keepverts=%s",
-			             amd->merge_dist, &op, "geom");
-
-			i = 0;
-			BMO_ITER(ele, &oiter, em->bm, &op, "geom", BM_ALL) {
-				BM_elem_index_set(ele, i); /* set_dirty */
-				i++;
-			}
-
-			BMO_ITER(ele, &oiter, em->bm, &op, "newout", BM_ALL) {
-				BM_elem_index_set(ele, i); /* set_dirty */
-				i++;
-			}
-			/* above loops over all, so set all to dirty, if this is somehow
-			 * setting valid values, this line can be remvoed - campbell */
-			em->bm->elem_index_dirty |= BM_VERT | BM_EDGE | BM_FACE;
-
-
-			BMO_op_exec(em->bm, &findop);
-
-			indexLen = i;
-			indexMap = MEM_callocN(sizeof(int)*indexLen, "indexMap");
-
-			/*element type argument doesn't do anything here*/
-			BMO_ITER(v, &oiter, em->bm, &findop, "targetmapout", 0) {
-				v2 = BMO_iter_map_value_p(&oiter);
-
-				indexMap[BM_elem_index_get(v)] = BM_elem_index_get(v2)+1;
-			}
-
-			BMO_op_finish(em->bm, &findop);
+			indexMap = find_doubles_index_map(em->bm, &dupe_op,
+											  amd, &indexLen);
 		}
 
+		#define _E(s, i) ((BMVert **)(s)->data.buf)[i]
 		/* generate merge mapping using index map.  we do this by using the
 		 * operator slots as lookup arrays.*/
 		#define E(i) (i) < s1->len ? _E(s1, i) : _E(s2, (i)-s1->len)
@@ -359,17 +370,22 @@
 			v = E(i);
 			v2 = E(indexMap[i]-1);
 
-			BMO_slot_map_ptr_insert(em->bm, &weldop, "targetmap", v, v2);
+			/* check in case the target vertex (v2) is already marked
+			   for merging */
+			while((v3 = BMO_slot_map_ptr_get(em->bm, &weld_op, "targetmap", v2)))
+				v2 = v3;
+
+			BMO_slot_map_ptr_insert(em->bm, &weld_op, "targetmap", v, v2);
 		}
 
 		#undef E
 		#undef _E
 
-		BMO_op_finish(em->bm, &oldop);
-		oldop = op;
+		BMO_op_finish(em->bm, &old_dupe_op);
+		old_dupe_op = dupe_op;
 	}
 
-	if (j > 0) BMO_op_finish(em->bm, &op);
+	if (j > 0) BMO_op_finish(em->bm, &dupe_op);
 
 	/* BMESH_TODO - cap ends are not welded, even though weld is called after */
 
@@ -399,9 +415,9 @@
 	/* done capping */
 
 	if (amd->flags & MOD_ARR_MERGE)
-		BMO_op_exec(em->bm, &weldop);
+		BMO_op_exec(em->bm, &weld_op);
 
-	BMO_op_finish(em->bm, &weldop);
+	BMO_op_finish(em->bm, &weld_op);
 
 	/* Bump the stack level back down to match the adjustment up above */
 	BMO_pop(em->bm);




More information about the Bf-blender-cvs mailing list