[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