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:
@@ -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){
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user