diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-08-14 03:48:48 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-08-14 03:48:48 +0400 |
commit | 5157eea9777182016fc648262077d644c736184b (patch) | |
tree | afbb7af023dacdcba3a8cb4fc847dcb5aeeb1fb8 /source/blender | |
parent | 5ba898d86894e067960a000f3c05f03baa1d2695 (diff) |
bmesh edge-net: refactor out face creation into its own function, replace array reallocation with alloca.
fix for error increasing the face tag count when the face might not be created.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/bmesh/operators/bmo_edgenet.c | 142 |
1 files changed, 75 insertions, 67 deletions
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c index e53e97ecc1c..923b877b822 100644 --- a/source/blender/bmesh/operators/bmo_edgenet.c +++ b/source/blender/bmesh/operators/bmo_edgenet.c @@ -31,6 +31,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_array.h" +#include "BLI_alloca.h" #include "BLI_smallhash.h" #include "BLI_rand.h" #include "BLI_heap.h" @@ -885,6 +886,67 @@ BLI_INLINE void vote_on_winding(BMEdge *edge, EPathNode *node, unsigned int wind winding[(test_v1 == node->v)]++; } +static BMFace *bm_face_from_path(BMesh *bm, EPath *path, + EdgeData *edata, + const bool use_fill_check) +{ + /* accumulte winding directions for each edge which has a face */ + const unsigned int path_len = BLI_countlist(&path->nodes); + unsigned int winding[2] = {0, 0}; + unsigned int i; + + EPathNode *node; + + BMVert **verts = BLI_array_alloca(verts, path_len); + BMEdge **edges = BLI_array_alloca(edges, path_len); + BMEdge *e; + BMVert *v; + + for (node = path->nodes.first, i = 0; node; node = node->next, i++) { + + v = node->v; + e = BM_edge_exists(v, node->next ? + node->next->v : + ((EPathNode *)path->nodes.first)->v); + + /* check on the winding */ + if (e->l) { + if (UNLIKELY(count_edge_faces(bm, e) >= 2)) { + return NULL; + } + + vote_on_winding(e, node, winding); + } + + verts[i] = v; + edges[i] = e; + } + + /* do after incase we bail early, above */ + for (i = 0; i < path_len; i++) { + edata[BM_elem_index_get(edges[i])].ftag++; + } + + + /* if these are even it doesn't really matter what to do, + * with consistent geometry one will be zero, the choice is clear */ + if (winding[0] > winding[1]) { + BLI_array_wrap(verts, path_len, -1); + BLI_array_reverse(verts, path_len); + BLI_array_reverse(edges, path_len); + } + + if ((use_fill_check == false) || + /* fairly expensive check - see if there are already faces filling this area */ + (BM_face_exists_multi(verts, edges, path_len) == false)) + { + return BM_face_create(bm, verts, edges, path_len, BM_CREATE_NO_DOUBLE); + } + else { + return NULL; + } +} + void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) { BMIter iter; @@ -892,18 +954,14 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) BMFace *f; BMEdge *e; EPath *path; - EPathNode *node; EdgeData *edata; VertData *vdata; - BMEdge **edges = NULL; PathBase *pathbase; - BLI_array_declare(edges); const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict"); const bool use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check"); const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr"); const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth"); int i; - unsigned int winding[2]; /* accumulte winding directions for each edge which has a face */ BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict"); BMOpSlot *slot_face_groupmap_out = BMO_slot_get(op->slots_out, "face_groupmap.out"); @@ -976,78 +1034,28 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) edata[BM_elem_index_get(edge)].tag += 1; path = edge_find_shortest_path(bm, op, edge, edata, vdata, pathbase, group); - if (!path) - continue; - - winding[0] = winding[1] = 0; - - BLI_array_empty(edges); - i = 0; - for (node = path->nodes.first; node; node = node->next) { - e = BM_edge_exists(node->v, node->next ? - node->next->v : - ((EPathNode *)path->nodes.first)->v); - - if (count_edge_faces(bm, e) >= 2) { - edge_free_path(pathbase, path); - break; - } - - /* check on the winding */ - if (e->l) { - vote_on_winding(e, node, winding); + if (path && path->nodes.first) { + BMFace *f = bm_face_from_path(bm, path, edata, + use_fill_check); + + if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) { + BMO_elem_flag_enable(bm, f, FACE_NEW); + f->mat_nr = mat_nr; + if (use_smooth) { + BM_elem_flag_enable(f, BM_ELEM_SMOOTH); + } } - edata[BM_elem_index_get(e)].ftag++; - BLI_array_grow_one(edges); - edges[i++] = e; - } - - /* above loop quit early */ - if (node) { - continue; - } - - if (i) { - BMVert *v1, *v2; - - /* if these are even it doesn't really matter what to do, - * with consistent geometry one will be zero, the choice is clear */ - node = path->nodes.first; - if (winding[0] < winding[1]) { - v1 = node->v; - v2 = node->next->v; - } - else { - v1 = node->next->v; - v2 = node->v; + if (use_restrict) { + BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group); } - if ((use_fill_check == false) || - /* fairly expensive check - see if there are already faces filling this area */ - (BM_face_exists_multi_edge(edges, i) == false)) - { - f = BM_face_create_ngon(bm, v1, v2, edges, i, BM_CREATE_NO_DOUBLE); - if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) { - BMO_elem_flag_enable(bm, f, FACE_NEW); - f->mat_nr = mat_nr; - if (use_smooth) { - BM_elem_flag_enable(f, BM_ELEM_SMOOTH); - } - } - - if (use_restrict) { - BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group); - } - } + edge_free_path(pathbase, path); } - - edge_free_path(pathbase, path); } BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW); - BLI_array_free(edges); edge_pathbase_free(pathbase); MEM_freeN(edata); MEM_freeN(vdata); |