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>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/editors/mesh/editmesh_intersect.c
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/editors/mesh/editmesh_intersect.c')
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c1538
1 files changed, 776 insertions, 762 deletions
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index c500683a228..06e2ef6e304 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -44,12 +44,11 @@
#include "intern/bmesh_private.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
#include "tools/bmesh_intersect.h"
#include "tools/bmesh_separate.h"
-
/* detect isolated holes and fill them */
#define USE_NET_ISLAND_CONNECT
@@ -58,12 +57,12 @@
*/
static int bm_face_isect_self(BMFace *f, void *UNUSED(user_data))
{
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- return 0;
- }
- else {
- return -1;
- }
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
}
/**
@@ -71,15 +70,15 @@ static int bm_face_isect_self(BMFace *f, void *UNUSED(user_data))
*/
static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
{
- if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- return -1;
- }
- else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- return 1;
- }
- else {
- return 0;
- }
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ return -1;
+ }
+ else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
/**
@@ -88,15 +87,15 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
*/
static int bm_face_isect_pair_swap(BMFace *f, void *UNUSED(user_data))
{
- if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- return -1;
- }
- else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- return 0;
- }
- else {
- return 1;
- }
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ return -1;
+ }
+ else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
}
/**
@@ -104,22 +103,21 @@ static int bm_face_isect_pair_swap(BMFace *f, void *UNUSED(user_data))
*/
static void edbm_intersect_select(BMEditMesh *em)
{
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
-
- if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
- BMIter iter;
- BMEdge *e;
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BM_edge_select_set(em->bm, e, true);
- }
- }
- }
+ if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
+ BMIter iter;
+ BMEdge *e;
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BM_edge_select_set(em->bm, e, true);
+ }
+ }
+ }
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
}
/* -------------------------------------------------------------------- */
@@ -130,138 +128,148 @@ static void edbm_intersect_select(BMEditMesh *em)
*/
enum {
- ISECT_SEL = 0,
- ISECT_SEL_UNSEL = 1,
+ ISECT_SEL = 0,
+ ISECT_SEL_UNSEL = 1,
};
enum {
- ISECT_SEPARATE_ALL = 0,
- ISECT_SEPARATE_CUT = 1,
- ISECT_SEPARATE_NONE = 2,
+ ISECT_SEPARATE_ALL = 0,
+ ISECT_SEPARATE_CUT = 1,
+ ISECT_SEPARATE_NONE = 2,
};
static int edbm_intersect_exec(bContext *C, wmOperator *op)
{
- const int mode = RNA_enum_get(op->ptr, "mode");
- int (*test_fn)(BMFace *, void *);
- bool use_separate_all = false;
- bool use_separate_cut = false;
- const int separate_mode = RNA_enum_get(op->ptr, "separate_mode");
- const float eps = RNA_float_get(op->ptr, "threshold");
- bool use_self;
- bool has_isect;
-
- switch (mode) {
- case ISECT_SEL:
- test_fn = bm_face_isect_self;
- use_self = true;
- break;
- default: /* ISECT_SEL_UNSEL */
- test_fn = bm_face_isect_pair;
- use_self = false;
- break;
- }
-
- switch (separate_mode) {
- case ISECT_SEPARATE_ALL:
- use_separate_all = true;
- break;
- case ISECT_SEPARATE_CUT:
- if (use_self == false) {
- use_separate_cut = true;
- }
- else {
- /* we could support this but would require more advanced logic inside 'BM_mesh_intersect'
- * for now just separate all */
- use_separate_all = true;
- }
- break;
- default: /* ISECT_SEPARATE_NONE */
- break;
- }
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- uint isect_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totfacesel == 0) {
- continue;
- }
-
- has_isect = BM_mesh_intersect(
- em->bm,
- em->looptris, em->tottri,
- test_fn, NULL,
- use_self, use_separate_all, true, true, true, true,
- -1,
- eps);
-
- if (use_separate_cut) {
- /* detach selected/un-selected faces */
- BM_mesh_separate_faces(
- em->bm,
- BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
- }
-
- if (has_isect) {
- edbm_intersect_select(em);
- }
- else {
- isect_len++;
- }
- }
- MEM_freeN(objects);
-
- if (isect_len == objects_len) {
- BKE_report(op->reports, RPT_WARNING, "No intersections found");
- }
- return OPERATOR_FINISHED;
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ int (*test_fn)(BMFace *, void *);
+ bool use_separate_all = false;
+ bool use_separate_cut = false;
+ const int separate_mode = RNA_enum_get(op->ptr, "separate_mode");
+ const float eps = RNA_float_get(op->ptr, "threshold");
+ bool use_self;
+ bool has_isect;
+
+ switch (mode) {
+ case ISECT_SEL:
+ test_fn = bm_face_isect_self;
+ use_self = true;
+ break;
+ default: /* ISECT_SEL_UNSEL */
+ test_fn = bm_face_isect_pair;
+ use_self = false;
+ break;
+ }
+
+ switch (separate_mode) {
+ case ISECT_SEPARATE_ALL:
+ use_separate_all = true;
+ break;
+ case ISECT_SEPARATE_CUT:
+ if (use_self == false) {
+ use_separate_cut = true;
+ }
+ else {
+ /* we could support this but would require more advanced logic inside 'BM_mesh_intersect'
+ * for now just separate all */
+ use_separate_all = true;
+ }
+ break;
+ default: /* ISECT_SEPARATE_NONE */
+ break;
+ }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ uint isect_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+
+ has_isect = BM_mesh_intersect(em->bm,
+ em->looptris,
+ em->tottri,
+ test_fn,
+ NULL,
+ use_self,
+ use_separate_all,
+ true,
+ true,
+ true,
+ true,
+ -1,
+ eps);
+
+ if (use_separate_cut) {
+ /* detach selected/un-selected faces */
+ BM_mesh_separate_faces(
+ em->bm, BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
+ }
+
+ if (has_isect) {
+ edbm_intersect_select(em);
+ }
+ else {
+ isect_len++;
+ }
+ }
+ MEM_freeN(objects);
+
+ if (isect_len == objects_len) {
+ BKE_report(op->reports, RPT_WARNING, "No intersections found");
+ }
+ return OPERATOR_FINISHED;
}
void MESH_OT_intersect(struct wmOperatorType *ot)
{
- static const EnumPropertyItem isect_mode_items[] = {
- {ISECT_SEL, "SELECT", 0, "Self Intersect",
- "Self intersect selected faces"},
- {ISECT_SEL_UNSEL, "SELECT_UNSELECT", 0, "Selected/Unselected",
- "Intersect selected with unselected faces"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem isect_separate_items[] = {
- {ISECT_SEPARATE_ALL, "ALL", 0, "All",
- "Separate all geometry from intersections"},
- {ISECT_SEPARATE_CUT, "CUT", 0, "Cut",
- "Cut into geometry keeping each side separate (Selected/Unselected only)"},
- {ISECT_SEPARATE_NONE, "NONE", 0, "Merge",
- "Merge all geometry from the intersection"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Intersect (Knife)";
- ot->description = "Cut an intersection into faces";
- ot->idname = "MESH_OT_intersect";
-
- /* api callbacks */
- ot->exec = edbm_intersect_exec;
- ot->poll = ED_operator_editmesh;
-
- /* props */
- RNA_def_enum(ot->srna, "mode", isect_mode_items, ISECT_SEL_UNSEL, "Source", "");
- RNA_def_enum(ot->srna, "separate_mode", isect_separate_items, ISECT_SEPARATE_CUT, "Separate Mode", "");
- RNA_def_float_distance(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ static const EnumPropertyItem isect_mode_items[] = {
+ {ISECT_SEL, "SELECT", 0, "Self Intersect", "Self intersect selected faces"},
+ {ISECT_SEL_UNSEL,
+ "SELECT_UNSELECT",
+ 0,
+ "Selected/Unselected",
+ "Intersect selected with unselected faces"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem isect_separate_items[] = {
+ {ISECT_SEPARATE_ALL, "ALL", 0, "All", "Separate all geometry from intersections"},
+ {ISECT_SEPARATE_CUT,
+ "CUT",
+ 0,
+ "Cut",
+ "Cut into geometry keeping each side separate (Selected/Unselected only)"},
+ {ISECT_SEPARATE_NONE, "NONE", 0, "Merge", "Merge all geometry from the intersection"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Intersect (Knife)";
+ ot->description = "Cut an intersection into faces";
+ ot->idname = "MESH_OT_intersect";
+
+ /* api callbacks */
+ ot->exec = edbm_intersect_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* props */
+ RNA_def_enum(ot->srna, "mode", isect_mode_items, ISECT_SEL_UNSEL, "Source", "");
+ RNA_def_enum(
+ ot->srna, "separate_mode", isect_separate_items, ISECT_SEPARATE_CUT, "Separate Mode", "");
+ RNA_def_float_distance(
+ ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Boolean (a kind of intersect) */
@@ -275,74 +283,90 @@ void MESH_OT_intersect(struct wmOperatorType *ot)
static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
{
- const int boolean_operation = RNA_enum_get(op->ptr, "operation");
- bool use_swap = RNA_boolean_get(op->ptr, "use_swap");
- const float eps = RNA_float_get(op->ptr, "threshold");
- int (*test_fn)(BMFace *, void *);
- bool has_isect;
-
- test_fn = use_swap ? bm_face_isect_pair_swap : bm_face_isect_pair;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- uint isect_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totfacesel == 0) {
- continue;
- }
-
- has_isect = BM_mesh_intersect(
- em->bm,
- em->looptris, em->tottri,
- test_fn, NULL,
- false, false, true, true, false, true,
- boolean_operation,
- eps);
-
-
- if (has_isect) {
- edbm_intersect_select(em);
- }
- else {
- isect_len++;
- }
- }
- MEM_freeN(objects);
-
- if (isect_len == objects_len) {
- BKE_report(op->reports, RPT_WARNING, "No intersections found");
- }
- return OPERATOR_FINISHED;
+ const int boolean_operation = RNA_enum_get(op->ptr, "operation");
+ bool use_swap = RNA_boolean_get(op->ptr, "use_swap");
+ const float eps = RNA_float_get(op->ptr, "threshold");
+ int (*test_fn)(BMFace *, void *);
+ bool has_isect;
+
+ test_fn = use_swap ? bm_face_isect_pair_swap : bm_face_isect_pair;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ uint isect_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+
+ has_isect = BM_mesh_intersect(em->bm,
+ em->looptris,
+ em->tottri,
+ test_fn,
+ NULL,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ boolean_operation,
+ eps);
+
+ if (has_isect) {
+ edbm_intersect_select(em);
+ }
+ else {
+ isect_len++;
+ }
+ }
+ MEM_freeN(objects);
+
+ if (isect_len == objects_len) {
+ BKE_report(op->reports, RPT_WARNING, "No intersections found");
+ }
+ return OPERATOR_FINISHED;
}
void MESH_OT_intersect_boolean(struct wmOperatorType *ot)
{
- static const EnumPropertyItem isect_boolean_operation_items[] = {
- {BMESH_ISECT_BOOLEAN_ISECT, "INTERSECT", 0, "Intersect", ""},
- {BMESH_ISECT_BOOLEAN_UNION, "UNION", 0, "Union", ""},
- {BMESH_ISECT_BOOLEAN_DIFFERENCE, "DIFFERENCE", 0, "Difference", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Intersect (Boolean)";
- ot->description = "Cut solid geometry from selected to unselected";
- ot->idname = "MESH_OT_intersect_boolean";
-
- /* api callbacks */
- ot->exec = edbm_intersect_boolean_exec;
- ot->poll = ED_operator_editmesh;
-
- /* props */
- RNA_def_enum(ot->srna, "operation", isect_boolean_operation_items, BMESH_ISECT_BOOLEAN_DIFFERENCE, "Boolean", "");
- RNA_def_boolean(ot->srna, "use_swap", false, "Swap", "Use with difference intersection to swap which side is kept");
- RNA_def_float_distance(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ static const EnumPropertyItem isect_boolean_operation_items[] = {
+ {BMESH_ISECT_BOOLEAN_ISECT, "INTERSECT", 0, "Intersect", ""},
+ {BMESH_ISECT_BOOLEAN_UNION, "UNION", 0, "Union", ""},
+ {BMESH_ISECT_BOOLEAN_DIFFERENCE, "DIFFERENCE", 0, "Difference", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Intersect (Boolean)";
+ ot->description = "Cut solid geometry from selected to unselected";
+ ot->idname = "MESH_OT_intersect_boolean";
+
+ /* api callbacks */
+ ot->exec = edbm_intersect_boolean_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* props */
+ RNA_def_enum(ot->srna,
+ "operation",
+ isect_boolean_operation_items,
+ BMESH_ISECT_BOOLEAN_DIFFERENCE,
+ "Boolean",
+ "");
+ RNA_def_boolean(ot->srna,
+ "use_swap",
+ false,
+ "Swap",
+ "Use with difference intersection to swap which side is kept");
+ RNA_def_float_distance(
+ ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -353,88 +377,82 @@ void MESH_OT_intersect_boolean(struct wmOperatorType *ot)
/** \name Face/Edge Split
* \{ */
-static void bm_face_split_by_edges(
- BMesh *bm, BMFace *f, const char hflag,
- /* reusable memory buffer */
- BLI_Buffer *edge_net_temp_buf)
+static void bm_face_split_by_edges(BMesh *bm,
+ BMFace *f,
+ const char hflag,
+ /* reusable memory buffer */
+ BLI_Buffer *edge_net_temp_buf)
{
- const int f_index = BM_elem_index_get(f);
-
- BMLoop *l_iter;
- BMLoop *l_first;
- BMVert *v;
-
- BMFace **face_arr;
- int face_arr_len;
-
- /* likely this will stay very small
- * all verts pushed into this stack _must_ have their previous edges set! */
- BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
- BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
-
- BLI_assert(edge_net_temp_buf->count == 0);
-
- /* collect all edges */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BMIter iter;
- BMEdge *e;
-
- BM_ITER_ELEM (e, &iter, l_iter->v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e, hflag) &&
- (BM_elem_index_get(e) == f_index))
- {
- v = BM_edge_other_vert(e, l_iter->v);
- v->e = e;
-
- BLI_SMALLSTACK_PUSH(vert_stack, v);
- BLI_buffer_append(edge_net_temp_buf, BMEdge *, e);
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
-
-
-
- /* now assign all */
- /* pop free values into the next stack */
- while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
- BMIter eiter;
- BMEdge *e_next;
-
- BM_ITER_ELEM (e_next, &eiter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_next, hflag) &&
- (BM_elem_index_get(e_next) == -1))
- {
- BMVert *v_next;
- v_next = BM_edge_other_vert(e_next, v);
- BM_elem_index_set(e_next, f_index);
- BLI_SMALLSTACK_PUSH(vert_stack_next, v_next);
- BLI_buffer_append(edge_net_temp_buf, BMEdge *, e_next);
- }
- }
-
- if (BLI_SMALLSTACK_IS_EMPTY(vert_stack)) {
- BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
- }
- }
-
- BM_face_split_edgenet(
- bm, f, edge_net_temp_buf->data, edge_net_temp_buf->count,
- &face_arr, &face_arr_len);
-
- BLI_buffer_clear(edge_net_temp_buf);
-
- if (face_arr_len) {
- int i;
- for (i = 0; i < face_arr_len; i++) {
- BM_face_select_set(bm, face_arr[i], true);
- BM_elem_flag_disable(face_arr[i], hflag);
- }
- }
-
- if (face_arr) {
- MEM_freeN(face_arr);
- }
+ const int f_index = BM_elem_index_get(f);
+
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMVert *v;
+
+ BMFace **face_arr;
+ int face_arr_len;
+
+ /* likely this will stay very small
+ * all verts pushed into this stack _must_ have their previous edges set! */
+ BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
+ BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
+
+ BLI_assert(edge_net_temp_buf->count == 0);
+
+ /* collect all edges */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMIter iter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &iter, l_iter->v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, hflag) && (BM_elem_index_get(e) == f_index)) {
+ v = BM_edge_other_vert(e, l_iter->v);
+ v->e = e;
+
+ BLI_SMALLSTACK_PUSH(vert_stack, v);
+ BLI_buffer_append(edge_net_temp_buf, BMEdge *, e);
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* now assign all */
+ /* pop free values into the next stack */
+ while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
+ BMIter eiter;
+ BMEdge *e_next;
+
+ BM_ITER_ELEM (e_next, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_next, hflag) && (BM_elem_index_get(e_next) == -1)) {
+ BMVert *v_next;
+ v_next = BM_edge_other_vert(e_next, v);
+ BM_elem_index_set(e_next, f_index);
+ BLI_SMALLSTACK_PUSH(vert_stack_next, v_next);
+ BLI_buffer_append(edge_net_temp_buf, BMEdge *, e_next);
+ }
+ }
+
+ if (BLI_SMALLSTACK_IS_EMPTY(vert_stack)) {
+ BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
+ }
+ }
+
+ BM_face_split_edgenet(
+ bm, f, edge_net_temp_buf->data, edge_net_temp_buf->count, &face_arr, &face_arr_len);
+
+ BLI_buffer_clear(edge_net_temp_buf);
+
+ if (face_arr_len) {
+ int i;
+ for (i = 0; i < face_arr_len; i++) {
+ BM_face_select_set(bm, face_arr[i], true);
+ BM_elem_flag_disable(face_arr[i], hflag);
+ }
+ }
+
+ if (face_arr) {
+ MEM_freeN(face_arr);
+ }
}
/**
@@ -443,113 +461,114 @@ static void bm_face_split_by_edges(
*/
static bool bm_vert_in_faces_radial(BMVert *v, BMEdge *e_radial, BMFace *f_ignore)
{
- BLI_assert(BM_vert_in_face(v, f_ignore) == false);
- if (e_radial->l) {
- BMLoop *l_iter = e_radial->l;
- do {
- if (l_iter->f != f_ignore) {
- if (BM_vert_in_face(v, l_iter->f)) {
- return true;
- }
- }
- } while ((l_iter = l_iter->radial_next) != e_radial->l);
- }
- return false;
+ BLI_assert(BM_vert_in_face(v, f_ignore) == false);
+ if (e_radial->l) {
+ BMLoop *l_iter = e_radial->l;
+ do {
+ if (l_iter->f != f_ignore) {
+ if (BM_vert_in_face(v, l_iter->f)) {
+ return true;
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != e_radial->l);
+ }
+ return false;
}
#ifdef USE_NET_ISLAND_CONNECT
struct LinkBase {
- LinkNode *list;
- unsigned int list_len;
+ LinkNode *list;
+ unsigned int list_len;
};
-static void ghash_insert_face_edge_link(
- GHash *gh, BMFace *f_key, BMEdge *e_val,
- MemArena *mem_arena)
+static void ghash_insert_face_edge_link(GHash *gh,
+ BMFace *f_key,
+ BMEdge *e_val,
+ MemArena *mem_arena)
{
- void **ls_base_p;
- struct LinkBase *ls_base;
- LinkNode *ls;
-
- if (!BLI_ghash_ensure_p(gh, f_key, &ls_base_p)) {
- ls_base = *ls_base_p = BLI_memarena_alloc(mem_arena, sizeof(*ls_base));
- ls_base->list = NULL;
- ls_base->list_len = 0;
- }
- else {
- ls_base = *ls_base_p;
- }
-
- ls = BLI_memarena_alloc(mem_arena, sizeof(*ls));
- ls->next = ls_base->list;
- ls->link = e_val;
- ls_base->list = ls;
- ls_base->list_len += 1;
+ void **ls_base_p;
+ struct LinkBase *ls_base;
+ LinkNode *ls;
+
+ if (!BLI_ghash_ensure_p(gh, f_key, &ls_base_p)) {
+ ls_base = *ls_base_p = BLI_memarena_alloc(mem_arena, sizeof(*ls_base));
+ ls_base->list = NULL;
+ ls_base->list_len = 0;
+ }
+ else {
+ ls_base = *ls_base_p;
+ }
+
+ ls = BLI_memarena_alloc(mem_arena, sizeof(*ls));
+ ls->next = ls_base->list;
+ ls->link = e_val;
+ ls_base->list = ls;
+ ls_base->list_len += 1;
}
static int bm_edge_sort_length_cb(const void *e_a_v, const void *e_b_v)
{
- const float val_a = -BM_edge_calc_length_squared(*((BMEdge **)e_a_v));
- const float val_b = -BM_edge_calc_length_squared(*((BMEdge **)e_b_v));
-
- if (val_a > val_b) return 1;
- else if (val_a < val_b) return -1;
- else return 0;
+ const float val_a = -BM_edge_calc_length_squared(*((BMEdge **)e_a_v));
+ const float val_b = -BM_edge_calc_length_squared(*((BMEdge **)e_b_v));
+
+ if (val_a > val_b)
+ return 1;
+ else if (val_a < val_b)
+ return -1;
+ else
+ return 0;
}
static void bm_face_split_by_edges_island_connect(
- BMesh *bm, BMFace *f,
- LinkNode *e_link, const int e_link_len,
- MemArena *mem_arena_edgenet)
+ BMesh *bm, BMFace *f, LinkNode *e_link, const int e_link_len, MemArena *mem_arena_edgenet)
{
- BMEdge **edge_arr = BLI_memarena_alloc(mem_arena_edgenet, sizeof(*edge_arr) * e_link_len);
- int edge_arr_len = 0;
-
- while (e_link) {
- edge_arr[edge_arr_len++] = e_link->link;
- e_link = e_link->next;
- }
-
- {
- unsigned int edge_arr_holes_len;
- BMEdge **edge_arr_holes;
- if (BM_face_split_edgenet_connect_islands(
- bm, f,
- edge_arr, e_link_len,
- true,
- mem_arena_edgenet,
- &edge_arr_holes, &edge_arr_holes_len))
- {
- edge_arr_len = edge_arr_holes_len;
- edge_arr = edge_arr_holes; /* owned by the arena */
- }
- }
-
- BM_face_split_edgenet(
- bm, f, edge_arr, edge_arr_len,
- NULL, NULL);
-
- for (int i = e_link_len; i < edge_arr_len; i++) {
- BM_edge_select_set(bm, edge_arr[i], true);
- }
-
- if (e_link_len != edge_arr_len) {
- /* connecting partial islands can add redundant edges
- * sort before removal to give deterministic outcome */
- qsort(edge_arr, edge_arr_len - e_link_len, sizeof(*edge_arr), bm_edge_sort_length_cb);
- for (int i = e_link_len; i < edge_arr_len; i++) {
- BMFace *f_pair[2];
- if (BM_edge_face_pair(edge_arr[i], &f_pair[0], &f_pair[1])) {
- if (BM_face_share_vert_count(f_pair[0], f_pair[1]) == 2) {
- BMFace *f_new = BM_faces_join(bm, f_pair, 2, true);
- if (f_new) {
- BM_face_select_set(bm, f_new, true);
- }
- }
- }
- }
- }
+ BMEdge **edge_arr = BLI_memarena_alloc(mem_arena_edgenet, sizeof(*edge_arr) * e_link_len);
+ int edge_arr_len = 0;
+
+ while (e_link) {
+ edge_arr[edge_arr_len++] = e_link->link;
+ e_link = e_link->next;
+ }
+
+ {
+ unsigned int edge_arr_holes_len;
+ BMEdge **edge_arr_holes;
+ if (BM_face_split_edgenet_connect_islands(bm,
+ f,
+ edge_arr,
+ e_link_len,
+ true,
+ mem_arena_edgenet,
+ &edge_arr_holes,
+ &edge_arr_holes_len)) {
+ edge_arr_len = edge_arr_holes_len;
+ edge_arr = edge_arr_holes; /* owned by the arena */
+ }
+ }
+
+ BM_face_split_edgenet(bm, f, edge_arr, edge_arr_len, NULL, NULL);
+
+ for (int i = e_link_len; i < edge_arr_len; i++) {
+ BM_edge_select_set(bm, edge_arr[i], true);
+ }
+
+ if (e_link_len != edge_arr_len) {
+ /* connecting partial islands can add redundant edges
+ * sort before removal to give deterministic outcome */
+ qsort(edge_arr, edge_arr_len - e_link_len, sizeof(*edge_arr), bm_edge_sort_length_cb);
+ for (int i = e_link_len; i < edge_arr_len; i++) {
+ BMFace *f_pair[2];
+ if (BM_edge_face_pair(edge_arr[i], &f_pair[0], &f_pair[1])) {
+ if (BM_face_share_vert_count(f_pair[0], f_pair[1]) == 2) {
+ BMFace *f_new = BM_faces_join(bm, f_pair, 2, true);
+ if (f_new) {
+ BM_face_select_set(bm, f_new, true);
+ }
+ }
+ }
+ }
+ }
}
/**
@@ -570,394 +589,389 @@ static void bm_face_split_by_edges_island_connect(
*
* \note Currently we don't snap to verts or split chains by verts on-edges.
*/
-static BMEdge *bm_face_split_edge_find(
- BMEdge *e_a, BMFace *f_a, BMVert *v_pivot, BMFace **ftable, const int ftable_len,
- float r_v_pivot_co[3], float *r_v_pivot_fac)
+static BMEdge *bm_face_split_edge_find(BMEdge *e_a,
+ BMFace *f_a,
+ BMVert *v_pivot,
+ BMFace **ftable,
+ const int ftable_len,
+ float r_v_pivot_co[3],
+ float *r_v_pivot_fac)
{
- const int f_a_index = BM_elem_index_get(e_a);
- bool found_other_self = false;
- int found_other_face = 0;
- BLI_SMALLSTACK_DECLARE(face_stack, BMFace *);
-
- /* loop over surrounding edges to check if we're part of a chain or a delimiter vertex */
- BMEdge *e_b = v_pivot->e;
- do {
- if (e_b != e_a) {
- const int f_b_index = BM_elem_index_get(e_b);
- if (f_b_index == f_a_index) {
- /* not an endpoint */
- found_other_self = true;
- }
- else if (f_b_index != -1) {
- BLI_assert(f_b_index < ftable_len);
- UNUSED_VARS_NDEBUG(ftable_len);
-
- /* 'v_pivot' spans 2+ faces,
- * tag to ensure we pick an edge that includes this face */
- BMFace *f_b = ftable[f_b_index];
- if (!BM_elem_flag_test(f_b, BM_ELEM_INTERNAL_TAG)) {
- BM_elem_flag_enable(f_b, BM_ELEM_INTERNAL_TAG);
- BLI_SMALLSTACK_PUSH(face_stack, f_b);
- found_other_face++;
- }
- }
- }
- } while ((e_b = BM_DISK_EDGE_NEXT(e_b, v_pivot)) != v_pivot->e);
-
- BMEdge *e_split = NULL;
-
- /* if we have no others or the other edge is outside this face,
- * we're an endpoint to connect to a boundary */
- if ((found_other_self == false) || found_other_face) {
-
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
- float dist_best_sq = FLT_MAX;
-
- do {
- float v_pivot_co_test[3];
- float v_pivot_fac = line_point_factor_v3(v_pivot->co, l_iter->e->v1->co, l_iter->e->v2->co);
- CLAMP(v_pivot_fac, 0.0f, 1.0f);
- interp_v3_v3v3(v_pivot_co_test, l_iter->e->v1->co, l_iter->e->v2->co, v_pivot_fac);
-
- float dist_test_sq = len_squared_v3v3(v_pivot_co_test, v_pivot->co);
- if ((dist_test_sq < dist_best_sq) || (e_split == NULL)) {
- bool ok = true;
-
- if (UNLIKELY(BM_edge_exists(v_pivot, l_iter->e->v1) ||
- BM_edge_exists(v_pivot, l_iter->e->v2)))
- {
- /* very unlikely but will cause complications splicing the verts together,
- * so just skip this case */
- ok = false;
- }
- else if (found_other_face) {
- /* double check that _all_ the faces used by v_pivot's edges are attached
- * to this edge otherwise don't attempt the split since it will give
- * non-deterministic results */
- BMLoop *l_radial_iter = l_iter->radial_next;
- int other_face_shared = 0;
- if (l_radial_iter != l_iter) {
- do {
- if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_INTERNAL_TAG)) {
- other_face_shared++;
- }
- } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
- }
- if (other_face_shared != found_other_face) {
- ok = false;
- }
- }
-
- if (ok) {
- e_split = l_iter->e;
- dist_best_sq = dist_test_sq;
- copy_v3_v3(r_v_pivot_co, v_pivot_co_test);
- *r_v_pivot_fac = v_pivot_fac;
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- {
- /* reset the flag, for future use */
- BMFace *f;
- while ((f = BLI_SMALLSTACK_POP(face_stack))) {
- BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
- }
- }
-
- return e_split;
+ const int f_a_index = BM_elem_index_get(e_a);
+ bool found_other_self = false;
+ int found_other_face = 0;
+ BLI_SMALLSTACK_DECLARE(face_stack, BMFace *);
+
+ /* loop over surrounding edges to check if we're part of a chain or a delimiter vertex */
+ BMEdge *e_b = v_pivot->e;
+ do {
+ if (e_b != e_a) {
+ const int f_b_index = BM_elem_index_get(e_b);
+ if (f_b_index == f_a_index) {
+ /* not an endpoint */
+ found_other_self = true;
+ }
+ else if (f_b_index != -1) {
+ BLI_assert(f_b_index < ftable_len);
+ UNUSED_VARS_NDEBUG(ftable_len);
+
+ /* 'v_pivot' spans 2+ faces,
+ * tag to ensure we pick an edge that includes this face */
+ BMFace *f_b = ftable[f_b_index];
+ if (!BM_elem_flag_test(f_b, BM_ELEM_INTERNAL_TAG)) {
+ BM_elem_flag_enable(f_b, BM_ELEM_INTERNAL_TAG);
+ BLI_SMALLSTACK_PUSH(face_stack, f_b);
+ found_other_face++;
+ }
+ }
+ }
+ } while ((e_b = BM_DISK_EDGE_NEXT(e_b, v_pivot)) != v_pivot->e);
+
+ BMEdge *e_split = NULL;
+
+ /* if we have no others or the other edge is outside this face,
+ * we're an endpoint to connect to a boundary */
+ if ((found_other_self == false) || found_other_face) {
+
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
+ float dist_best_sq = FLT_MAX;
+
+ do {
+ float v_pivot_co_test[3];
+ float v_pivot_fac = line_point_factor_v3(v_pivot->co, l_iter->e->v1->co, l_iter->e->v2->co);
+ CLAMP(v_pivot_fac, 0.0f, 1.0f);
+ interp_v3_v3v3(v_pivot_co_test, l_iter->e->v1->co, l_iter->e->v2->co, v_pivot_fac);
+
+ float dist_test_sq = len_squared_v3v3(v_pivot_co_test, v_pivot->co);
+ if ((dist_test_sq < dist_best_sq) || (e_split == NULL)) {
+ bool ok = true;
+
+ if (UNLIKELY(BM_edge_exists(v_pivot, l_iter->e->v1) ||
+ BM_edge_exists(v_pivot, l_iter->e->v2))) {
+ /* very unlikely but will cause complications splicing the verts together,
+ * so just skip this case */
+ ok = false;
+ }
+ else if (found_other_face) {
+ /* double check that _all_ the faces used by v_pivot's edges are attached
+ * to this edge otherwise don't attempt the split since it will give
+ * non-deterministic results */
+ BMLoop *l_radial_iter = l_iter->radial_next;
+ int other_face_shared = 0;
+ if (l_radial_iter != l_iter) {
+ do {
+ if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_INTERNAL_TAG)) {
+ other_face_shared++;
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
+ }
+ if (other_face_shared != found_other_face) {
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ e_split = l_iter->e;
+ dist_best_sq = dist_test_sq;
+ copy_v3_v3(r_v_pivot_co, v_pivot_co_test);
+ *r_v_pivot_fac = v_pivot_fac;
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ {
+ /* reset the flag, for future use */
+ BMFace *f;
+ while ((f = BLI_SMALLSTACK_POP(face_stack))) {
+ BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
+ }
+ }
+
+ return e_split;
}
-#endif /* USE_NET_ISLAND_CONNECT */
-
+#endif /* USE_NET_ISLAND_CONNECT */
static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
{
- const char hflag = BM_ELEM_TAG;
-
- BMEdge *e;
- BMIter iter;
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if ((bm->totedgesel == 0) ||
- (bm->totfacesel == 0))
- {
- continue;
- }
-
- BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
-
- {
- BMVert *v;
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(v, hflag);
- }
- }
-
- /* edge index is set to -1 then used to associate them with faces */
- BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
- BM_elem_flag_enable(e, hflag);
-
- BM_elem_flag_enable(e->v1, hflag);
- BM_elem_flag_enable(e->v2, hflag);
-
- }
- else {
- BM_elem_flag_disable(e, hflag);
- }
- BM_elem_index_set(e, -1); /* set_dirty */
- }
- bm->elem_index_dirty |= BM_EDGE;
-
- {
- BMFace *f;
- int i;
- BM_ITER_MESH_INDEX(f, &iter, bm, BM_FACES_OF_MESH, i) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(f, hflag);
- }
- else {
- BM_elem_flag_disable(f, hflag);
- }
- BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
- BM_elem_index_set(f, i); /* set_ok */
- }
- }
- bm->elem_index_dirty &= ~BM_FACE;
-
- BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, hflag)) {
- BMIter viter;
- BMVert *v;
- BM_ITER_ELEM(v, &viter, e, BM_VERTS_OF_EDGE) {
- BMIter liter;
- BMLoop *l;
-
- unsigned int loop_stack_len;
- BMLoop *l_best = NULL;
-
- BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
- loop_stack_len = 0;
-
- BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
- if (BM_elem_flag_test(l->f, hflag)) {
- BLI_SMALLSTACK_PUSH(loop_stack, l);
- loop_stack_len++;
- }
- }
-
- if (loop_stack_len == 0) {
- /* pass */
- }
- else if (loop_stack_len == 1) {
- l_best = BLI_SMALLSTACK_POP(loop_stack);
- }
- else {
- /* complicated case, match the edge with a face-loop */
-
- BMVert *v_other = BM_edge_other_vert(e, v);
- float e_dir[3];
-
- /* we want closest to zero */
- float dot_best = FLT_MAX;
-
- sub_v3_v3v3(e_dir, v_other->co, v->co);
- normalize_v3(e_dir);
-
- while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
- float dot_test;
-
- /* Check dot first to save on expensive angle-comparison.
- * ideal case is 90d difference == 0.0 dot */
- dot_test = fabsf(dot_v3v3(e_dir, l->f->no));
- if (dot_test < dot_best) {
-
- /* check we're in the correct corner
- * (works with convex loops too) */
- if (angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, v_other->co, l->f->no) <
- angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, l->next->v->co, l->f->no))
- {
- dot_best = dot_test;
- l_best = l;
- }
- }
- }
- }
-
- if (l_best) {
- BM_elem_index_set(e, BM_elem_index_get(l_best->f)); /* set_dirty */
- }
- }
- }
- }
-
- {
- BMFace *f;
- BLI_buffer_declare_static(BMEdge **, edge_net_temp_buf, 0, 128);
-
- BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, hflag)) {
- bm_face_split_by_edges(bm, f, hflag, &edge_net_temp_buf);
- }
- }
- BLI_buffer_free(&edge_net_temp_buf);
- }
+ const char hflag = BM_ELEM_TAG;
+
+ BMEdge *e;
+ BMIter iter;
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if ((bm->totedgesel == 0) || (bm->totfacesel == 0)) {
+ continue;
+ }
+
+ BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
+
+ {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(v, hflag);
+ }
+ }
+
+ /* edge index is set to -1 then used to associate them with faces */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
+ BM_elem_flag_enable(e, hflag);
+
+ BM_elem_flag_enable(e->v1, hflag);
+ BM_elem_flag_enable(e->v2, hflag);
+ }
+ else {
+ BM_elem_flag_disable(e, hflag);
+ }
+ BM_elem_index_set(e, -1); /* set_dirty */
+ }
+ bm->elem_index_dirty |= BM_EDGE;
+
+ {
+ BMFace *f;
+ int i;
+ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(f, hflag);
+ }
+ else {
+ BM_elem_flag_disable(f, hflag);
+ }
+ BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
+ BM_elem_index_set(f, i); /* set_ok */
+ }
+ }
+ bm->elem_index_dirty &= ~BM_FACE;
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, hflag)) {
+ BMIter viter;
+ BMVert *v;
+ BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
+ BMIter liter;
+ BMLoop *l;
+
+ unsigned int loop_stack_len;
+ BMLoop *l_best = NULL;
+
+ BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
+ loop_stack_len = 0;
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(l->f, hflag)) {
+ BLI_SMALLSTACK_PUSH(loop_stack, l);
+ loop_stack_len++;
+ }
+ }
+
+ if (loop_stack_len == 0) {
+ /* pass */
+ }
+ else if (loop_stack_len == 1) {
+ l_best = BLI_SMALLSTACK_POP(loop_stack);
+ }
+ else {
+ /* complicated case, match the edge with a face-loop */
+
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ float e_dir[3];
+
+ /* we want closest to zero */
+ float dot_best = FLT_MAX;
+
+ sub_v3_v3v3(e_dir, v_other->co, v->co);
+ normalize_v3(e_dir);
+
+ while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
+ float dot_test;
+
+ /* Check dot first to save on expensive angle-comparison.
+ * ideal case is 90d difference == 0.0 dot */
+ dot_test = fabsf(dot_v3v3(e_dir, l->f->no));
+ if (dot_test < dot_best) {
+
+ /* check we're in the correct corner
+ * (works with convex loops too) */
+ if (angle_signed_on_axis_v3v3v3_v3(
+ l->prev->v->co, l->v->co, v_other->co, l->f->no) <
+ angle_signed_on_axis_v3v3v3_v3(
+ l->prev->v->co, l->v->co, l->next->v->co, l->f->no)) {
+ dot_best = dot_test;
+ l_best = l;
+ }
+ }
+ }
+ }
+
+ if (l_best) {
+ BM_elem_index_set(e, BM_elem_index_get(l_best->f)); /* set_dirty */
+ }
+ }
+ }
+ }
+
+ {
+ BMFace *f;
+ BLI_buffer_declare_static(BMEdge **, edge_net_temp_buf, 0, 128);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, hflag)) {
+ bm_face_split_by_edges(bm, f, hflag, &edge_net_temp_buf);
+ }
+ }
+ BLI_buffer_free(&edge_net_temp_buf);
+ }
#ifdef USE_NET_ISLAND_CONNECT
- /* before overwriting edge index values, collect edges left untouched */
- BLI_Stack *edges_loose = BLI_stack_new(sizeof(BMEdge *), __func__);
- BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
- BLI_stack_push(edges_loose, &e);
- }
- }
+ /* before overwriting edge index values, collect edges left untouched */
+ BLI_Stack *edges_loose = BLI_stack_new(sizeof(BMEdge *), __func__);
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
+ BLI_stack_push(edges_loose, &e);
+ }
+ }
#endif
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
-
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
#ifdef USE_NET_ISLAND_CONNECT
- /* we may have remaining isolated regions remaining,
- * these will need to have connecting edges created */
- if (!BLI_stack_is_empty(edges_loose)) {
- GHash *face_edge_map = BLI_ghash_ptr_new(__func__);
-
- MemArena *mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
-
- BM_mesh_elem_index_ensure(bm, BM_FACE);
-
- {
- BMBVHTree *bmbvh = BKE_bmbvh_new(bm, em->looptris, em->tottri, BMBVH_RESPECT_SELECT, NULL, false);
-
- BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_index_set(e, -1); /* set_dirty */
- }
-
- while (!BLI_stack_is_empty(edges_loose)) {
- BLI_stack_pop(edges_loose, &e);
- float e_center[3];
- mid_v3_v3v3(e_center, e->v1->co, e->v2->co);
-
- BMFace *f = BKE_bmbvh_find_face_closest(bmbvh, e_center, FLT_MAX);
- if (f) {
- ghash_insert_face_edge_link(face_edge_map, f, e, mem_arena);
- BM_elem_index_set(e, BM_elem_index_get(f)); /* set_dirty */
- }
- }
-
- BKE_bmbvh_free(bmbvh);
- }
-
- bm->elem_index_dirty |= BM_EDGE;
-
- BM_mesh_elem_table_ensure(bm, BM_FACE);
-
- /* detect edges chains that span faces
- * and splice vertices into the closest edges */
- {
- GHashIterator gh_iter;
-
- GHASH_ITER(gh_iter, face_edge_map) {
- BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
- LinkNode *e_link = e_ls_base->list;
-
- do {
- e = e_link->link;
-
- for (int j = 0; j < 2; j++) {
- BMVert *v_pivot = (&e->v1)[j];
- /* checking that \a v_pivot isn't in the face prevents attempting
- * to splice the same vertex into an edge from multiple faces */
- if (!BM_vert_in_face(v_pivot, f)) {
- float v_pivot_co[3];
- float v_pivot_fac;
- BMEdge *e_split = bm_face_split_edge_find(
- e, f, v_pivot, bm->ftable, bm->totface,
- v_pivot_co, &v_pivot_fac);
-
- if (e_split) {
- /* for degenerate cases this vertex may be in one
- * of this edges radial faces */
- if (!bm_vert_in_faces_radial(v_pivot, e_split, f)) {
- BMEdge *e_new;
- BMVert *v_new = BM_edge_split(bm, e_split, e_split->v1, &e_new, v_pivot_fac);
- if (v_new) {
- /* we _know_ these don't share an edge */
- BM_vert_splice(bm, v_pivot, v_new);
- BM_elem_index_set(e_new, BM_elem_index_get(e_split));
- }
- }
- }
- }
- }
-
- } while ((e_link = e_link->next));
- }
- }
-
-
- {
- MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
-
- GHashIterator gh_iter;
-
- GHASH_ITER(gh_iter, face_edge_map) {
- BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
-
- bm_face_split_by_edges_island_connect(
- bm, f,
- e_ls_base->list, e_ls_base->list_len,
- mem_arena_edgenet);
-
- BLI_memarena_clear(mem_arena_edgenet);
- }
-
- BLI_memarena_free(mem_arena_edgenet);
- }
-
- BLI_memarena_free(mem_arena);
-
- BLI_ghash_free(face_edge_map, NULL, NULL);
-
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
- }
-
- BLI_stack_free(edges_loose);
-#endif /* USE_NET_ISLAND_CONNECT */
-
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ /* we may have remaining isolated regions remaining,
+ * these will need to have connecting edges created */
+ if (!BLI_stack_is_empty(edges_loose)) {
+ GHash *face_edge_map = BLI_ghash_ptr_new(__func__);
+
+ MemArena *mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
+
+ {
+ BMBVHTree *bmbvh = BKE_bmbvh_new(
+ bm, em->looptris, em->tottri, BMBVH_RESPECT_SELECT, NULL, false);
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_index_set(e, -1); /* set_dirty */
+ }
+
+ while (!BLI_stack_is_empty(edges_loose)) {
+ BLI_stack_pop(edges_loose, &e);
+ float e_center[3];
+ mid_v3_v3v3(e_center, e->v1->co, e->v2->co);
+
+ BMFace *f = BKE_bmbvh_find_face_closest(bmbvh, e_center, FLT_MAX);
+ if (f) {
+ ghash_insert_face_edge_link(face_edge_map, f, e, mem_arena);
+ BM_elem_index_set(e, BM_elem_index_get(f)); /* set_dirty */
+ }
+ }
+
+ BKE_bmbvh_free(bmbvh);
+ }
+
+ bm->elem_index_dirty |= BM_EDGE;
+
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
+
+ /* detect edges chains that span faces
+ * and splice vertices into the closest edges */
+ {
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, face_edge_map) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+ LinkNode *e_link = e_ls_base->list;
+
+ do {
+ e = e_link->link;
+
+ for (int j = 0; j < 2; j++) {
+ BMVert *v_pivot = (&e->v1)[j];
+ /* checking that \a v_pivot isn't in the face prevents attempting
+ * to splice the same vertex into an edge from multiple faces */
+ if (!BM_vert_in_face(v_pivot, f)) {
+ float v_pivot_co[3];
+ float v_pivot_fac;
+ BMEdge *e_split = bm_face_split_edge_find(
+ e, f, v_pivot, bm->ftable, bm->totface, v_pivot_co, &v_pivot_fac);
+
+ if (e_split) {
+ /* for degenerate cases this vertex may be in one
+ * of this edges radial faces */
+ if (!bm_vert_in_faces_radial(v_pivot, e_split, f)) {
+ BMEdge *e_new;
+ BMVert *v_new = BM_edge_split(bm, e_split, e_split->v1, &e_new, v_pivot_fac);
+ if (v_new) {
+ /* we _know_ these don't share an edge */
+ BM_vert_splice(bm, v_pivot, v_new);
+ BM_elem_index_set(e_new, BM_elem_index_get(e_split));
+ }
+ }
+ }
+ }
+ }
+
+ } while ((e_link = e_link->next));
+ }
+ }
+
+ {
+ MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, face_edge_map) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+
+ bm_face_split_by_edges_island_connect(
+ bm, f, e_ls_base->list, e_ls_base->list_len, mem_arena_edgenet);
+
+ BLI_memarena_clear(mem_arena_edgenet);
+ }
+
+ BLI_memarena_free(mem_arena_edgenet);
+ }
+
+ BLI_memarena_free(mem_arena);
+
+ BLI_ghash_free(face_edge_map, NULL, NULL);
+
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+ }
+
+ BLI_stack_free(edges_loose);
+#endif /* USE_NET_ISLAND_CONNECT */
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
-
void MESH_OT_face_split_by_edges(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Weld Edges into Faces";
- ot->description = "Weld loose edges into faces (splitting them into new faces)";
- ot->idname = "MESH_OT_face_split_by_edges";
+ /* identifiers */
+ ot->name = "Weld Edges into Faces";
+ ot->description = "Weld loose edges into faces (splitting them into new faces)";
+ ot->idname = "MESH_OT_face_split_by_edges";
- /* api callbacks */
- ot->exec = edbm_face_split_by_edges_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_face_split_by_edges_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */