[Bf-blender-cvs] [6b189d2bcf3] master: Edit Mesh: New option "Split Edges & Faces" to "AutoMerge"

mano-wii noreply at git.blender.org
Mon Aug 26 19:16:00 CEST 2019


Commit: 6b189d2bcf3536231f7040926ed34fe01012f14e
Author: mano-wii
Date:   Mon Aug 26 14:15:25 2019 -0300
Branches: master
https://developer.blender.org/rB6b189d2bcf3536231f7040926ed34fe01012f14e

Edit Mesh: New option "Split Edges & Faces" to "AutoMerge"

Ref T66423

Differential revision: https://developer.blender.org/D5562

===================================================================

M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/blenlib/BLI_kdopbvh.h
M	source/blender/blenlib/intern/BLI_kdopbvh.c
M	source/blender/bmesh/intern/bmesh_query.c
M	source/blender/bmesh/intern/bmesh_query.h
M	source/blender/editors/include/ED_mesh.h
M	source/blender/editors/mesh/editmesh_select.c
M	source/blender/editors/transform/transform_conversions.c
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/intern/rna_scene.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 5246d8fa864..9fd35808b4b 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -177,6 +177,7 @@ class VIEW3D_PT_tools_meshedit_options_automerge(View3DPanel, Panel):
         layout.use_property_decorate = False
 
         layout.active = tool_settings.use_mesh_automerge
+        layout.prop(tool_settings, "use_mesh_automerge_and_split", toggle=False)
         layout.prop(tool_settings, "double_threshold", text="Threshold")
 
 # ********** default tools for editmode_curve ****************
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index a348694c4da..abfd561200c 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -177,6 +177,12 @@ int BLI_bvhtree_find_nearest(BVHTree *tree,
                              BVHTree_NearestPointCallback callback,
                              void *userdata);
 
+int BLI_bvhtree_find_nearest_first(BVHTree *tree,
+                                   const float co[3],
+                                   const float dist_sq,
+                                   BVHTree_NearestPointCallback callback,
+                                   void *userdata);
+
 int BLI_bvhtree_ray_cast_ex(BVHTree *tree,
                             const float co[3],
                             const float dir[3],
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 0e93fd8e13b..ed3c7096865 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -1466,6 +1466,95 @@ int BLI_bvhtree_find_nearest(BVHTree *tree,
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name BLI_bvhtree_find_nearest_first
+ * \{ */
+
+static bool isect_aabb_v3(BVHNode *node, const float co[3])
+{
+  const BVHTreeAxisRange *bv = (const BVHTreeAxisRange *)node->bv;
+
+  if (co[0] > bv[0].min && co[0] < bv[0].max && co[1] > bv[1].min && co[1] < bv[1].max &&
+      co[2] > bv[2].min && co[2] < bv[2].max) {
+    return true;
+  }
+
+  return false;
+}
+
+static bool dfs_find_duplicate_fast_dfs(BVHNearestData *data, BVHNode *node)
+{
+  if (node->totnode == 0) {
+    if (isect_aabb_v3(node, data->co)) {
+      if (data->callback) {
+        const float dist_sq = data->nearest.dist_sq;
+        data->callback(data->userdata, node->index, data->co, &data->nearest);
+        return (data->nearest.dist_sq < dist_sq);
+      }
+      else {
+        data->nearest.index = node->index;
+        return true;
+      }
+    }
+  }
+  else {
+    /* Better heuristic to pick the closest node to dive on */
+    int i;
+
+    if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) {
+      for (i = 0; i != node->totnode; i++) {
+        if (isect_aabb_v3(node->children[i], data->co)) {
+          if (dfs_find_duplicate_fast_dfs(data, node->children[i])) {
+            return true;
+          }
+        }
+      }
+    }
+    else {
+      for (i = node->totnode; i--;) {
+        if (isect_aabb_v3(node->children[i], data->co)) {
+          if (dfs_find_duplicate_fast_dfs(data, node->children[i])) {
+            return true;
+          }
+        }
+      }
+    }
+  }
+  return false;
+}
+
+/**
+ * Find the first node nearby.
+ * Favors speed over quality since it doesn't find the best target node.
+ */
+int BLI_bvhtree_find_nearest_first(BVHTree *tree,
+                                   const float co[3],
+                                   const float dist_sq,
+                                   BVHTree_NearestPointCallback callback,
+                                   void *userdata)
+{
+  BVHNearestData data;
+  BVHNode *root = tree->nodes[tree->totleaf];
+
+  /* init data to search */
+  data.tree = tree;
+  data.co = co;
+
+  data.callback = callback;
+  data.userdata = userdata;
+  data.nearest.index = -1;
+  data.nearest.dist_sq = dist_sq;
+
+  /* dfs search */
+  if (root) {
+    dfs_find_duplicate_fast_dfs(&data, root);
+  }
+
+  return data.nearest.index;
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name BLI_bvhtree_ray_cast
  *
diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c
index 51bc86e40eb..219bec15e5b 100644
--- a/source/blender/bmesh/intern/bmesh_query.c
+++ b/source/blender/bmesh/intern/bmesh_query.c
@@ -207,6 +207,34 @@ bool BM_vert_pair_share_face_check_cb(BMVert *v_a,
   return false;
 }
 
+BMFace *BM_vert_pair_shared_face_cb(BMVert *v_a,
+                                    BMVert *v_b,
+                                    const bool allow_adjacent,
+                                    bool (*callback)(BMFace *, BMLoop *, BMLoop *, void *userdata),
+                                    void *user_data,
+                                    BMLoop **r_l_a,
+                                    BMLoop **r_l_b)
+{
+  if (v_a->e && v_b->e) {
+    BMIter iter;
+    BMLoop *l_a, *l_b;
+
+    BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) {
+      BMFace *f = l_a->f;
+      l_b = BM_face_vert_share_loop(f, v_b);
+      if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b)) &&
+          callback(f, l_a, l_b, user_data)) {
+        *r_l_a = l_a;
+        *r_l_b = l_b;
+
+        return f;
+      }
+    }
+  }
+
+  return NULL;
+}
+
 /**
  * Given 2 verts, find the smallest face they share and give back both loops.
  */
diff --git a/source/blender/bmesh/intern/bmesh_query.h b/source/blender/bmesh/intern/bmesh_query.h
index e96984490c0..3a864fbb5dd 100644
--- a/source/blender/bmesh/intern/bmesh_query.h
+++ b/source/blender/bmesh/intern/bmesh_query.h
@@ -62,6 +62,13 @@ bool BM_vert_pair_share_face_check_cb(BMVert *v_a,
                                       bool (*test_fn)(BMFace *f, void *user_data),
                                       void *user_data) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL(1, 2, 3);
+BMFace *BM_vert_pair_shared_face_cb(BMVert *v_a,
+                                    BMVert *v_b,
+                                    const bool allow_adjacent,
+                                    bool (*callback)(BMFace *, BMLoop *, BMLoop *, void *userdata),
+                                    void *user_data,
+                                    BMLoop **r_l_a,
+                                    BMLoop **r_l_b) ATTR_NONNULL(1, 2, 4, 6, 7);
 BMFace *BM_vert_pair_share_face_by_len(BMVert *v_a,
                                        BMVert *v_b,
                                        BMLoop **r_l_a,
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 0b2adfed531..30d4aa10c1b 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -145,6 +145,8 @@ void ED_mesh_undosys_type(struct UndoType *ut);
 void EDBM_select_mirrored(
     struct BMEditMesh *em, const int axis, const bool extend, int *r_totmirr, int *r_totfail);
 void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag);
+void EDBM_automerge_and_split(
+    struct Scene *scene, struct Object *ob, bool split_edges, bool update, const char hflag);
 
 struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc,
                                          float *r_dist,
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 94ffd9a34d6..e60934734bc 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -31,8 +31,10 @@
 #include "BLI_math.h"
 #include "BLI_math_bits.h"
 #include "BLI_rand.h"
+#include "BLI_sort.h"
 #include "BLI_array.h"
 
+#include "BKE_bvhutils.h"
 #include "BKE_context.h"
 #include "BKE_report.h"
 #include "BKE_paint.h"
@@ -193,6 +195,314 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag)
   }
 }
 
+struct EDBMSplitEdge {
+  BMVert *v;
+  BMEdge *e;
+  float lambda;
+};
+
+struct EDBMSplitEdgeData {
+  BMesh *bm;
+
+  BMEdge *r_edge;
+  float r_lambda;
+};
+
+static bool edbm_automerge_and_split_check_best_face_cb(BMFace *UNUSED(f),
+                                                        BMLoop *l_a,
+                                                        BMLoop *l_b,
+                                                        void *userdata)
+{
+  float(*data)[3] = userdata;
+  float *v_a_co = data[0];
+  float *v_a_b_dir = data[1];
+
+  float lambda;
+  if (isect_ray_seg_v3(v_a_co, v_a_b_dir, l_a->prev->v->co, l_a->next->v->co, &lambda)) {
+    if (IN_RANGE(lambda, 0.0f, 1.0f)) {
+      if (isect_ray_seg_v3(v_a_co, v_a_b_dir, l_b->prev->v->co, l_b->next->v->co, &lambda)) {
+        return IN_RANGE(lambda, 0.0f, 1.0f);
+      }
+    }
+  }
+
+  return false;
+}
+
+static bool edbm_automerge_check_and_split_faces(BMesh *bm, BMVert *v_src, BMVert *v_dst)
+{
+  BMIter iter;
+  BMEdge *e_iter;
+  BM_ITER_ELEM (e_iter, &iter, v_src, BM_EDGES_OF_VERT) {
+    BMVert *vert_other = BM_edge_other_vert(e_iter, v_src);
+    if (vert_other != v_dst) {
+      float data[2][3];
+      copy_v3_v3(data[0], vert_other->co);
+      sub_v3_v3v3(data[1], v_dst->co, data[0]);
+
+      BMLoop *l_a, *l_b;
+      BMFace *f = BM_vert_pair_shared_face_cb(
+          vert_other, v_dst, false, edbm_automerge_and_split_check_best_face_cb, data, &l_a, &l_b);
+
+      if (f) {
+        BM_face_split(bm, f, l_a, l_b, NULL, NULL, true);
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+static void ebbm_automerge_and_split_find_duplicate_cb(void *userdata,
+                                                       int index,
+                                                       const float co[3],
+                                                       BVHTreeNearest *nearest)
+{
+  struct EDBMSplitEdgeData *data = userdata;
+  BMEdge *e = BM_edge_at_index(data->bm, index);
+  float lambda = line_point_factor_v3_ex(co, e->v1->co, e->v2->co, 0.0f, -1.0f);
+  if (IN_R

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list