Fix #126633: Multi-resolution modifier un-subdivide freezes

Hidden geometry caused an eternal loop in the un-subdivide internal
logic.

Also fix the un-subdivide operator leaving an invalid selection,
where faces where unselected while all their edges were selected.
This commit is contained in:
Campbell Barton
2024-08-29 14:47:58 +10:00
parent fc1cf66646
commit 2cc395be06

View File

@@ -460,9 +460,10 @@ static bool multires_unsubdivide_single_level(BMesh *bm)
bool valid_tag_found = true;
/* Reset the #BMesh flags as they are used to store data during the un-subdivide process. */
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
/* Reset the #BMesh flags as they are used to store data during the un-subdivide process.
* Un-hiding all faces is important so the entire mesh is handled, see: #126633. */
BM_mesh_elem_hflag_disable_all(
bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT | BM_ELEM_HIDDEN | BM_ELEM_TAG, false);
/* For each disconnected mesh element ID, search if an un-subdivide solution is possible. The
* whole un-subdivide process fails if a single disconnected mesh element fails. */
@@ -927,10 +928,10 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract(
BM_mesh_elem_table_ensure(bm_original_mesh, BM_VERT);
/* Disable all flags. */
BM_mesh_elem_hflag_disable_all(
bm_original_mesh, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
BM_mesh_elem_hflag_disable_all(
bm_original_mesh, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
BM_mesh_elem_hflag_disable_all(bm_original_mesh,
BM_VERT | BM_EDGE | BM_FACE,
BM_ELEM_SELECT | BM_ELEM_HIDDEN | BM_ELEM_TAG,
false);
/* Get the mapping data-layer. */
context->base_to_orig_vmap = static_cast<const int *>(
@@ -1138,6 +1139,10 @@ bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context)
/* Store the new base-mesh as a mesh in context, free bmesh. */
context->base_mesh = BKE_mesh_new_nomain(0, 0, 0, 0);
/* De-select all.
* The user-selection has been overwritten and this selection has not been flushed. */
BM_mesh_elem_hflag_disable_all(bm_base_mesh, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
BMeshToMeshParams bm_to_me_params{};
bm_to_me_params.calc_object_remap = true;
BM_mesh_bm_to_me(nullptr, bm_base_mesh, context->base_mesh, &bm_to_me_params);