From 56076e04920c8d570bf7e234c6987f4f440ee58b Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 1 Sep 2020 12:13:25 -0300 Subject: Fix T80224: Crash after duplicating and hiding vertices while using X Axis Mirror The mirror map can reference a hidden vertex that is currently ignored in the transformation. Thus the mirror element array is not filled. --- source/blender/editors/include/ED_mesh.h | 2 + source/blender/editors/mesh/editmesh_select.c | 2 +- source/blender/editors/mesh/editmesh_tools.c | 6 +- source/blender/editors/mesh/editmesh_utils.c | 71 ++++++++++++---------- source/blender/editors/object/object_vgroup.c | 2 +- .../editors/transform/transform_convert_mesh.c | 2 +- 6 files changed, 48 insertions(+), 37 deletions(-) diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index f2cad1acc84..660e4de09d3 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -59,6 +59,7 @@ void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em, const int axis, const bool use_self, const bool use_select, + const bool respecthide, const bool use_topology, float maxdist, int *r_index); @@ -66,6 +67,7 @@ void EDBM_verts_mirror_cache_begin(struct BMEditMesh *em, const int axis, const bool use_self, const bool use_select, + const bool respecthide, const bool use_toplogy); void EDBM_verts_mirror_apply(struct BMEditMesh *em, const int sel_from, const int sel_to); struct BMVert *EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 1ea25353598..60a09b7eabe 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -110,7 +110,7 @@ void EDBM_select_mirrored(BMEditMesh *em, } } - EDBM_verts_mirror_cache_begin(em, axis, true, true, use_topology); + EDBM_verts_mirror_cache_begin(em, axis, true, true, false, use_topology); if (!extend) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 4de7143682a..279becc1ae9 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -2513,7 +2513,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) /* mirror before smooth */ if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) { - EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology); + EDBM_verts_mirror_cache_begin(em, 0, false, true, false, use_topology); } /* if there is a mirror modifier with clipping, flag the verts that @@ -2658,7 +2658,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) /* Mirror before smooth. */ if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) { - EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology); + EDBM_verts_mirror_cache_begin(em, 0, false, true, false, use_topology); } bool failed_repeat_loop = false; @@ -7600,7 +7600,7 @@ static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op) BMVert *v; int i; - EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, use_topology, thresh, index); + EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, false, use_topology, thresh, index); BM_mesh_elem_table_ensure(bm, BM_VERT); diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 46c63d2e057..e0e369882d2 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -1059,6 +1059,7 @@ static BMVert *cache_mirr_intptr_as_bmvert(const intptr_t *index_lookup, int ind * \param em: Editmesh. * \param use_self: Allow a vertex to point to its self (middle verts). * \param use_select: Restrict to selected verts. + * \param respecthide: Skip hidden vertices. * \param use_topology: Use topology mirror. * \param maxdist: Distance for close point test. * \param r_index: Optional array to write into, as an alternative to a customdata layer @@ -1068,6 +1069,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool use_self, const bool use_select, + const bool respecthide, /* extra args */ const bool use_topology, float maxdist, @@ -1110,6 +1112,10 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, else { tree = BLI_kdtree_3d_new(bm->totvert); BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + if (respecthide && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + continue; + } + BLI_kdtree_3d_insert(tree, i, v->co); } BLI_kdtree_3d_balance(tree); @@ -1118,44 +1124,45 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, #define VERT_INTPTR(_v, _i) (r_index ? &r_index[_i] : BM_ELEM_CD_GET_VOID_P(_v, cd_vmirr_offset)) BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { - BLI_assert(BM_elem_index_get(v) == i); + if (respecthide && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + continue; + } - /* temporary for testing, check for selection */ if (use_select && !BM_elem_flag_test(v, BM_ELEM_SELECT)) { - /* do nothing */ + continue; } - else { - BMVert *v_mirr; - int *idx = VERT_INTPTR(v, i); - if (use_topology) { - v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i); - } - else { - int i_mirr; - float co[3]; - copy_v3_v3(co, v->co); - co[axis] *= -1.0f; - - v_mirr = NULL; - i_mirr = BLI_kdtree_3d_find_nearest(tree, co, NULL); - if (i_mirr != -1) { - BMVert *v_test = BM_vert_at_index(bm, i_mirr); - if (len_squared_v3v3(co, v_test->co) < maxdist_sq) { - v_mirr = v_test; - } + BLI_assert(BM_elem_index_get(v) == i); + BMVert *v_mirr; + int *idx = VERT_INTPTR(v, i); + + if (use_topology) { + v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i); + } + else { + int i_mirr; + float co[3]; + copy_v3_v3(co, v->co); + co[axis] *= -1.0f; + + v_mirr = NULL; + i_mirr = BLI_kdtree_3d_find_nearest(tree, co, NULL); + if (i_mirr != -1) { + BMVert *v_test = BM_vert_at_index(bm, i_mirr); + if (len_squared_v3v3(co, v_test->co) < maxdist_sq) { + v_mirr = v_test; } } + } - if (v_mirr && (use_self || (v_mirr != v))) { - const int i_mirr = BM_elem_index_get(v_mirr); - *idx = i_mirr; - idx = VERT_INTPTR(v_mirr, i_mirr); - *idx = i; - } - else { - *idx = -1; - } + if (v_mirr && (use_self || (v_mirr != v))) { + const int i_mirr = BM_elem_index_get(v_mirr); + *idx = i_mirr; + idx = VERT_INTPTR(v_mirr, i_mirr); + *idx = i; + } + else { + *idx = -1; } } @@ -1173,12 +1180,14 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const int axis, const bool use_self, const bool use_select, + const bool respecthide, const bool use_topology) { EDBM_verts_mirror_cache_begin_ex(em, axis, use_self, use_select, + respecthide, /* extra args */ use_topology, BM_SEARCH_MAXDIST_MIRR, diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 253287c382e..d33c72a5c91 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -2407,7 +2407,7 @@ void ED_vgroup_mirror(Object *ob, goto cleanup; } - EDBM_verts_mirror_cache_begin(em, 0, true, false, use_topology); + EDBM_verts_mirror_cache_begin(em, 0, true, false, false, use_topology); BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index ad426713719..c509cc782e5 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -507,7 +507,7 @@ static void editmesh_mirror_data_calc(BMEditMesh *em, index[a] = MEM_mallocN(totvert * sizeof(*index[a]), __func__); EDBM_verts_mirror_cache_begin_ex( - em, a, false, test_selected_only, use_topology, TRANSFORM_MAXDIST_MIRROR, index[a]); + em, a, false, test_selected_only, true, use_topology, TRANSFORM_MAXDIST_MIRROR, index[a]); flag = TD_MIRROR_X << a; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { -- cgit v1.2.3