diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-11-08 02:39:47 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-11-08 02:39:47 +0400 |
commit | c0fb605a04d64d8efd5176ea1e7b217e7d2d768d (patch) | |
tree | 18eb4849b7c2e490ebdcc710ec630ad3c970eef5 /source/blender/bmesh | |
parent | 620a78c106c4615a9e08d682fa099b889fad597c (diff) |
fix [#26472] Decimate overlaps polygons
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_decimate_collapse.c | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/intern/bmesh_decimate_collapse.c index f8b1a638558..15f774e50a8 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/intern/bmesh_decimate_collapse.c @@ -133,6 +133,56 @@ static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], } } +static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3]) +{ + BMIter liter; + BMLoop *l; + unsigned int i; + + for (i = 0; i < 2; i++) { + /* loop over both verts */ + BMVert *v = *((&e->v1) + i); + + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + if (l->e != e && l->prev->e != e) { + float *co_prev = l->prev->v->co; + float *co_next = l->next->v->co; + float cross_exist[3]; + float cross_optim[3]; + +#if 1 + float vec_other[3]; /* line between the two outer verts, re-use for both cross products */ + float vec_exist[3]; /* before collapse */ + float vec_optim[3]; /* after collapse */ + + sub_v3_v3v3(vec_other, co_prev, co_next); + sub_v3_v3v3(vec_exist, co_prev, v->co); + sub_v3_v3v3(vec_optim, co_prev, optimize_co); + + cross_v3_v3v3(cross_exist, vec_other, vec_exist); + cross_v3_v3v3(cross_optim, vec_other, vec_optim); + + /* normalize isn't really needed, but ensures the value at a unit we can compare against */ + normalize_v3(cross_exist); + normalize_v3(cross_optim); +#else + normal_tri_v3(cross_exist, v->co, co_prev, co_next); + normal_tri_v3(cross_optim, optimize_co, co_prev, co_next); +#endif + + /* use a small value rather then zero so we don't flip a face in multiple steps + * (first making it zero area, then flipping again)*/ + if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) { + //printf("no flip\n"); + return TRUE; + } + } + } + } + + return FALSE; +} + static void bm_decim_build_edge_cost_single(BMEdge *e, const Quadric *vquadrics, const float *vweights, Heap *eheap, HeapNode **eheap_table) @@ -795,6 +845,12 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, bm_decim_calc_target_co(e, optimize_co, vquadrics); + /* check if this would result in an overlapping face */ + if (UNLIKELY(bm_edge_collapse_is_degenerate_flip(e, optimize_co))) { + bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */ + return; + } + /* use for customdata merging */ if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) { customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co); @@ -859,7 +915,10 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, } while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first); } -#if 0 + /* this block used to be disabled, + * but enable now since surrounding faces may have been + * set to COST_INVALID because of a face overlap that no longer occurs */ +#if 1 /* optional, update edges around the vertex face fan */ { BMIter liter; @@ -874,7 +933,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE); - bm_decim_build_edge_cost_single(e_outer, vquadrics, eheap, eheap_table); + bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, eheap, eheap_table); } } } |