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.
This commit is contained in:
parent
eb911610d0
commit
907a718ebe
Notes:
blender-bot
2023-02-14 06:00:46 +01:00
Referenced by issue #80924, Crash edit mesh with proportional editing and symmetry. Referenced by issue #80396, Potential candidates for corrective releases Referenced by issue #80224, Crash after duplicating and hiding vertices while using X Axis Mirror
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
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 {
|
||||
BMVert *v_mirr;
|
||||
int *idx = VERT_INTPTR(v, i);
|
||||
int i_mirr;
|
||||
float co[3];
|
||||
copy_v3_v3(co, v->co);
|
||||
co[axis] *= -1.0f;
|
||||
|
||||
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;
|
||||
}
|
||||
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,
|
||||
|
|
|
@ -2430,7 +2430,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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue