[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