bmesh - remove faces with <3 sides after dissolve/collapse (most tools already did this).

This commit is contained in:
Campbell Barton 2012-02-26 05:48:12 +00:00
parent ff7ddb1925
commit 1004b03578
6 changed files with 52 additions and 28 deletions

@ -219,8 +219,10 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f,
struct BMLoop **nl, BMEdge *example); struct BMLoop **nl, BMEdge *example);
/* these 2 functions are very similar */ /* these 2 functions are very similar */
BMEdge* BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, const int join_faces); BMEdge* BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
BMEdge* BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv); const short join_faces, const short kill_degenerate_faces);
BMEdge* BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv,
const short kill_degenerate_faces);
/* splits an edge. ne is set to the new edge created. */ /* splits an edge. ne is set to the new edge created. */

@ -51,7 +51,7 @@ struct Object;
typedef struct BMHeader { typedef struct BMHeader {
void *data; /* customdata layers */ void *data; /* customdata layers */
int index; /* notes: int index; /* notes:
* - Use BM_elem_index_get/SetIndex macros for index * - Use BM_elem_index_get/set macros for index
* - Unitialized to -1 so we can easily tell its not set. * - Unitialized to -1 so we can easily tell its not set.
* - Used for edge/vert/face, check BMesh.elem_index_dirty for valid index values, * - Used for edge/vert/face, check BMesh.elem_index_dirty for valid index values,
* this is abused by various tools which set it dirty. * this is abused by various tools which set it dirty.

@ -72,7 +72,7 @@ int BM_vert_dissolve(BMesh *bm, BMVert *v)
} }
else if (!v->e->l) { else if (!v->e->l) {
if (len == 2) { if (len == 2) {
return (BM_vert_collapse_edge(bm, v->e, v) != NULL); return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL);
} }
else { else {
/* used to kill the vertex here, but it may be connected to faces. /* used to kill the vertex here, but it may be connected to faces.
@ -86,7 +86,7 @@ int BM_vert_dissolve(BMesh *bm, BMVert *v)
} }
else if (len == 2 && BM_vert_face_count(v) == 1) { else if (len == 2 && BM_vert_face_count(v) == 1) {
/* boundry vertex on a face */ /* boundry vertex on a face */
return (BM_vert_collapse_edge(bm, v->e, v) != NULL); return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL);
} }
else { else {
return BM_disk_dissolve(bm, v); return BM_disk_dissolve(bm, v);
@ -134,7 +134,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
} }
else if (keepedge == NULL && len == 2) { else if (keepedge == NULL && len == 2) {
/* collapse the verte */ /* collapse the verte */
e = BM_vert_collapse_faces(bm, v->e, v, 1.0, TRUE); e = BM_vert_collapse_faces(bm, v->e, v, 1.0, TRUE, TRUE);
if (!e) { if (!e) {
return FALSE; return FALSE;
@ -179,7 +179,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
} }
/* collapse the verte */ /* collapse the verte */
e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, TRUE); e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, TRUE, TRUE);
if (!e) { if (!e) {
return FALSE; return FALSE;
@ -410,7 +410,8 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl,
* @returns The New Edge * @returns The New Edge
*/ */
BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, const int join_faces) BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
const short join_faces, const short kill_degenerate_faces)
{ {
BMEdge *ne = NULL; BMEdge *ne = NULL;
BMVert *tv = bmesh_edge_getothervert(ke, kv); BMVert *tv = bmesh_edge_getothervert(ke, kv);
@ -471,15 +472,28 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, con
} }
BLI_array_free(faces); BLI_array_free(faces);
return ne;
} }
else {
/* single face or no faces */
/* same as BM_vert_collapse_edge() however we already
* have vars to perform this operation so dont call. */
ne = bmesh_jekv(bm, ke, kv, TRUE);
/* ne = BM_edge_exists(tv, tv2); */ /* same as return above */
/* single face or no faces */ if (kill_degenerate_faces) {
/* same as BM_vert_collapse_edge() however we already BMIter fiter;
* have vars to perform this operation so dont call. */ BMFace *f;
ne = bmesh_jekv(bm, ke, kv, TRUE); BMVert *verts[2] = {ne->v1, ne->v2};
/* ne = BM_edge_exists(tv, tv2); */ /* same as return above */ int i;
for (i = 0; i < 2; i++) {
BM_ITER(f, &fiter, bm, BM_FACES_OF_VERT, verts[i]) {
if (f->len < 3) {
BM_face_kill(bm, f);
}
}
}
}
}
return ne; return ne;
} }
@ -494,7 +508,8 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, con
* The New Edge * The New Edge
*/ */
BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv) BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv,
const short kill_degenerate_faces)
{ {
/* nice example implementation but we want loops to have their customdata /* nice example implementation but we want loops to have their customdata
* accounted for */ * accounted for */
@ -523,7 +538,7 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv)
#else #else
/* with these args faces are never joined, same as above /* with these args faces are never joined, same as above
* but account for loop customdata */ * but account for loop customdata */
return BM_vert_collapse_faces(bm, ke, kv, 1.0f, FALSE); return BM_vert_collapse_faces(bm, ke, kv, 1.0f, FALSE, kill_degenerate_faces);
#endif #endif
} }

@ -165,7 +165,7 @@ void dissolvefaces_exec(BMesh *bm, BMOperator *op)
BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) { BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
if (BM_vert_edge_count(v) == 2) { if (BM_vert_edge_count(v) == 2) {
BM_vert_collapse_edge(bm, v->e, v); BM_vert_collapse_edge(bm, v->e, v, TRUE);
} }
} }
} }
@ -216,7 +216,7 @@ void dissolve_edgeloop_exec(BMesh *bm, BMOperator *op)
/* clean up extreneous 2-valence vertice */ /* clean up extreneous 2-valence vertice */
for (i = 0; i < BLI_array_count(verts); i++) { for (i = 0; i < BLI_array_count(verts); i++) {
if (verts[i]->e) { if (verts[i]->e) {
BM_vert_collapse_edge(bm, verts[i]->e, verts[i]); BM_vert_collapse_edge(bm, verts[i]->e, verts[i], TRUE);
} }
} }
@ -265,7 +265,7 @@ void dissolveedges_exec(BMesh *bm, BMOperator *op)
BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) { BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
if (BM_vert_edge_count(v) == 2) { if (BM_vert_edge_count(v) == 2) {
BM_vert_collapse_edge(bm, v->e, v); BM_vert_collapse_edge(bm, v->e, v, TRUE);
} }
} }
} }
@ -334,7 +334,14 @@ void dissolveverts_exec(BMesh *bm, BMOperator *op)
if (BM_vert_edge_count(v) == 2) { if (BM_vert_edge_count(v) == 2) {
/* collapse the ver */ /* collapse the ver */
BM_vert_collapse_faces(bm, v->e, v, 1.0f, FALSE); /* previously the faces were joined, but collapsing between 2 edges
* gives some advantage/difference in using vertex-dissolve over edge-dissolve */
#if 0
BM_vert_collapse_faces(bm, v->e, v, 1.0f, TRUE, TRUE);
#else
BM_vert_collapse_edge(bm, v->e, v, TRUE);
#endif
continue; continue;
} }
@ -540,7 +547,7 @@ void dissolvelimit_exec(BMesh *bm, BMOperator *op)
BMVert *v = (BMVert *)weight_elems[i].ele; BMVert *v = (BMVert *)weight_elems[i].ele;
/* check twice because cumulative effect could disolve over angle limit */ /* check twice because cumulative effect could disolve over angle limit */
if (BM_vert_edge_angle(bm, v) < angle_limit) { if (BM_vert_edge_angle(bm, v) < angle_limit) {
BM_vert_collapse_edge(bm, v->e, v); /* join edges */ BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */
} }
} }
} }

@ -530,14 +530,14 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti
ke = kl->e; ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */ /* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e); jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e);
BM_vert_collapse_edge(bm, ke, kv); BM_vert_collapse_edge(bm, ke, kv, FALSE);
} }
else { else {
BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e); BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e);
ke = kl->e; ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */ /* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e); jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e);
BM_vert_collapse_edge(bm, ke, kv); BM_vert_collapse_edge(bm, ke, kv, FALSE);
} }
/* find saved loop pointer */ /* find saved loop pointer */
l = se->l; l = se->l;
@ -576,14 +576,14 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti
ke = kl->e; ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */ /* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e); jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e);
BM_vert_collapse_edge(bm, ke, kv); BM_vert_collapse_edge(bm, ke, kv, FALSE);
} }
else { else {
BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e); BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e);
ke = kl->e; ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */ /* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e); jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e);
BM_vert_collapse_edge(bm, ke, kv); BM_vert_collapse_edge(bm, ke, kv, FALSE);
} }
/* find saved loop pointer */ /* find saved loop pointer */
l = se->l; l = se->l;

@ -88,7 +88,7 @@ static PyObject *bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObjec
bm = py_edge->bm; bm = py_edge->bm;
e_new = BM_vert_collapse_edge(bm, py_edge->e, py_vert->v); e_new = BM_vert_collapse_edge(bm, py_edge->e, py_vert->v, TRUE);
if (e_new) { if (e_new) {
return BPy_BMEdge_CreatePyObject(bm, e_new); return BPy_BMEdge_CreatePyObject(bm, e_new);
@ -154,7 +154,7 @@ static PyObject *bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObje
bm = py_edge->bm; bm = py_edge->bm;
e_new = BM_vert_collapse_faces(bm, py_edge->e, py_vert->v, CLAMPIS(fac, 0.0f, 1.0f), do_join_faces); e_new = BM_vert_collapse_faces(bm, py_edge->e, py_vert->v, CLAMPIS(fac, 0.0f, 1.0f), do_join_faces, TRUE);
if (e_new) { if (e_new) {
return BPy_BMEdge_CreatePyObject(bm, e_new); return BPy_BMEdge_CreatePyObject(bm, e_new);