From 495a6ec6ccb935418967913d48928396b7e20c13 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Thu, 9 Mar 2023 01:31:46 -0300 Subject: [PATCH] Fix #105579: weld modifier crashes when merging n-gons The correction bbc6bb3468 was still wrong because there it was disregarded that `vert_ctx_len` does not necessarily indicate merges in the same polygon. Therefore, it is not safe to rely on `vert_ctx_len` to count possible new polygons. NOTE: It might be worth preempting part of the `weld_poly_split_recursive` logic to identify what the new polygons are in advance. But this can be left for a future refactor. --- .../geometry/intern/mesh_merge_by_distance.cc | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/source/blender/geometry/intern/mesh_merge_by_distance.cc b/source/blender/geometry/intern/mesh_merge_by_distance.cc index f0f1e02ae1d..b9295a8344d 100644 --- a/source/blender/geometry/intern/mesh_merge_by_distance.cc +++ b/source/blender/geometry/intern/mesh_merge_by_distance.cc @@ -795,8 +795,6 @@ static void weld_poly_loop_ctx_alloc(Span mpoly, const int loopstart = mp.loopstart; const int totloop = mp.totloop; - int vert_ctx_len = 0; - int prev_wloop_len = wloop_len; for (const int i_loop : mloop.index_range().slice(loopstart, totloop)) { int v = mloop[i_loop].v; @@ -805,9 +803,6 @@ static void weld_poly_loop_ctx_alloc(Span mpoly, int e_dest = edge_dest_map[e]; bool is_vert_ctx = v_dest != OUT_OF_CONTEXT; bool is_edge_ctx = e_dest != OUT_OF_CONTEXT; - if (is_vert_ctx) { - vert_ctx_len++; - } if (is_vert_ctx || is_edge_ctx) { WeldLoop wl{}; wl.vert = is_vert_ctx ? v_dest : v; @@ -835,9 +830,11 @@ static void weld_poly_loop_ctx_alloc(Span mpoly, wpoly.append(wp); poly_map[i] = wpoly_len++; - if (totloop > 5 && vert_ctx_len > 1) { - /* Each untouched vertex pair is a candidate for a new polygon. */ - int max_new = std::min(vert_ctx_len, (totloop - vert_ctx_len) / 2); + if (totloop > 5 && loops_len > 1) { + /* We could be smarter here and actually count how many new polygons will be created. + * But counting this can be inefficient as it depends on the number of non-consecutive + * self polygon merges. For now just estimate a maximum value. */ + int max_new = std::min((totloop / 3), loops_len) - 1; maybe_new_poly += max_new; CLAMP_MIN(max_ctx_poly_len, totloop); }