diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-10-20 13:48:41 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-10-20 13:48:41 +0400 |
commit | a7a723283b9ec72888850999993287b598ceaecd (patch) | |
tree | d70d719afdf934e4bb07bae3d3f56724fa1b9572 /source | |
parent | 95a414955ce2d15c62adde665ced18804ca98945 (diff) |
add BM_edge_find_double() and use in bmesh decimator to fix crash.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_decimate.c | 27 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.c | 22 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.h | 1 |
3 files changed, 49 insertions, 1 deletions
diff --git a/source/blender/bmesh/intern/bmesh_decimate.c b/source/blender/bmesh/intern/bmesh_decimate.c index 122f24955c6..519bdba02a9 100644 --- a/source/blender/bmesh/intern/bmesh_decimate.c +++ b/source/blender/bmesh/intern/bmesh_decimate.c @@ -503,8 +503,31 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, BMEdge *e_first; e_iter = e_first = v->e; do { + //BLI_assert(BM_edge_find_double(e_iter) == NULL); +#ifdef USE_SAFETY_CHECKS + /* note! - this check is slow, but we can't avoid it - Campbell */ + BMEdge *e_double; + + e_double = BM_edge_find_double(e_iter); + + if (UNLIKELY(e_double != NULL)) { + int e_index = BM_elem_index_get(e_double); + if (BM_edge_splice(bm, e_double, e_iter)) { + if (eheap_table[e_index]) { + BLI_heap_remove(eheap, eheap_table[e_index]); + eheap_table[e_index] = NULL; + } + } + } + + /* if this happens, the e_double check could be put in a while loop, + * so as to keep removing doubles while they are found. so far this isnt needed */ + BLI_assert(BM_edge_find_double(e_iter) == NULL); +#endif + bm_decim_build_edge_cost_single(e_iter, vquadrics, eheap, eheap_table); } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } } } @@ -566,9 +589,11 @@ void BM_mesh_decimate(BMesh *bm, const float factor) } #endif - /* free vars */ MEM_freeN(vquadrics); MEM_freeN(eheap_table); BLI_heap_free(eheap, NULL); + + /* testing only */ + // BM_mesh_validate(bm); } diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 6bf4e3db1d3..9520b0298d8 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1064,6 +1064,28 @@ BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2) } /** + * Returns an edge sharing the same vertices as this one. + * This isn't an invalid state but tools should clean up these cases before + * returning the mesh to the user. + */ +BMEdge *BM_edge_find_double(BMEdge *e) +{ + BMVert *v = e->v1; + BMVert *v_other = e->v2; + + BMEdge *e_iter; + + e_iter = e; + while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e) { + if (UNLIKELY(BM_vert_in_edge(e_iter, v_other))) { + return e_iter; + } + } + + return NULL; +} + +/** * Given a set of vertices \a varr, find out if * all those vertices overlap an existing face. * diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 84a5ffacec7..166b8a54f8a 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -74,6 +74,7 @@ BMLoop *BM_face_find_shortest_loop(BMFace *f); BMLoop *BM_face_find_longest_loop(BMFace *f); BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2); +BMEdge *BM_edge_find_double(BMEdge *e); int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_existface); |