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
path: root/source
diff options
context:
space:
mode:
authormano-wii <germano.costa@ig.com.br>2019-08-27 07:41:05 +0300
committermano-wii <germano.costa@ig.com.br>2019-08-27 07:42:02 +0300
commite57b14feae9b4c206de7d33f53342210c01c8278 (patch)
tree2615b5fcfae596d92a67b5e1ece63d48b2a807cb /source
parent60ba7d4539b12c5be2b53fe59eb62033cf557e2a (diff)
Edit Mesh AutoMerge: Improve `Split Edges & Faces` option
Now all wire edges linked to the merged vertex are used for split faces. Reviewers: campbellbarton Differential Revision: https://developer.blender.org/D5603
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/include/ED_mesh.h8
-rw-r--r--source/blender/editors/mesh/editmesh_select.c157
-rw-r--r--source/blender/editors/transform/transform_conversions.c2
3 files changed, 137 insertions, 30 deletions
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 30d4aa10c1b..234f36a587b 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -145,8 +145,12 @@ 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);
+void EDBM_automerge_and_split(struct Scene *scene,
+ struct Object *ob,
+ bool split_edges,
+ bool split_faces,
+ 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 e60934734bc..2273c3fffcf 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -201,6 +201,14 @@ struct EDBMSplitEdge {
float lambda;
};
+struct EDBMSplitBestFaceData {
+ BMEdge **edgenet;
+ int edgenet_len;
+ float average;
+
+ BMFace *r_best_face;
+};
+
struct EDBMSplitEdgeData {
BMesh *bm;
@@ -208,10 +216,49 @@ struct EDBMSplitEdgeData {
float r_lambda;
};
-static bool edbm_automerge_and_split_check_best_face_cb(BMFace *UNUSED(f),
- BMLoop *l_a,
- BMLoop *l_b,
- void *userdata)
+static bool edbm_vert_pair_share_best_splittable_face_cb(BMFace *f,
+ BMLoop *l_a,
+ BMLoop *l_b,
+ void *userdata)
+{
+ struct EDBMSplitBestFaceData *data = userdata;
+ float no[3], min = FLT_MAX, max = -FLT_MAX;
+ copy_v3_v3(no, f->no);
+
+ BMVert *verts[2] = {NULL};
+ BMEdge **e_iter = &data->edgenet[0];
+ for (int i = data->edgenet_len; i--; e_iter++) {
+ BMIter iter;
+ BMVert *v;
+ BM_ITER_ELEM (v, &iter, *e_iter, BM_VERTS_OF_EDGE) {
+ if (!ELEM(v, verts[0], verts[1])) {
+ float dot = dot_v3v3(v->co, no);
+ if (dot < min) {
+ min = dot;
+ }
+ if (dot > max) {
+ max = dot;
+ }
+ }
+ }
+ verts[0] = (*e_iter)->v1;
+ verts[1] = (*e_iter)->v2;
+ }
+
+ float average = max - min;
+ if (average < data->average) {
+ data->average = average;
+ data->r_best_face = f;
+ }
+
+ return false;
+}
+
+/* find the best splittable face between the two vertices. */
+static bool edbm_vert_pair_share_splittable_face_cb(BMFace *f,
+ BMLoop *l_a,
+ BMLoop *l_b,
+ void *userdata)
{
float(*data)[3] = userdata;
float *v_a_co = data[0];
@@ -225,32 +272,71 @@ static bool edbm_automerge_and_split_check_best_face_cb(BMFace *UNUSED(f),
}
}
}
-
return false;
}
-static bool edbm_automerge_check_and_split_faces(BMesh *bm, BMVert *v_src, BMVert *v_dst)
+static void edbm_automerge_weld_linked_wire_edges_into_linked_faces(BMesh *bm,
+ BMVert *v,
+ BMEdge **r_edgenet[],
+ int *r_edgenet_max_len)
{
+ BMEdge **edgenet = *r_edgenet;
+ int edgenet_max_len = *r_edgenet_max_len;
+
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) {
+ BMEdge *e;
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ int edgenet_len = 0;
+ BMVert *v_other = v;
+ while (BM_edge_is_wire(e)) {
+ if (edgenet_max_len == edgenet_len) {
+ edgenet_max_len = (edgenet_max_len + 1) * 2;
+ edgenet = MEM_reallocN(edgenet, (edgenet_max_len) * sizeof(*edgenet));
+ }
+ edgenet[edgenet_len++] = e;
+ v_other = BM_edge_other_vert(e, v_other);
+ BMEdge *e_next = BM_DISK_EDGE_NEXT(e, v_other);
+ if (e_next == e) {
+ /* Vert is wire_endpoint */
+ edgenet_len = 0;
+ break;
+ }
+ e = e_next;
+ }
+
+ BMLoop *dummy;
+ BMFace *best_face;
+ if (edgenet_len == 0) {
+ /* Nothing to do. */
+ continue;
+ }
+ if (edgenet_len == 1) {
float data[2][3];
- copy_v3_v3(data[0], vert_other->co);
- sub_v3_v3v3(data[1], v_dst->co, data[0]);
+ copy_v3_v3(data[0], v_other->co);
+ sub_v3_v3v3(data[1], v->co, data[0]);
+ best_face = BM_vert_pair_shared_face_cb(
+ v_other, v, true, edbm_vert_pair_share_splittable_face_cb, &data, &dummy, &dummy);
+ }
+ else {
+ struct EDBMSplitBestFaceData data = {
+ .edgenet = edgenet,
+ .edgenet_len = edgenet_len,
+ .average = FLT_MAX,
+ .r_best_face = NULL,
+ };
+ BM_vert_pair_shared_face_cb(
+ v_other, v, true, edbm_vert_pair_share_best_splittable_face_cb, &data, &dummy, &dummy);
- 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);
+ best_face = data.r_best_face;
+ }
- if (f) {
- BM_face_split(bm, f, l_a, l_b, NULL, NULL, true);
- return true;
- }
+ if (best_face) {
+ BM_face_split_edgenet(bm, best_face, edgenet, edgenet_len, NULL, NULL);
}
}
- return false;
+
+ *r_edgenet = edgenet;
+ *r_edgenet_max_len = edgenet_max_len;
}
static void ebbm_automerge_and_split_find_duplicate_cb(void *userdata,
@@ -291,8 +377,12 @@ static int edbm_automerge_and_split_sort_cmp_by_keys_cb(const void *index1_v,
}
}
-void EDBM_automerge_and_split(
- Scene *scene, Object *obedit, bool split_edges, bool update, const char hflag)
+void EDBM_automerge_and_split(Scene *scene,
+ Object *obedit,
+ bool split_edges,
+ bool split_faces,
+ bool update,
+ const char hflag)
{
bool ok = false;
@@ -342,8 +432,6 @@ void EDBM_automerge_and_split(
BLI_assert(BM_elem_flag_test(v, BM_ELEM_TAG));
BM_elem_flag_disable(v, BM_ELEM_TAG);
- edbm_automerge_check_and_split_faces(bm, v, v_dst);
-
ok = true;
verts_len--;
}
@@ -369,6 +457,9 @@ void EDBM_automerge_and_split(
}
if (edges_len) {
+ /* Use `e->head.index` to count intersections. */
+ bm->elem_index_dirty &= ~BM_EDGE;
+
/* Create a BVHTree of edges with `dist` as epsilon. */
BVHTree *tree_edges = BLI_bvhtree_new(edges_len, dist, 2, 6);
int i;
@@ -380,7 +471,6 @@ void EDBM_automerge_and_split(
BLI_bvhtree_insert(tree_edges, i, co[0], 2);
- /* Use `e->head.index` to count intersections. */
e->head.index = 0;
}
}
@@ -463,7 +553,7 @@ void EDBM_automerge_and_split(
for (i = 0; i < map_len;
e_map_iter = (void *)&e_map->as_int[i], i += 1 + e_map_iter->cuts_len) {
- /* sort by lambda! */
+ /* sort by lambda. */
BLI_qsort_r(e_map_iter->cuts_index,
e_map_iter->cuts_len,
sizeof(*(e_map->cuts_index)),
@@ -480,7 +570,6 @@ void EDBM_automerge_and_split(
BMVert *v_new = BM_edge_split(bm, e, e->v1, NULL, lambda);
- edbm_automerge_check_and_split_faces(bm, v, v_new);
BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_new, v);
}
}
@@ -495,6 +584,20 @@ void EDBM_automerge_and_split(
BMO_op_exec(bm, &weldop);
+ BMEdge **edgenet = NULL;
+ int edgenet_len_max = 0;
+ if (split_faces) {
+ GHASH_ITER (gh_iter, ghash_targetmap) {
+ v = BLI_ghashIterator_getValue(&gh_iter);
+ BLI_assert(BM_elem_flag_test(v, hflag) || hflag == BM_ELEM_TAG);
+ edbm_automerge_weld_linked_wire_edges_into_linked_faces(bm, v, &edgenet, &edgenet_len_max);
+ }
+ }
+
+ if (edgenet) {
+ MEM_freeN(edgenet);
+ }
+
BMO_op_finish(bm, &findop);
BMO_op_finish(bm, &weldop);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 845ff43bed5..2e328457faf 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -7128,7 +7128,7 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
if (t->scene->toolsettings->automerge & AUTO_MERGE) {
if (t->scene->toolsettings->automerge & AUTO_MERGE_AND_SPLIT) {
- EDBM_automerge_and_split(t->scene, tc->obedit, true, true, hflag);
+ EDBM_automerge_and_split(t->scene, tc->obedit, true, true, true, hflag);
}
else {
EDBM_automerge(t->scene, tc->obedit, true, hflag);