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:
Diffstat (limited to 'source/blender/bmesh/operators')
-rw-r--r--source/blender/bmesh/operators/bmo_bevel.c3
-rw-r--r--source/blender/bmesh/operators/bmo_bridge.c4
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c93
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c72
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c46
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c11
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c4
-rw-r--r--source/blender/bmesh/operators/bmo_extrude.c64
-rw-r--r--source/blender/bmesh/operators/bmo_fill_attribute.c2
-rw-r--r--source/blender/bmesh/operators/bmo_fill_grid.c4
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c6
-rw-r--r--source/blender/bmesh/operators/bmo_poke.c2
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c34
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c5
-rw-r--r--source/blender/bmesh/operators/bmo_smooth_laplacian.c2
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c8
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c158
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c2
18 files changed, 400 insertions, 120 deletions
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index 07a2e674863..213a0830e63 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -40,6 +40,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
const int seg = BMO_slot_int_get(op->slots_in, "segments");
const bool vonly = BMO_slot_bool_get(op->slots_in, "vertex_only");
const float profile = BMO_slot_float_get(op->slots_in, "profile");
+ const int material = BMO_slot_int_get(op->slots_in, "material");
if (offset > 0) {
BMOIter siter;
@@ -60,7 +61,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
}
}
- BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, false, NULL, -1);
+ BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, false, NULL, -1, material);
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
}
diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c
index 9e9cd0d66e2..e4417477e76 100644
--- a/source/blender/bmesh/operators/bmo_bridge.c
+++ b/source/blender/bmesh/operators/bmo_bridge.c
@@ -119,7 +119,7 @@ static void bm_bridge_best_rotation(struct BMEdgeLoopStore *el_store_a, struct B
}
if (el_b_best) {
- BLI_rotatelist_first(lb_b, el_b_best);
+ BLI_listbase_rotate_first(lb_b, el_b_best);
}
}
@@ -272,7 +272,7 @@ static void bridge_loop_pair(BMesh *bm,
const int len_b = BM_edgeloop_length_get(el_store_b);
ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
LinkData *el_b = BLI_rfindlink(lb_b, mod_i(twist_offset, len_b));
- BLI_rotatelist_first(lb_b, el_b);
+ BLI_listbase_rotate_first(lb_b, el_b);
}
}
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index 4cf6e82fc8e..0213329118c 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -36,54 +36,68 @@
#include "intern/bmesh_operators_private.h" /* own include */
#define VERT_INPUT 1
+
#define EDGE_OUT 1
-#define FACE_TAG 2
+/* Edge spans 2 VERT_INPUT's, its a nop,
+ * but include in "edges.out" */
+#define EDGE_OUT_ADJ 2
+
+#define FACE_TAG 2
+#define FACE_EXCLUDE 4
static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenerate)
{
- BMLoop *(*loops_split)[2] = BLI_array_alloca(loops_split, f->len);
+ const unsigned pair_split_max = f->len / 2;
+ BMLoop *(*loops_split)[2] = BLI_array_alloca(loops_split, pair_split_max);
STACK_DECLARE(loops_split);
- BMVert *(*verts_pair)[2] = BLI_array_alloca(verts_pair, f->len);
+ BMVert *(*verts_pair)[2] = BLI_array_alloca(verts_pair, pair_split_max);
STACK_DECLARE(verts_pair);
- BMIter liter;
- BMFace *f_new;
- BMLoop *l;
- BMLoop *l_last;
+ BMLoop *l_tag_prev = NULL, *l_tag_first = NULL;
+ BMLoop *l_iter, *l_first;
unsigned int i;
- STACK_INIT(loops_split, f->len);
- STACK_INIT(verts_pair, f->len);
+ STACK_INIT(loops_split, pair_split_max);
+ STACK_INIT(verts_pair, pair_split_max);
- l_last = NULL;
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (BMO_elem_flag_test(bm, l->v, VERT_INPUT)) {
- if (!l_last) {
- l_last = l;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BMO_elem_flag_test(bm, l_iter->v, VERT_INPUT) &&
+ /* ensure this vertex isnt part of a contiguous group */
+ ((BMO_elem_flag_test(bm, l_iter->prev->v, VERT_INPUT) == 0) ||
+ (BMO_elem_flag_test(bm, l_iter->next->v, VERT_INPUT) == 0)))
+ {
+ if (!l_tag_prev) {
+ l_tag_prev = l_tag_first = l_iter;
continue;
}
- if (!BM_loop_is_adjacent(l_last, l)) {
+ if (!BM_loop_is_adjacent(l_tag_prev, l_iter)) {
BMEdge *e;
- e = BM_edge_exists(l_last->v, l->v);
+ e = BM_edge_exists(l_tag_prev->v, l_iter->v);
if (e == NULL || !BMO_elem_flag_test(bm, e, EDGE_OUT)) {
BMLoop **l_pair = STACK_PUSH_RET(loops_split);
- l_pair[0] = l_last;
- l_pair[1] = l;
+ l_pair[0] = l_tag_prev;
+ l_pair[1] = l_iter;
}
}
- l_last = l;
+
+ l_tag_prev = l_iter;
}
- }
+ } while ((l_iter = l_iter->next) != l_first);
if (STACK_SIZE(loops_split) == 0) {
return 0;
}
- if (STACK_SIZE(loops_split) > 1) {
+ if (!BM_loop_is_adjacent(l_tag_first, l_tag_prev) &&
+ /* ensure we don't add the same pair twice */
+ (((loops_split[0][0] == l_tag_first) &&
+ (loops_split[0][1] == l_tag_prev)) == 0))
+ {
BMLoop **l_pair = STACK_PUSH_RET(loops_split);
- l_pair[0] = loops_split[STACK_SIZE(loops_split) - 2][1];
- l_pair[1] = loops_split[0][0];
+ l_pair[0] = l_tag_first;
+ l_pair[1] = l_tag_prev;
}
if (check_degenerate) {
@@ -105,6 +119,7 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenera
}
for (i = 0; i < STACK_SIZE(verts_pair); i++) {
+ BMFace *f_new;
BMLoop *l_new;
BMLoop *l_a, *l_b;
@@ -134,7 +149,6 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenera
void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
{
BMOIter siter;
- BMIter iter;
BMVert *v;
BMFace *f;
const bool check_degenerate = BMO_slot_bool_get(op->slots_in, "check_degenerate");
@@ -142,16 +156,35 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
BLI_LINKSTACK_INIT(faces);
+ /* tag so we won't touch ever (typically hidden faces) */
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces_exclude", BM_FACE, FACE_EXCLUDE);
+
/* add all faces connected to verts */
BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+ BMIter iter;
+ BMLoop *l_iter;
+
BMO_elem_flag_enable(bm, v, VERT_INPUT);
- BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
- if (!BMO_elem_flag_test(bm, f, FACE_TAG)) {
- BMO_elem_flag_enable(bm, f, FACE_TAG);
- if (f->len > 3) {
- BLI_LINKSTACK_PUSH(faces, f);
+ BM_ITER_ELEM (l_iter, &iter, v, BM_LOOPS_OF_VERT) {
+ f = l_iter->f;
+ if (!BMO_elem_flag_test(bm, f, FACE_EXCLUDE)) {
+ if (!BMO_elem_flag_test(bm, f, FACE_TAG)) {
+ BMO_elem_flag_enable(bm, f, FACE_TAG);
+ if (f->len > 3) {
+ BLI_LINKSTACK_PUSH(faces, f);
+ }
}
}
+
+ /* flag edges even if these are not newly created
+ * this way cut-pairs that include co-linear edges will get
+ * predictable output. */
+ if (BMO_elem_flag_test(bm, l_iter->prev->v, VERT_INPUT)) {
+ BMO_elem_flag_enable(bm, l_iter->prev->e, EDGE_OUT_ADJ);
+ }
+ if (BMO_elem_flag_test(bm, l_iter->next->v, VERT_INPUT)) {
+ BMO_elem_flag_enable(bm, l_iter->e, EDGE_OUT_ADJ);
+ }
}
}
@@ -164,5 +197,5 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
BLI_LINKSTACK_FREE(faces);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT | EDGE_OUT_ADJ);
}
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index b497ab2f693..a0acf6ed2c5 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -51,6 +51,15 @@
#define CONNECT_EPS 0.0001f
#define VERT_OUT 1
+#define VERT_EXCLUDE 2
+
+/* typically hidden faces */
+#define FACE_EXCLUDE 2
+
+#define FACE_WALK_TEST(f) (CHECK_TYPE_INLINE(f, BMFace *), \
+ BMO_elem_flag_test(pc->bm_bmoflag, f, FACE_EXCLUDE) == 0)
+#define VERT_WALK_TEST(v) (CHECK_TYPE_INLINE(v, BMVert *), \
+ BMO_elem_flag_test(pc->bm_bmoflag, v, VERT_EXCLUDE) == 0)
// #define DEBUG_PRINT
@@ -59,6 +68,9 @@ typedef struct PathContext {
float matrix[3][3];
float axis_sep;
+ /* only to access BMO flags */
+ BMesh *bm_bmoflag;
+
BMVert *v_a, *v_b;
BLI_mempool *link_pool;
@@ -134,7 +146,7 @@ static void state_calc_co_pair(const PathContext *pc,
static bool state_link_find(PathLinkState *state, BMElem *ele)
{
PathLink *link = state->link_last;
- BLI_assert(ELEM3(ele->head.htype, BM_VERT, BM_EDGE, BM_FACE));
+ BLI_assert(ELEM(ele->head.htype, BM_VERT, BM_EDGE, BM_FACE));
if (link) {
do {
if (link->ele == ele) {
@@ -204,8 +216,9 @@ static void state_link_add(PathContext *pc, PathLinkState *state,
state->link_last = step_new;
}
-static PathLinkState *state_dupe_add(PathContext *pc,
- PathLinkState *state, const PathLinkState *state_orig)
+static PathLinkState *state_dupe_add(
+ PathContext *pc,
+ PathLinkState *state, const PathLinkState *state_orig)
{
state = MEM_mallocN(sizeof(*state), __func__);
*state = *state_orig;
@@ -214,16 +227,19 @@ static PathLinkState *state_dupe_add(PathContext *pc,
}
/* walk around the face edges */
-static PathLinkState *state_step__face_edges(PathContext *pc,
- PathLinkState *state, const PathLinkState *state_orig,
- BMLoop *l_iter, BMLoop *l_last)
+static PathLinkState *state_step__face_edges(
+ PathContext *pc,
+ PathLinkState *state, const PathLinkState *state_orig,
+ BMLoop *l_iter, BMLoop *l_last)
{
do {
if (state_isect_co_pair(pc, l_iter->v->co, l_iter->next->v->co)) {
BMElem *ele_next = (BMElem *)l_iter->e;
BMElem *ele_next_from = (BMElem *)l_iter->f;
- if (state_link_find(state, ele_next) == false) {
+ if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
+ (state_link_find(state, ele_next) == false))
+ {
if (state_orig->link_last != state->link_last) {
state = state_dupe_add(pc, state, state_orig);
}
@@ -235,16 +251,19 @@ static PathLinkState *state_step__face_edges(PathContext *pc,
}
/* walk around the face verts */
-static PathLinkState *state_step__face_verts(PathContext *pc,
- PathLinkState *state, const PathLinkState *state_orig,
- BMLoop *l_iter, BMLoop *l_last)
+static PathLinkState *state_step__face_verts(
+ PathContext *pc,
+ PathLinkState *state, const PathLinkState *state_orig,
+ BMLoop *l_iter, BMLoop *l_last)
{
do {
if (state_isect_co_exact(pc, l_iter->v->co)) {
BMElem *ele_next = (BMElem *)l_iter->v;
BMElem *ele_next_from = (BMElem *)l_iter->f;
- if (state_link_find(state, ele_next) == false) {
+ if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
+ state_link_find(state, ele_next) == false)
+ {
if (state_orig->link_last != state->link_last) {
state = state_dupe_add(pc, state, state_orig);
}
@@ -268,7 +287,9 @@ static bool state_step(PathContext *pc, PathLinkState *state)
BMLoop *l_start;
BM_ITER_ELEM (l_start, &liter, e, BM_LOOPS_OF_EDGE) {
- if (l_start->f != ele_from) {
+ if ((l_start->f != ele_from) &&
+ FACE_WALK_TEST(l_start->f))
+ {
/* very similar to block below */
if (BM_vert_in_face(l_start->f, pc->v_b)) {
if (state_orig.link_last != state->link_last) {
@@ -295,7 +316,9 @@ static bool state_step(PathContext *pc, PathLinkState *state)
BMLoop *l_start;
BM_ITER_ELEM (l_start, &liter, v, BM_LOOPS_OF_VERT) {
- if (l_start->f != ele_from) {
+ if ((l_start->f != ele_from) &&
+ FACE_WALK_TEST(l_start->f))
+ {
/* very similar to block above */
if (BM_vert_in_face(l_start->f, pc->v_b)) {
BMElem *ele_next = (BMElem *)pc->v_b;
@@ -324,8 +347,10 @@ static bool state_step(PathContext *pc, PathLinkState *state)
BMIter eiter;
BMEdge *e;
BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if ((BMElem *)e != ele_from) {
- BMVert *v_other = BM_edge_other_vert(e, v);
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (((BMElem *)e != ele_from) &&
+ VERT_WALK_TEST(v_other))
+ {
if (v_other == pc->v_b) {
BMElem *ele_next = (BMElem *)pc->v_b;
BMElem *ele_next_from = (BMElem *)e;
@@ -371,6 +396,7 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
return;
}
+ pc.bm_bmoflag = bm;
pc.v_a = ((BMVert **)op_verts_slot->data.p)[0];
pc.v_b = ((BMVert **)op_verts_slot->data.p)[1];
@@ -384,6 +410,10 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
printf("%s: v_b: %d\n", __func__, BM_elem_index_get(pc.v_b));
#endif
+ /* tag so we won't touch ever (typically hidden faces) */
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces_exclude", BM_FACE, FACE_EXCLUDE);
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts_exclude", BM_VERT, VERT_EXCLUDE);
+
/* setup context */
{
BLI_listbase_clear(&pc.state_lb);
@@ -468,9 +498,7 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
BLI_remlink(&pc.state_lb, state);
MEM_freeN(state);
}
- else {
- found_all = false;
- }
+ found_all = false;
}
else {
/* didn't reach the end, remove it,
@@ -481,6 +509,11 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
}
if (found_all) {
+#ifdef DEBUG
+ for (state = pc.state_lb.first; state; state = state->next) {
+ BLI_assert(state->link_last->ele == (BMElem *)pc.v_b);
+ }
+#endif
break;
}
}
@@ -533,7 +566,8 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
* always connect even when resulting faces are degenerate [#39418] */
BMOperator op_sub;
BMO_op_initf(bm, &op_sub, 0,
- "connect_verts verts=%fv", VERT_OUT);
+ "connect_verts verts=%fv faces_exclude=%s",
+ VERT_OUT, op, "faces_exclude");
BMO_op_exec(bm, &op_sub);
BMO_slot_copy(&op_sub, slots_out, "edges.out",
op, slots_out, "edges.out");
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index 209ca30ddc3..8cd9ee14bcb 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -29,6 +29,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_array.h"
+#include "BLI_stack.h"
#include "BLI_math.h"
#include "bmesh.h"
@@ -51,6 +52,7 @@
#define VERT_MARK_PAIR 4
#define VERT_TAG 2
#define VERT_ISGC 8
+#define VERT_MARK_TEAR 16
@@ -85,15 +87,20 @@ static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f)
return true;
}
-static void bm_face_split(BMesh *bm, const short oflag)
+static void bm_face_split(BMesh *bm, const short oflag, bool use_edge_delete)
{
+ BLI_Stack *edge_delete_verts;
BMIter iter;
BMVert *v;
- BMIter liter;
+ if (use_edge_delete) {
+ edge_delete_verts = BLI_stack_new(sizeof(BMVert *), __func__);
+ }
+
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, oflag)) {
if (BM_vert_is_edge_pair(v) == false) {
+ BMIter liter;
BMLoop *l;
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
if (l->f->len > 3) {
@@ -104,8 +111,23 @@ static void bm_face_split(BMesh *bm, const short oflag)
}
}
}
+
+ if (use_edge_delete) {
+ BLI_stack_push(edge_delete_verts, &v);
+ }
+ }
+ }
+ }
+
+ if (use_edge_delete) {
+ while (!BLI_stack_is_empty(edge_delete_verts)) {
+ /* remove surrounding edges & faces */
+ BLI_stack_pop(edge_delete_verts, &v);
+ while (v->e) {
+ BM_edge_kill(bm, v->e);
}
}
+ BLI_stack_free(edge_delete_verts);
}
}
@@ -268,7 +290,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
}
}
- bm_face_split(bm, VERT_TAG);
+ bm_face_split(bm, VERT_TAG, false);
}
if (use_verts) {
@@ -345,13 +367,29 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
BMFace *act_face = bm->act_face;
const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
+ const bool use_boundary_tear = BMO_slot_bool_get(op->slots_in, "use_boundary_tear");
BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
BMO_elem_flag_enable(bm, v, VERT_MARK | VERT_ISGC);
}
if (use_face_split) {
- bm_face_split(bm, VERT_MARK);
+ bm_face_split(bm, VERT_MARK, false);
+ }
+
+ if (use_boundary_tear) {
+ BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+ if (!BM_vert_is_edge_pair(v)) {
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_boundary(e)) {
+ BMO_elem_flag_enable(bm, v, VERT_MARK_TEAR);
+ break;
+ }
+ }
+ }
+ }
+
+ bm_face_split(bm, VERT_MARK_TEAR, true);
}
BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 794c688b26b..cd5592f08c9 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -183,6 +183,7 @@ static BMFace *bmo_face_copy(BMOperator *op,
*/
static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
{
+ const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
BMVert *v = NULL, *v2;
BMEdge *e = NULL;
@@ -285,6 +286,16 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
/* free pointer hashes */
BLI_ghash_free(vhash, NULL, NULL);
BLI_ghash_free(ehash, NULL, NULL);
+
+ if (use_select_history) {
+ BLI_assert(bm_src == bm_dst);
+ BMO_mesh_selected_remap(
+ bm_dst,
+ slot_vert_map_out,
+ slot_edge_map_out,
+ slot_face_map_out,
+ false);
+ }
}
/**
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c
index 0c5de590ccf..4423123f65e 100644
--- a/source/blender/bmesh/operators/bmo_edgenet.c
+++ b/source/blender/bmesh/operators/bmo_edgenet.c
@@ -179,11 +179,11 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op)
if (!count) {
edges1 = edges;
- BLI_array_length_set(edges1, BLI_array_count(edges));
+ BLI_array_count_set(edges1, BLI_array_count(edges));
}
else {
edges2 = edges;
- BLI_array_length_set(edges2, BLI_array_count(edges));
+ BLI_array_count_set(edges2, BLI_array_count(edges));
}
BLI_array_empty(edges);
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index 510c3ae0078..88b53b63abb 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -53,9 +53,16 @@ enum {
void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
{
+ const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
+ GHash *select_history_map = NULL;
+
BMOIter siter;
BMFace *f_org;
+ if (use_select_history) {
+ select_history_map = BM_select_history_map_create(bm);
+ }
+
BMO_ITER (f_org, &siter, op->slots_in, "faces", BM_FACE) {
BMFace *f_new;
BMLoop *l_org, *l_org_first;
@@ -66,6 +73,14 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
f_new = BM_face_copy(bm, bm, f_org, true, true);
BMO_elem_flag_enable(bm, f_new, EXT_KEEP);
+ if (select_history_map) {
+ BMEditSelection *ese;
+ ese = BLI_ghash_lookup(select_history_map, f_org);
+ if (ese) {
+ ese->ele = (BMElem *)f_new;
+ }
+ }
+
l_org = l_org_first = BM_FACE_FIRST_LOOP(f_org);
l_new = BM_FACE_FIRST_LOOP(f_new);
@@ -85,10 +100,28 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter); l_side_iter = l_side_iter->next;
BM_elem_attrs_copy(bm, bm, l_org, l_side_iter); l_side_iter = l_side_iter->next;
BM_elem_attrs_copy(bm, bm, l_org, l_side_iter);
+
+ if (select_history_map) {
+ BMEditSelection *ese;
+
+ ese = BLI_ghash_lookup(select_history_map, l_org->v);
+ if (ese) {
+ ese->ele = (BMElem *)l_new->v;
+ }
+ ese = BLI_ghash_lookup(select_history_map, l_org->e);
+ if (ese) {
+ ese->ele = (BMElem *)l_new->e;
+ }
+ }
+
} while (((l_new = l_new->next),
(l_org = l_org->next)) != l_org_first);
}
+ if (select_history_map) {
+ BLI_ghash_free(select_history_map, NULL, NULL);
+ }
+
BMO_op_callf(bm, op->flag,
"delete geom=%ff context=%i",
EXT_DEL, DEL_ONLYFACES);
@@ -157,7 +190,11 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, e->v2, EXT_INPUT);
}
- BMO_op_initf(bm, &dupeop, op->flag, "duplicate geom=%fve", EXT_INPUT);
+ BMO_op_initf(
+ bm, &dupeop, op->flag,
+ "duplicate geom=%fve use_select_history=%b",
+ EXT_INPUT, BMO_slot_bool_get(op->slots_in, "use_select_history"));
+
BMO_op_exec(bm, &dupeop);
/* disable root flag on all new skin nodes */
@@ -205,10 +242,16 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op)
void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
{
+ const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
BMOIter siter;
BMVert *v, *dupev;
BMEdge *e;
const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN);
+ GHash *select_history_map = NULL;
+
+ if (use_select_history) {
+ select_history_map = BM_select_history_map_create(bm);
+ }
for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) {
dupev = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
@@ -217,6 +260,14 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
if (has_vskin)
bm_extrude_disable_skin_root(bm, v);
+ if (select_history_map) {
+ BMEditSelection *ese;
+ ese = BLI_ghash_lookup(select_history_map, v);
+ if (ese) {
+ ese->ele = (BMElem *)dupev;
+ }
+ }
+
/* not essential, but ensures face normals from extruded edges are contiguous */
if (BM_vert_is_wire_endpoint(v)) {
if (v->e->v1 == v) {
@@ -228,6 +279,10 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, e, EXT_KEEP);
}
+ if (select_history_map) {
+ BLI_ghash_free(select_history_map, NULL, NULL);
+ }
+
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, EXT_KEEP);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP);
}
@@ -245,8 +300,11 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
BMOpSlot *slot_edges_exclude;
/* initialize our sub-operators */
- BMO_op_init(bm, &dupeop, op->flag, "duplicate");
-
+ BMO_op_initf(
+ bm, &dupeop, op->flag,
+ "duplicate use_select_history=%b",
+ BMO_slot_bool_get(op->slots_in, "use_select_history"));
+
BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, EXT_INPUT);
/* if one flagged face is bordered by an un-flagged face, then we delete
diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c
index fa77e6b509c..d9f50ac891c 100644
--- a/source/blender/bmesh/operators/bmo_fill_attribute.c
+++ b/source/blender/bmesh/operators/bmo_fill_attribute.c
@@ -154,7 +154,7 @@ static unsigned int bmesh_face_attribute_fill(BMesh *bm,
return face_tot;
}
-void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op)
+void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op)
{
const bool use_normals = BMO_slot_bool_get(op->slots_in, "use_normals");
const bool use_data = BMO_slot_bool_get(op->slots_in, "use_data");
diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c
index 6a0fca425f8..40f6937245b 100644
--- a/source/blender/bmesh/operators/bmo_fill_grid.c
+++ b/source/blender/bmesh/operators/bmo_fill_grid.c
@@ -313,12 +313,12 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const unsigned int xt
if (use_interp_simple == false) {
float co_a[3], co_b[3];
- barycentric_transform(
+ transform_point_by_tri_v3(
co_a,
v_grid[x]->co,
tri_t[0], tri_t[1], tri_t[2],
tri_a[0], tri_a[1], tri_a[2]);
- barycentric_transform(
+ transform_point_by_tri_v3(
co_b,
v_grid[(xtot * ytot) + (x - xtot)]->co,
tri_t[0], tri_t[1], tri_t[2],
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index 0ca4ddf8d55..f2e5ebad9c8 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -389,7 +389,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
const bool use_outset = BMO_slot_bool_get(op->slots_in, "use_outset");
const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary") && (use_outset == false);
const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
- const bool use_even_boundry = use_even_offset; /* could make own option */
+ const bool use_even_boundary = use_even_offset; /* could make own option */
const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
const bool use_edge_rail = BMO_slot_bool_get(op->slots_in, "use_edge_rail");
const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
@@ -716,7 +716,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
else if (vert_edge_tag_tot == 1) { /* 1 edge user - boundary vert, not so common */
const float *e_no_a = edge_info[vecpair[0]].no;
- if (use_even_boundry) {
+ if (use_even_boundary) {
/* This case where only one edge attached to v_split
* is used - ei - the face to inset is on a boundary.
@@ -984,7 +984,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
const float fac = (depth *
(use_relative_offset ? bm_edge_info_average_length(v, edge_info) : 1.0f) *
- (use_even_boundry ? BM_vert_calc_shell_factor(v) : 1.0f));
+ (use_even_boundary ? BM_vert_calc_shell_factor(v) : 1.0f));
madd_v3_v3v3fl(varr_co[i], v->co, v->no, fac);
}
}
diff --git a/source/blender/bmesh/operators/bmo_poke.c b/source/blender/bmesh/operators/bmo_poke.c
index 26f20656478..363e395e082 100644
--- a/source/blender/bmesh/operators/bmo_poke.c
+++ b/source/blender/bmesh/operators/bmo_poke.c
@@ -101,7 +101,7 @@ void bmo_poke_exec(BMesh *bm, BMOperator *op)
do {
BMLoop *l_new;
- f_new = BM_face_create_quad_tri(bm, l_iter->v, l_iter->next->v, v_center, NULL, f, false);
+ f_new = BM_face_create_quad_tri(bm, l_iter->v, l_iter->next->v, v_center, NULL, f, BM_CREATE_NOP);
l_new = BM_FACE_FIRST_LOOP(f_new);
if (i == 0) {
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index f0e31b78ca0..e69dcca6342 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -405,7 +405,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
v2 = eva[icoface[a][1]];
v3 = eva[icoface[a][2]];
- eftemp = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, false);
+ eftemp = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, BM_CREATE_NOP);
BM_ITER_ELEM (l, &liter, eftemp, BM_LOOPS_OF_FACE) {
BMO_elem_flag_enable(bm, l->e, EDGE_MARK);
@@ -476,14 +476,14 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
tv[monkeyf[i][1] + i - monkeyo],
tv[monkeyf[i][2] + i - monkeyo],
(monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeyf[i][3] + i - monkeyo] : NULL,
- NULL, false);
+ NULL, BM_CREATE_NOP);
BM_face_create_quad_tri(bm,
tv[monkeynv + monkeyf[i][2] + i - monkeyo],
tv[monkeynv + monkeyf[i][1] + i - monkeyo],
tv[monkeynv + monkeyf[i][0] + i - monkeyo],
(monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeynv + monkeyf[i][3] + i - monkeyo] : NULL,
- NULL, false);
+ NULL, BM_CREATE_NOP);
}
MEM_freeN(tv);
@@ -535,7 +535,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
if (a && cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
@@ -553,7 +553,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
if (cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
@@ -622,12 +622,12 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
if (cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
- f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
- BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, false);
+ BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, BM_CREATE_NOP);
}
else {
firstv1 = v1;
@@ -644,9 +644,9 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
if (cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
- f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, false);
+ f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
@@ -654,7 +654,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW);
}
- BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, false);
+ BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, BM_CREATE_NOP);
BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
@@ -726,14 +726,14 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, v8, VERT_MARK);
/* the four sides */
- BM_face_create_quad_tri(bm, v5, v6, v2, v1, NULL, false);
- BM_face_create_quad_tri(bm, v6, v7, v3, v2, NULL, false);
- BM_face_create_quad_tri(bm, v7, v8, v4, v3, NULL, false);
- BM_face_create_quad_tri(bm, v8, v5, v1, v4, NULL, false);
+ BM_face_create_quad_tri(bm, v5, v6, v2, v1, NULL, BM_CREATE_NOP);
+ BM_face_create_quad_tri(bm, v6, v7, v3, v2, NULL, BM_CREATE_NOP);
+ BM_face_create_quad_tri(bm, v7, v8, v4, v3, NULL, BM_CREATE_NOP);
+ BM_face_create_quad_tri(bm, v8, v5, v1, v4, NULL, BM_CREATE_NOP);
/* top/bottom */
- BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, false);
- BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, false);
+ BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, BM_CREATE_NOP);
+ BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, BM_CREATE_NOP);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index 814649c7dbf..75f9feef413 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -528,7 +528,8 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op,
int i, j, keepvert = 0;
const float dist = BMO_slot_float_get(op->slots_in, "dist");
- const float dist3 = dist * 3.0f;
+ const float dist_sq = dist * dist;
+ const float dist3 = (M_SQRT3 + 0.00005f) * dist; /* Just above sqrt(3) */
/* Test whether keep_verts arg exists and is non-empty */
if (BMO_slot_exists(op->slots_in, "keep_verts")) {
@@ -576,7 +577,7 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op,
continue;
}
- if (compare_len_v3v3(v_check->co, v_other->co, dist)) {
+ if (compare_len_squared_v3v3(v_check->co, v_other->co, dist_sq)) {
/* If one vert is marked as keep, make sure it will be the target */
if (BMO_elem_flag_test(bm, v_other, VERT_KEEP)) {
diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
index af5f35f2a75..a250c716c16 100644
--- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c
+++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
@@ -156,7 +156,7 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in
return sys;
}
-/* Compute weigth between vertice v_i and all your neighbors
+/* Compute weight between vertice v_i and all your neighbors
* weight between v_i and v_neighbor
* Wij = cot(alpha) + cot(beta) / (4.0 * total area of all faces * sum all weight)
* v_i *
diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
index e13a9df4474..c01ad10d716 100644
--- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c
+++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
@@ -727,8 +727,8 @@ static void bm_edgering_pair_interpolate(BMesh *bm, LoopPairStore *lpair,
tri_tmp = tri_array[i];
- barycentric_transform(co_a, v_a->co, UNPACK3(tri_tmp), UNPACK3(tri_sta));
- barycentric_transform(co_b, v_b->co, UNPACK3(tri_tmp), UNPACK3(tri_end));
+ transform_point_by_tri_v3(co_a, v_a->co, UNPACK3(tri_tmp), UNPACK3(tri_sta));
+ transform_point_by_tri_v3(co_b, v_b->co, UNPACK3(tri_tmp), UNPACK3(tri_end));
interp_v3_v3v3(((BMVert *)v_iter->data)->co, co_a, co_b, (float)i / (float)(resolu - 1));
}
@@ -920,13 +920,13 @@ static void bm_edgering_pair_order(BMesh *bm,
}
BLI_assert(node != NULL);
- BLI_rotatelist_first(lb_b, node);
+ BLI_listbase_rotate_first(lb_b, node);
/* now check we are winding the same way */
if (bm_edgering_pair_order_is_flipped(bm, el_store_a, el_store_b)) {
BM_edgeloop_flip(bm, el_store_b);
/* re-ensure the first node */
- BLI_rotatelist_first(lb_b, node);
+ BLI_listbase_rotate_first(lb_b, node);
}
/* sanity checks that we are aligned & winding now */
diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c
index 8e254b2e499..986583cc21b 100644
--- a/source/blender/bmesh/operators/bmo_triangulate.c
+++ b/source/blender/bmesh/operators/bmo_triangulate.c
@@ -26,10 +26,12 @@
* Triangulate faces, also defines triangle fill.
*/
+#include "MEM_guardedalloc.h"
+
#include "DNA_listBase.h"
#include "BLI_math.h"
-#include "BLI_smallhash.h"
+#include "BLI_sort_utils.h"
#include "BLI_scanfill.h"
#include "bmesh.h"
@@ -56,6 +58,10 @@ void bmo_triangulate_exec(BMesh *bm, BMOperator *op)
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
}
+struct SortNormal {
+ float value; /* keep first */
+ float no[3];
+};
void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
{
@@ -65,54 +71,153 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
BMEdge *e;
ScanFillContext sf_ctx;
/* ScanFillEdge *sf_edge; */ /* UNUSED */
- ScanFillVert *sf_vert_1, *sf_vert_2;
ScanFillFace *sf_tri;
- SmallHash hash;
- float normal[3], *normal_pt;
+ GHash *sf_vert_map;
+ float normal[3];
const int scanfill_flag = BLI_SCANFILL_CALC_HOLES | BLI_SCANFILL_CALC_POLYS | BLI_SCANFILL_CALC_LOOSE;
+ bool calc_winding = false;
- BLI_smallhash_init_ex(&hash, BMO_slot_buffer_count(op->slots_in, "edges"));
+ sf_vert_map = BLI_ghash_ptr_new_ex(__func__, BMO_slot_buffer_count(op->slots_in, "edges"));
BMO_slot_vec_get(op->slots_in, "normal", normal);
BLI_scanfill_begin(&sf_ctx);
BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ ScanFillVert *sf_verts[2];
+ BMVert **e_verts = &e->v1;
+ unsigned int i;
+
BMO_elem_flag_enable(bm, e, EDGE_MARK);
-
- if ((sf_vert_1 = BLI_smallhash_lookup(&hash, (uintptr_t)e->v1)) == NULL) {
- sf_vert_1 = BLI_scanfill_vert_add(&sf_ctx, e->v1->co);
- sf_vert_1->tmp.p = e->v1;
- BLI_smallhash_insert(&hash, (uintptr_t)e->v1, sf_vert_1);
- }
-
- if ((sf_vert_2 = BLI_smallhash_lookup(&hash, (uintptr_t)e->v2)) == NULL) {
- sf_vert_2 = BLI_scanfill_vert_add(&sf_ctx, e->v2->co);
- sf_vert_2->tmp.p = e->v2;
- BLI_smallhash_insert(&hash, (uintptr_t)e->v2, sf_vert_2);
+
+ calc_winding = (calc_winding || BM_edge_is_boundary(e));
+
+ for (i = 0; i < 2; i++) {
+ if ((sf_verts[i] = BLI_ghash_lookup(sf_vert_map, e_verts[i])) == NULL) {
+ sf_verts[i] = BLI_scanfill_vert_add(&sf_ctx, e_verts[i]->co);
+ sf_verts[i]->tmp.p = e_verts[i];
+ BLI_ghash_insert(sf_vert_map, e_verts[i], sf_verts[i]);
+ }
}
-
- /* sf_edge = */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_1, sf_vert_2);
+ /* sf_edge = */ BLI_scanfill_edge_add(&sf_ctx, UNPACK2(sf_verts));
/* sf_edge->tmp.p = e; */ /* UNUSED */
}
+ BLI_ghash_free(sf_vert_map, NULL, NULL);
+
if (is_zero_v3(normal)) {
- normal_pt = NULL;
+ /* calculate the normal from the cross product of vert-edge pairs.
+ * Since we don't know winding, just accumulate */
+ ScanFillVert *sf_vert;
+ struct SortNormal *nors;
+ const unsigned int nors_tot = BLI_ghash_size(sf_vert_map);
+ unsigned int i;
+ bool is_degenerate = true;
+
+ nors = MEM_mallocN(sizeof(*nors) * nors_tot, __func__);
+
+ for (sf_vert = sf_ctx.fillvertbase.first, i = 0; sf_vert; sf_vert = sf_vert->next, i++) {
+ BMVert *v = sf_vert->tmp.p;
+ BMIter eiter;
+ BMEdge *e, *e_pair[2];
+ unsigned int e_index = 0;
+
+ nors[i].value = -1.0f;
+
+ /* only use if 'is_degenerate' stays true */
+ add_v3_v3(normal, v->no);
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
+ if (e_index == 2) {
+ e_index = 0;
+ break;
+ }
+ e_pair[e_index++] = e;
+ }
+ }
+
+ if (e_index == 2) {
+ float dir_a[3], dir_b[3];
+
+ is_degenerate = false;
+
+ sub_v3_v3v3(dir_a, v->co, BM_edge_other_vert(e_pair[0], v)->co);
+ sub_v3_v3v3(dir_b, v->co, BM_edge_other_vert(e_pair[1], v)->co);
+
+ cross_v3_v3v3(nors[i].no, dir_a, dir_b);
+ nors[i].value = len_squared_v3(nors[i].no);
+
+ /* only to get deterministic behavior (for initial normal) */
+ if (len_squared_v3(dir_a) > len_squared_v3(dir_b)) {
+ negate_v3(nors[i].no);
+ }
+ }
+ }
+
+ if (UNLIKELY(is_degenerate)) {
+ /* no vertices have 2 edges?
+ * in this case fall back to the average vertex normals */
+ }
+ else {
+ qsort(nors, nors_tot, sizeof(*nors), BLI_sortutil_cmp_float_reverse);
+
+ copy_v3_v3(normal, nors[0].no);
+ for (i = 0; i < nors_tot; i++) {
+ if (UNLIKELY(nors[i].value == -1.0f)) {
+ break;
+ }
+ if (dot_v3v3(normal, nors[i].no) < 0.0f) {
+ negate_v3(nors[i].no);
+ }
+ add_v3_v3(normal, nors[i].no);
+ }
+ normalize_v3(normal);
+ }
+
+ MEM_freeN(nors);
}
else {
- normalize_v3(normal);
- normal_pt = normal;
+ calc_winding = false;
}
- BLI_scanfill_calc_ex(&sf_ctx, scanfill_flag, normal_pt);
-
+ normalize_v3(normal);
+
+ BLI_scanfill_calc_ex(&sf_ctx, scanfill_flag, normal);
+
+
+ /* if we have existing faces, base winding on those */
+ if (calc_winding) {
+ int winding_votes = 0;
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ BMVert *v_tri[3] = {sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p};
+ unsigned int i, i_prev;
+
+ for (i = 0, i_prev = 2; i < 3; i_prev = i++) {
+ e = BM_edge_exists(v_tri[i], v_tri[i_prev]);
+ if (e && BM_edge_is_boundary(e) && BMO_elem_flag_test(bm, e, EDGE_MARK)) {
+ winding_votes += (e->l->v == v_tri[i]) ? 1 : -1;
+ }
+ }
+ }
+
+ if (winding_votes < 0) {
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ SWAP(struct ScanFillVert *, sf_tri->v2, sf_tri->v3);
+ }
+ }
+ }
+
+
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
- BMFace *f = BM_face_create_quad_tri(bm,
- sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p, NULL,
- NULL, true);
+ BMFace *f;
BMLoop *l;
BMIter liter;
+
+ f = BM_face_create_quad_tri(bm,
+ sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p, NULL,
+ NULL, BM_CREATE_NO_DOUBLE);
BMO_elem_flag_enable(bm, f, ELE_NEW);
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
@@ -123,7 +228,6 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
}
BLI_scanfill_end(&sf_ctx);
- BLI_smallhash_release(&hash);
if (use_beauty) {
BMOperator bmop;
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index 600386893dd..d2d1c0854de 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -63,7 +63,7 @@ void bmo_transform_exec(BMesh *UNUSED(bm), BMOperator *op)
if (!is_zero_m4(mat_space)) {
invert_m4_m4(imat_space, mat_space);
- mul_serie_m4(mat, imat_space, mat, mat_space, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, imat_space, mat, mat_space);
}
BMO_ITER (v, &iter, op->slots_in, "verts", BM_VERT) {