Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2013-08-14 03:48:48 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-08-14 03:48:48 +0400
commit5157eea9777182016fc648262077d644c736184b (patch)
treeafbb7af023dacdcba3a8cb4fc847dcb5aeeb1fb8
parent5ba898d86894e067960a000f3c05f03baa1d2695 (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.
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c142
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);