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/bmesh/tools/bmesh_bisect_plane.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/bmesh/tools/bmesh_bisect_plane.c')
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.c784
1 files changed, 410 insertions, 374 deletions
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c
index da7feff70e6..f314ae6848b 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.c
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c
@@ -39,36 +39,43 @@
#include "BLI_math.h"
#include "bmesh.h"
-#include "bmesh_bisect_plane.h" /* own include */
-
-#include "BLI_strict_flags.h" /* keep last */
+#include "bmesh_bisect_plane.h" /* own include */
+#include "BLI_strict_flags.h" /* keep last */
/* -------------------------------------------------------------------- */
/* Math utils */
-static short plane_point_test_v3(const float plane[4], const float co[3], const float eps, float *r_depth)
+static short plane_point_test_v3(const float plane[4],
+ const float co[3],
+ const float eps,
+ float *r_depth)
{
- const float f = plane_point_side_v3(plane, co);
- *r_depth = f;
-
- if (f <= -eps) { return -1; }
- else if (f >= eps) { return 1; }
- else { return 0; }
+ const float f = plane_point_side_v3(plane, co);
+ *r_depth = f;
+
+ if (f <= -eps) {
+ return -1;
+ }
+ else if (f >= eps) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
-
/* -------------------------------------------------------------------- */
/* Wrappers to hide internal data-structure abuse,
* later we may want to move this into some hash lookup
* to a separate struct, but for now we can store in BMesh data */
-#define BM_VERT_DIR(v) ((short *)(&(v)->head.index))[0] /* Direction -1/0/1 */
-#define BM_VERT_SKIP(v) ((short *)(&(v)->head.index))[1] /* Skip Vert 0/1 */
-#define BM_VERT_DIST(v) ((v)->no[0]) /* Distance from the plane. */
-#define BM_VERT_SORTVAL(v) ((v)->no[1]) /* Temp value for sorting. */
-#define BM_VERT_LOOPINDEX(v) /* The verts index within a face (temp var) */ \
- (*((uint *)(&(v)->no[2])))
+#define BM_VERT_DIR(v) ((short *)(&(v)->head.index))[0] /* Direction -1/0/1 */
+#define BM_VERT_SKIP(v) ((short *)(&(v)->head.index))[1] /* Skip Vert 0/1 */
+#define BM_VERT_DIST(v) ((v)->no[0]) /* Distance from the plane. */
+#define BM_VERT_SORTVAL(v) ((v)->no[1]) /* Temp value for sorting. */
+#define BM_VERT_LOOPINDEX(v) /* The verts index within a face (temp var) */ \
+ (*((uint *)(&(v)->no[2])))
/**
* Hide flag access
@@ -76,220 +83,247 @@ static short plane_point_test_v3(const float plane[4], const float co[3], const
*/
/* enable when vertex is in the center and its faces have been added to the stack */
-BLI_INLINE void vert_is_center_enable(BMVert *v) { BM_elem_flag_enable(v, BM_ELEM_TAG); }
-BLI_INLINE void vert_is_center_disable(BMVert *v) { BM_elem_flag_disable(v, BM_ELEM_TAG); }
-BLI_INLINE bool vert_is_center_test(BMVert *v) { return (BM_elem_flag_test(v, BM_ELEM_TAG) != 0); }
+BLI_INLINE void vert_is_center_enable(BMVert *v)
+{
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+}
+BLI_INLINE void vert_is_center_disable(BMVert *v)
+{
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+}
+BLI_INLINE bool vert_is_center_test(BMVert *v)
+{
+ return (BM_elem_flag_test(v, BM_ELEM_TAG) != 0);
+}
/* enable when the edge can be cut */
-BLI_INLINE void edge_is_cut_enable(BMEdge *e) { BM_elem_flag_enable(e, BM_ELEM_TAG); }
-BLI_INLINE void edge_is_cut_disable(BMEdge *e) { BM_elem_flag_disable(e, BM_ELEM_TAG); }
-BLI_INLINE bool edge_is_cut_test(BMEdge *e) { return (BM_elem_flag_test(e, BM_ELEM_TAG) != 0); }
+BLI_INLINE void edge_is_cut_enable(BMEdge *e)
+{
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+}
+BLI_INLINE void edge_is_cut_disable(BMEdge *e)
+{
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+}
+BLI_INLINE bool edge_is_cut_test(BMEdge *e)
+{
+ return (BM_elem_flag_test(e, BM_ELEM_TAG) != 0);
+}
/* enable when the faces are added to the stack */
-BLI_INLINE void face_in_stack_enable(BMFace *f) { BM_elem_flag_disable(f, BM_ELEM_TAG); }
-BLI_INLINE void face_in_stack_disable(BMFace *f) { BM_elem_flag_enable(f, BM_ELEM_TAG); }
-BLI_INLINE bool face_in_stack_test(BMFace *f) { return (BM_elem_flag_test(f, BM_ELEM_TAG) == 0); }
+BLI_INLINE void face_in_stack_enable(BMFace *f)
+{
+ BM_elem_flag_disable(f, BM_ELEM_TAG);
+}
+BLI_INLINE void face_in_stack_disable(BMFace *f)
+{
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+}
+BLI_INLINE bool face_in_stack_test(BMFace *f)
+{
+ return (BM_elem_flag_test(f, BM_ELEM_TAG) == 0);
+}
/* -------------------------------------------------------------------- */
/* BMesh utils */
static int bm_vert_sortval_cb(const void *v_a_v, const void *v_b_v)
{
- const float val_a = BM_VERT_SORTVAL(*((BMVert **)v_a_v));
- const float val_b = BM_VERT_SORTVAL(*((BMVert **)v_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_VERT_SORTVAL(*((BMVert **)v_a_v));
+ const float val_b = BM_VERT_SORTVAL(*((BMVert **)v_b_v));
+
+ if (val_a > val_b) {
+ return 1;
+ }
+ else if (val_a < val_b) {
+ return -1;
+ }
+ else {
+ return 0;
+ }
}
-
-static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center, const short oflag_new)
+static void bm_face_bisect_verts(
+ BMesh *bm, BMFace *f, const float plane[4], const short oflag_center, const short oflag_new)
{
- /* unlikely more than 2 verts are needed */
- const uint f_len_orig = (uint)f->len;
- BMVert **vert_split_arr = BLI_array_alloca(vert_split_arr, f_len_orig);
- STACK_DECLARE(vert_split_arr);
- BMLoop *l_iter, *l_first;
- bool use_dirs[3] = {false, false, false};
- bool is_inside = false;
-
- STACK_INIT(vert_split_arr, f_len_orig);
-
- l_first = BM_FACE_FIRST_LOOP(f);
-
- /* add plane-aligned verts to the stack
- * and check we have verts from both sides in this face,
- * ... that the face doesn't only have boundary verts on the plane for eg. */
- l_iter = l_first;
- do {
- if (vert_is_center_test(l_iter->v)) {
- BLI_assert(BM_VERT_DIR(l_iter->v) == 0);
-
- /* if both are -1 or 1, or both are zero:
- * don't flip 'inside' var while walking */
- BM_VERT_SKIP(l_iter->v) = (((BM_VERT_DIR(l_iter->prev->v) ^ BM_VERT_DIR(l_iter->next->v))) == 0);
-
- STACK_PUSH(vert_split_arr, l_iter->v);
- }
- use_dirs[BM_VERT_DIR(l_iter->v) + 1] = true;
- } while ((l_iter = l_iter->next) != l_first);
-
- if ((STACK_SIZE(vert_split_arr) > 1) &&
- (use_dirs[0] && use_dirs[2]))
- {
- if (LIKELY(STACK_SIZE(vert_split_arr) == 2)) {
- BMLoop *l_new;
- BMLoop *l_a, *l_b;
-
- l_a = BM_face_vert_share_loop(f, vert_split_arr[0]);
- l_b = BM_face_vert_share_loop(f, vert_split_arr[1]);
-
- /* common case, just cut the face once */
- BM_face_split(bm, f, l_a, l_b, &l_new, NULL, true);
- if (l_new) {
- if (oflag_center | oflag_new) {
- BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
- }
- if (oflag_new) {
- BMO_face_flag_enable(bm, l_new->f, oflag_new);
- }
- }
- }
- else {
- /* less common case, _complicated_ we need to calculate how to do multiple cuts */
- float (*face_verts_proj_2d)[2] = BLI_array_alloca(face_verts_proj_2d, f_len_orig);
- float axis_mat[3][3];
-
- BMFace **face_split_arr = BLI_array_alloca(face_split_arr, STACK_SIZE(vert_split_arr));
- STACK_DECLARE(face_split_arr);
-
- float sort_dir[3];
- uint i;
-
-
- /* ---- */
- /* Calculate the direction to sort verts in the face intersecting the plane */
-
- /* exact dir isn't so important,
- * just need a dir for sorting verts across face,
- * 'sort_dir' could be flipped either way, it not important, we only need to order the array
- */
- cross_v3_v3v3(sort_dir, f->no, plane);
- if (UNLIKELY(normalize_v3(sort_dir) == 0.0f)) {
- /* find any 2 verts and get their direction */
- for (i = 0; i < STACK_SIZE(vert_split_arr); i++) {
- if (!equals_v3v3(vert_split_arr[0]->co, vert_split_arr[i]->co)) {
- sub_v3_v3v3(sort_dir, vert_split_arr[0]->co, vert_split_arr[i]->co);
- normalize_v3(sort_dir);
- }
- }
- if (UNLIKELY(i == STACK_SIZE(vert_split_arr))) {
- /* ok, we can't do anything useful here,
- * face has no area or so, bail out, this is highly unlikely but not impossible */
- goto finally;
- }
- }
-
-
- /* ---- */
- /* Calculate 2d coords to use for intersection checks */
-
- /* get the faces 2d coords */
- BLI_assert(BM_face_is_normal_valid(f));
- axis_dominant_v3_to_m3(axis_mat, f->no);
-
- l_iter = l_first;
- i = 0;
- do {
- BM_VERT_LOOPINDEX(l_iter->v) = i;
- mul_v2_m3v3(face_verts_proj_2d[i], axis_mat, l_iter->v->co);
- i++;
- } while ((l_iter = l_iter->next) != l_first);
-
-
- /* ---- */
- /* Sort the verts across the face from one side to another */
- for (i = 0; i < STACK_SIZE(vert_split_arr); i++) {
- BMVert *v = vert_split_arr[i];
- BM_VERT_SORTVAL(v) = dot_v3v3(sort_dir, v->co);
- }
-
- qsort(vert_split_arr, STACK_SIZE(vert_split_arr), sizeof(*vert_split_arr), bm_vert_sortval_cb);
-
-
- /* ---- */
- /* Split the face across sorted splits */
-
- /* note: we don't know which face gets which splits,
- * so at the moment we have to search all faces for the vert pair,
- * while not all that nice, typically there are < 5 resulting faces,
- * so its not _that_ bad. */
-
- STACK_INIT(face_split_arr, STACK_SIZE(vert_split_arr));
- STACK_PUSH(face_split_arr, f);
-
- for (i = 0; i < STACK_SIZE(vert_split_arr) - 1; i++) {
- BMVert *v_a = vert_split_arr[i];
- BMVert *v_b = vert_split_arr[i + 1];
-
- if (!BM_VERT_SKIP(v_a)) {
- is_inside = !is_inside;
- }
-
- if (is_inside) {
- BMLoop *l_a, *l_b;
- bool found = false;
- uint j;
-
- for (j = 0; j < STACK_SIZE(face_split_arr); j++) {
- /* would be nice to avoid loop lookup here,
- * but we need to know which face the verts are in */
- if ((l_a = BM_face_vert_share_loop(face_split_arr[j], v_a)) &&
- (l_b = BM_face_vert_share_loop(face_split_arr[j], v_b)))
- {
- found = true;
- break;
- }
- }
-
- /* ideally wont happen, but it can for self intersecting faces */
- // BLI_assert(found == true);
-
- /* in fact this simple test is good enough,
- * test if the loops are adjacent */
- if (found && !BM_loop_is_adjacent(l_a, l_b)) {
- BMLoop *l_new;
- BMFace *f_tmp;
- f_tmp = BM_face_split(bm, face_split_arr[j], l_a, l_b, &l_new, NULL, true);
-
- if (l_new) {
- if (oflag_center | oflag_new) {
- BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
- }
- if (oflag_new) {
- BMO_face_flag_enable(bm, l_new->f, oflag_new);
- }
- }
-
- if (f_tmp) {
- if (f_tmp != face_split_arr[j]) {
- STACK_PUSH(face_split_arr, f_tmp);
- BLI_assert(STACK_SIZE(face_split_arr) <= STACK_SIZE(vert_split_arr));
- }
- }
- }
- }
- else {
- // printf("no intersect\n");
- }
- }
- }
- }
-
+ /* unlikely more than 2 verts are needed */
+ const uint f_len_orig = (uint)f->len;
+ BMVert **vert_split_arr = BLI_array_alloca(vert_split_arr, f_len_orig);
+ STACK_DECLARE(vert_split_arr);
+ BMLoop *l_iter, *l_first;
+ bool use_dirs[3] = {false, false, false};
+ bool is_inside = false;
+
+ STACK_INIT(vert_split_arr, f_len_orig);
+
+ l_first = BM_FACE_FIRST_LOOP(f);
+
+ /* add plane-aligned verts to the stack
+ * and check we have verts from both sides in this face,
+ * ... that the face doesn't only have boundary verts on the plane for eg. */
+ l_iter = l_first;
+ do {
+ if (vert_is_center_test(l_iter->v)) {
+ BLI_assert(BM_VERT_DIR(l_iter->v) == 0);
+
+ /* if both are -1 or 1, or both are zero:
+ * don't flip 'inside' var while walking */
+ BM_VERT_SKIP(l_iter->v) = (((BM_VERT_DIR(l_iter->prev->v) ^ BM_VERT_DIR(l_iter->next->v))) ==
+ 0);
+
+ STACK_PUSH(vert_split_arr, l_iter->v);
+ }
+ use_dirs[BM_VERT_DIR(l_iter->v) + 1] = true;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if ((STACK_SIZE(vert_split_arr) > 1) && (use_dirs[0] && use_dirs[2])) {
+ if (LIKELY(STACK_SIZE(vert_split_arr) == 2)) {
+ BMLoop *l_new;
+ BMLoop *l_a, *l_b;
+
+ l_a = BM_face_vert_share_loop(f, vert_split_arr[0]);
+ l_b = BM_face_vert_share_loop(f, vert_split_arr[1]);
+
+ /* common case, just cut the face once */
+ BM_face_split(bm, f, l_a, l_b, &l_new, NULL, true);
+ if (l_new) {
+ if (oflag_center | oflag_new) {
+ BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
+ }
+ if (oflag_new) {
+ BMO_face_flag_enable(bm, l_new->f, oflag_new);
+ }
+ }
+ }
+ else {
+ /* less common case, _complicated_ we need to calculate how to do multiple cuts */
+ float(*face_verts_proj_2d)[2] = BLI_array_alloca(face_verts_proj_2d, f_len_orig);
+ float axis_mat[3][3];
+
+ BMFace **face_split_arr = BLI_array_alloca(face_split_arr, STACK_SIZE(vert_split_arr));
+ STACK_DECLARE(face_split_arr);
+
+ float sort_dir[3];
+ uint i;
+
+ /* ---- */
+ /* Calculate the direction to sort verts in the face intersecting the plane */
+
+ /* exact dir isn't so important,
+ * just need a dir for sorting verts across face,
+ * 'sort_dir' could be flipped either way, it not important, we only need to order the array
+ */
+ cross_v3_v3v3(sort_dir, f->no, plane);
+ if (UNLIKELY(normalize_v3(sort_dir) == 0.0f)) {
+ /* find any 2 verts and get their direction */
+ for (i = 0; i < STACK_SIZE(vert_split_arr); i++) {
+ if (!equals_v3v3(vert_split_arr[0]->co, vert_split_arr[i]->co)) {
+ sub_v3_v3v3(sort_dir, vert_split_arr[0]->co, vert_split_arr[i]->co);
+ normalize_v3(sort_dir);
+ }
+ }
+ if (UNLIKELY(i == STACK_SIZE(vert_split_arr))) {
+ /* ok, we can't do anything useful here,
+ * face has no area or so, bail out, this is highly unlikely but not impossible */
+ goto finally;
+ }
+ }
+
+ /* ---- */
+ /* Calculate 2d coords to use for intersection checks */
+
+ /* get the faces 2d coords */
+ BLI_assert(BM_face_is_normal_valid(f));
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+ l_iter = l_first;
+ i = 0;
+ do {
+ BM_VERT_LOOPINDEX(l_iter->v) = i;
+ mul_v2_m3v3(face_verts_proj_2d[i], axis_mat, l_iter->v->co);
+ i++;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* ---- */
+ /* Sort the verts across the face from one side to another */
+ for (i = 0; i < STACK_SIZE(vert_split_arr); i++) {
+ BMVert *v = vert_split_arr[i];
+ BM_VERT_SORTVAL(v) = dot_v3v3(sort_dir, v->co);
+ }
+
+ qsort(
+ vert_split_arr, STACK_SIZE(vert_split_arr), sizeof(*vert_split_arr), bm_vert_sortval_cb);
+
+ /* ---- */
+ /* Split the face across sorted splits */
+
+ /* note: we don't know which face gets which splits,
+ * so at the moment we have to search all faces for the vert pair,
+ * while not all that nice, typically there are < 5 resulting faces,
+ * so its not _that_ bad. */
+
+ STACK_INIT(face_split_arr, STACK_SIZE(vert_split_arr));
+ STACK_PUSH(face_split_arr, f);
+
+ for (i = 0; i < STACK_SIZE(vert_split_arr) - 1; i++) {
+ BMVert *v_a = vert_split_arr[i];
+ BMVert *v_b = vert_split_arr[i + 1];
+
+ if (!BM_VERT_SKIP(v_a)) {
+ is_inside = !is_inside;
+ }
+
+ if (is_inside) {
+ BMLoop *l_a, *l_b;
+ bool found = false;
+ uint j;
+
+ for (j = 0; j < STACK_SIZE(face_split_arr); j++) {
+ /* would be nice to avoid loop lookup here,
+ * but we need to know which face the verts are in */
+ if ((l_a = BM_face_vert_share_loop(face_split_arr[j], v_a)) &&
+ (l_b = BM_face_vert_share_loop(face_split_arr[j], v_b))) {
+ found = true;
+ break;
+ }
+ }
+
+ /* ideally wont happen, but it can for self intersecting faces */
+ // BLI_assert(found == true);
+
+ /* in fact this simple test is good enough,
+ * test if the loops are adjacent */
+ if (found && !BM_loop_is_adjacent(l_a, l_b)) {
+ BMLoop *l_new;
+ BMFace *f_tmp;
+ f_tmp = BM_face_split(bm, face_split_arr[j], l_a, l_b, &l_new, NULL, true);
+
+ if (l_new) {
+ if (oflag_center | oflag_new) {
+ BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
+ }
+ if (oflag_new) {
+ BMO_face_flag_enable(bm, l_new->f, oflag_new);
+ }
+ }
+
+ if (f_tmp) {
+ if (f_tmp != face_split_arr[j]) {
+ STACK_PUSH(face_split_arr, f_tmp);
+ BLI_assert(STACK_SIZE(face_split_arr) <= STACK_SIZE(vert_split_arr));
+ }
+ }
+ }
+ }
+ else {
+ // printf("no intersect\n");
+ }
+ }
+ }
+ }
finally:
- (void)vert_split_arr;
+ (void)vert_split_arr;
}
/* -------------------------------------------------------------------- */
@@ -300,163 +334,165 @@ finally:
* \param use_tag: Only bisect tagged edges and faces.
* \param oflag_center: Operator flag, enabled for geometry on the axis (existing and created)
*/
-void BM_mesh_bisect_plane(
- BMesh *bm, const float plane[4],
- const bool use_snap_center, const bool use_tag,
- const short oflag_center, const short oflag_new, const float eps)
+void BM_mesh_bisect_plane(BMesh *bm,
+ const float plane[4],
+ const bool use_snap_center,
+ const bool use_tag,
+ const short oflag_center,
+ const short oflag_new,
+ const float eps)
{
- uint einput_len;
- uint i;
- BMEdge **edges_arr = MEM_mallocN(sizeof(*edges_arr) * (size_t)bm->totedge, __func__);
-
- BLI_LINKSTACK_DECLARE(face_stack, BMFace *);
-
- BMVert *v;
- BMFace *f;
-
- BMIter iter;
-
- if (use_tag) {
- /* build tagged edge array */
- BMEdge *e;
- einput_len = 0;
-
- /* flush edge tags to verts */
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
-
- /* keep face tags as is */
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- if (edge_is_cut_test(e)) {
- edges_arr[einput_len++] = e;
-
- /* flush edge tags to verts */
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
- }
- }
-
- /* face tags are set by caller */
- }
- else {
- BMEdge *e;
- einput_len = (uint)bm->totedge;
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- edge_is_cut_enable(e);
- edges_arr[i] = e;
- }
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- face_in_stack_disable(f);
- }
- }
-
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
-
- if (use_tag && !BM_elem_flag_test(v, BM_ELEM_TAG)) {
- vert_is_center_disable(v);
-
- /* these should never be accessed */
- BM_VERT_DIR(v) = 0;
- BM_VERT_DIST(v) = 0.0f;
-
- continue;
- }
-
- vert_is_center_disable(v);
- BM_VERT_DIR(v) = plane_point_test_v3(plane, v->co, eps, &(BM_VERT_DIST(v)));
-
- if (BM_VERT_DIR(v) == 0) {
- if (oflag_center) {
- BMO_vert_flag_enable(bm, v, oflag_center);
- }
- if (use_snap_center) {
- closest_to_plane_v3(v->co, plane, v->co);
- }
- }
- }
-
- /* store a stack of faces to be evaluated for splitting */
- BLI_LINKSTACK_INIT(face_stack);
-
- for (i = 0; i < einput_len; i++) {
- /* we could check edge_is_cut_test(e) but there is no point */
- BMEdge *e = edges_arr[i];
- const int side[2] = {BM_VERT_DIR(e->v1), BM_VERT_DIR(e->v2)};
- const float dist[2] = {BM_VERT_DIST(e->v1), BM_VERT_DIST(e->v2)};
-
- if (side[0] && side[1] && (side[0] != side[1])) {
- const float e_fac = dist[0] / (dist[0] - dist[1]);
- BMVert *v_new;
-
- if (e->l) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- if (!face_in_stack_test(l_iter->f)) {
- face_in_stack_enable(l_iter->f);
- BLI_LINKSTACK_PUSH(face_stack, l_iter->f);
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
-
- {
- BMEdge *e_new;
- v_new = BM_edge_split(bm, e, e->v1, &e_new, e_fac);
- if (oflag_new) {
- BMO_edge_flag_enable(bm, e_new, oflag_new);
- }
- }
-
- vert_is_center_enable(v_new);
- if (oflag_new | oflag_center) {
- BMO_vert_flag_enable(bm, v_new, oflag_new | oflag_center);
- }
-
- BM_VERT_DIR(v_new) = 0;
- BM_VERT_DIST(v_new) = 0.0f;
- }
- else if (side[0] == 0 || side[1] == 0) {
- /* check if either edge verts are aligned,
- * if so - tag and push all faces that use it into the stack */
- uint j;
- BM_ITER_ELEM_INDEX (v, &iter, e, BM_VERTS_OF_EDGE, j) {
- if (side[j] == 0) {
- if (vert_is_center_test(v) == 0) {
- BMIter itersub;
- BMLoop *l_iter;
-
- vert_is_center_enable(v);
-
- BM_ITER_ELEM (l_iter, &itersub, v, BM_LOOPS_OF_VERT) {
- if (!face_in_stack_test(l_iter->f)) {
- face_in_stack_enable(l_iter->f);
- BLI_LINKSTACK_PUSH(face_stack, l_iter->f);
- }
- }
-
- }
- }
- }
-
- /* if both verts are on the center - tag it */
- if (oflag_center) {
- if (side[0] == 0 && side[1] == 0) {
- BMO_edge_flag_enable(bm, e, oflag_center);
- }
- }
- }
- }
-
- MEM_freeN(edges_arr);
-
- while ((f = BLI_LINKSTACK_POP(face_stack))) {
- bm_face_bisect_verts(bm, f, plane, oflag_center, oflag_new);
- }
-
- /* Caused by access macros: BM_VERT_DIR, BM_VERT_SKIP. */
- bm->elem_index_dirty |= BM_VERT;
-
- /* now we have all faces to split in the stack */
- BLI_LINKSTACK_FREE(face_stack);
+ uint einput_len;
+ uint i;
+ BMEdge **edges_arr = MEM_mallocN(sizeof(*edges_arr) * (size_t)bm->totedge, __func__);
+
+ BLI_LINKSTACK_DECLARE(face_stack, BMFace *);
+
+ BMVert *v;
+ BMFace *f;
+
+ BMIter iter;
+
+ if (use_tag) {
+ /* build tagged edge array */
+ BMEdge *e;
+ einput_len = 0;
+
+ /* flush edge tags to verts */
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+
+ /* keep face tags as is */
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ if (edge_is_cut_test(e)) {
+ edges_arr[einput_len++] = e;
+
+ /* flush edge tags to verts */
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ }
+ }
+
+ /* face tags are set by caller */
+ }
+ else {
+ BMEdge *e;
+ einput_len = (uint)bm->totedge;
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ edge_is_cut_enable(e);
+ edges_arr[i] = e;
+ }
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ face_in_stack_disable(f);
+ }
+ }
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+
+ if (use_tag && !BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ vert_is_center_disable(v);
+
+ /* these should never be accessed */
+ BM_VERT_DIR(v) = 0;
+ BM_VERT_DIST(v) = 0.0f;
+
+ continue;
+ }
+
+ vert_is_center_disable(v);
+ BM_VERT_DIR(v) = plane_point_test_v3(plane, v->co, eps, &(BM_VERT_DIST(v)));
+
+ if (BM_VERT_DIR(v) == 0) {
+ if (oflag_center) {
+ BMO_vert_flag_enable(bm, v, oflag_center);
+ }
+ if (use_snap_center) {
+ closest_to_plane_v3(v->co, plane, v->co);
+ }
+ }
+ }
+
+ /* store a stack of faces to be evaluated for splitting */
+ BLI_LINKSTACK_INIT(face_stack);
+
+ for (i = 0; i < einput_len; i++) {
+ /* we could check edge_is_cut_test(e) but there is no point */
+ BMEdge *e = edges_arr[i];
+ const int side[2] = {BM_VERT_DIR(e->v1), BM_VERT_DIR(e->v2)};
+ const float dist[2] = {BM_VERT_DIST(e->v1), BM_VERT_DIST(e->v2)};
+
+ if (side[0] && side[1] && (side[0] != side[1])) {
+ const float e_fac = dist[0] / (dist[0] - dist[1]);
+ BMVert *v_new;
+
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (!face_in_stack_test(l_iter->f)) {
+ face_in_stack_enable(l_iter->f);
+ BLI_LINKSTACK_PUSH(face_stack, l_iter->f);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ {
+ BMEdge *e_new;
+ v_new = BM_edge_split(bm, e, e->v1, &e_new, e_fac);
+ if (oflag_new) {
+ BMO_edge_flag_enable(bm, e_new, oflag_new);
+ }
+ }
+
+ vert_is_center_enable(v_new);
+ if (oflag_new | oflag_center) {
+ BMO_vert_flag_enable(bm, v_new, oflag_new | oflag_center);
+ }
+
+ BM_VERT_DIR(v_new) = 0;
+ BM_VERT_DIST(v_new) = 0.0f;
+ }
+ else if (side[0] == 0 || side[1] == 0) {
+ /* check if either edge verts are aligned,
+ * if so - tag and push all faces that use it into the stack */
+ uint j;
+ BM_ITER_ELEM_INDEX(v, &iter, e, BM_VERTS_OF_EDGE, j)
+ {
+ if (side[j] == 0) {
+ if (vert_is_center_test(v) == 0) {
+ BMIter itersub;
+ BMLoop *l_iter;
+
+ vert_is_center_enable(v);
+
+ BM_ITER_ELEM (l_iter, &itersub, v, BM_LOOPS_OF_VERT) {
+ if (!face_in_stack_test(l_iter->f)) {
+ face_in_stack_enable(l_iter->f);
+ BLI_LINKSTACK_PUSH(face_stack, l_iter->f);
+ }
+ }
+ }
+ }
+ }
+
+ /* if both verts are on the center - tag it */
+ if (oflag_center) {
+ if (side[0] == 0 && side[1] == 0) {
+ BMO_edge_flag_enable(bm, e, oflag_center);
+ }
+ }
+ }
+ }
+
+ MEM_freeN(edges_arr);
+
+ while ((f = BLI_LINKSTACK_POP(face_stack))) {
+ bm_face_bisect_verts(bm, f, plane, oflag_center, oflag_new);
+ }
+
+ /* Caused by access macros: BM_VERT_DIR, BM_VERT_SKIP. */
+ bm->elem_index_dirty |= BM_VERT;
+
+ /* now we have all faces to split in the stack */
+ BLI_LINKSTACK_FREE(face_stack);
}