Dissolve verts better cleans up two-edged faces, as much

as it can.

Some design notes:

* BM_Dissolve_Disk is now more like a
  BM_Dissolve_Vert function (e.g. there's logic
  to remove verts if there's not surrounding faces).
  I kindof like this idea better (if we decide to
  go this way we should call it BM_Dissolve_Vert)
  but will have to discuss it further with Briggs.
  It seems more intuitive to have a "destroy this
  vert" function then a "just destroy it in this
  specific situation" function.

* Joining two two-edged faces does not work, so
  dissolve vert cannot clean all of them up.  Until
  this is fixed, I've added checks in the conversion
  code so at least things don't crash.
This commit is contained in:
Joseph Eagar
2009-02-15 02:14:40 +00:00
parent 6ad0c2078c
commit 0b3d60c39c
3 changed files with 83 additions and 29 deletions

View File

@@ -36,8 +36,6 @@
* |=========| |=========|
*
*
* Returns -
* 1 for success, 0 for failure.
*/
#if 1
void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
@@ -46,7 +44,14 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
BMLoop *loop;
int done, len;
if(BM_Nonmanifold_Vert(bm, v)) return;
if(BM_Nonmanifold_Vert(bm, v)) {
if (!v->edge) bmesh_kv(bm, v);
else if (!v->edge->loop) {
bmesh_ke(bm, v->edge);
bmesh_kv(bm, v);
}
return;
}
if(v->edge){
/*v->edge we keep, what else?*/
@@ -81,6 +86,9 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
/*collapse the vertex*/
BM_Collapse_Vert(bm, v->edge, v, 1.0, 0);
BM_Join_Faces(bm, f, f2, NULL, 0, 0);
} else if (len == 1) {
bmesh_ke(bm, v->edge);
bmesh_kv(bm, v);
}
if(keepedge){

View File

@@ -154,6 +154,7 @@ static EditFace *bmeshface_to_editface(BMesh *bm, EditMesh *em, BMFace *f, EditV
}
efa = addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL);
if (!efa) return NULL;
bmeshedge_to_editedge_internal(bm, em, f->loopbase->e, efa->e1);
bmeshedge_to_editedge_internal(bm, em, ((BMLoop*)(f->loopbase->head.next))->e, efa->e2);

View File

@@ -28,38 +28,83 @@ void dissolveverts_exec(BMesh *bm, BMOperator *op)
BMIter iter, liter, fiter;
BMVert *v;
BMFace *f, *f2;
BMEdge *e;
BMEdge *fe;
BMLoop *l;
int i, found;
int found, found2, found3, len, oldlen=0;
vinput = BMO_GetSlot(op, BMOP_DISVERTS_VERTIN);
BMO_Flag_Buffer(bm, op, BMOP_DISVERTS_VERTIN, VERT_MARK);
for (v=BMIter_New(&iter, bm, BM_VERTS, NULL); v; v=BMIter_Step(&iter)) {
if (BMO_TestFlag(bm, v, VERT_MARK)) {
BM_Dissolve_Disk(bm, v);
}
}
/*clean up two-edged faces*/
for (f=BMIter_New(&iter, bm, BM_FACES, NULL); f; f=BMIter_Step(&iter)){
if (f->len == 2) {
found = 0;
l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
for (; l; l=BMIter_Step(&liter)) {
f2 = BMIter_New(&fiter, bm,
BM_FACES_OF_EDGE, l->e);
for (; f2; f2=BMIter_Step(&fiter)) {
if (f2 != f) {
BM_Join_Faces(bm, f, f2, l->e,
1, 0);
found = 1;
break;
}
}
if (found) break;
found = 1;
while (found) {
found = 0;
len = 0;
for (v=BMIter_New(&iter, bm, BM_VERTS, NULL); v; v=BMIter_Step(&iter)) {
if (BMO_TestFlag(bm, v, VERT_MARK)) {
BM_Dissolve_Disk(bm, v);
found = 1;
len++;
}
}
/*clean up two-edged faces*/
/*basic idea is to keep joining 2-edged faces until their
gone. this however relies on joining two 2-edged faces
together to work, which doesn't.*/
found3 = 1;
while (found3) {
found3 = 0;
for (f=BMIter_New(&iter, bm, BM_FACES, NULL); f; f=BMIter_Step(&iter)){
if (f->len == 2) {
//this design relies on join faces working
//with two-edged faces properly.
//commenting this line disables the
//outermost loop.
//found3 = 1;
found2 = 0;
l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
fe = l->e;
for (; l; l=BMIter_Step(&liter)) {
f2 = BMIter_New(&fiter, bm,
BM_FACES_OF_EDGE, l->e);
for (; f2; f2=BMIter_Step(&fiter)) {
if (f2 != f) {
BM_Join_Faces(bm, f, f2, l->e,
1, 0);
found2 = 1;
break;
}
}
if (found2) break;
}
if (!found2) {
bmesh_kf(bm, f);
bmesh_ke(bm, fe);
}
} else if (f->len == 3) {
BMEdge *ed[3];
BMVert *vt[3];
BMLoop *lp[3];
int i=0;
/*check for duplicate edges*/
l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
for (; l; l=BMIter_Step(&liter)) {
ed[i++] = l->e;
lp[i++] = l;
vt[i++] = l->v;
}
if (vt[0] == vt[1] || vt[0] == vt[2]) {
i += 1;
}
}
}
}
if (oldlen == len) break;
oldlen = len;
}
}