Fix multi-res un-subdivide skipping faces & leaking memory

When unsibdivide ran with quads that share shared two edges,
only one of the loops attached to the vertex would have its grid
initialized (multiple times), skipping the other loops grid calculation
and leaking memory.
This commit is contained in:
Campbell Barton
2024-08-29 14:47:59 +10:00
parent 2cc395be06
commit 86f2c120f2

View File

@@ -711,6 +711,7 @@ static void multires_unsubdivide_extract_single_grid_from_face_edge(
const int grid_size = BKE_ccg_gridsize(context->num_new_levels);
const int unsubdiv_grid_size = grid->grid_size = BKE_ccg_gridsize(context->num_total_levels);
BLI_assert(grid->grid_co == nullptr);
grid->grid_size = unsubdiv_grid_size;
grid->grid_co = static_cast<float(*)[3]>(MEM_calloc_arrayN(
unsubdiv_grid_size * unsubdiv_grid_size, sizeof(float[3]), "grids coordinates"));
@@ -1076,9 +1077,22 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte
faces, corner_verts, base_mesh_face_index, base_mesh_loop_index, corner_x_index);
/* Extract the grid for that loop. */
context->base_mesh_grids[base_mesh_loop_index].grid_index = base_mesh_loop_index;
MultiresUnsubdivideGrid *grid = &context->base_mesh_grids[base_mesh_loop_index];
if (UNLIKELY(grid->grid_co != nullptr)) {
/* It's possible this grid has already been initialized which occurs when quads
* share two edge, while not so common it happens with "Suzanne's" nose,
* see: #126633 & run un-subdivide.
*
* Continue here instead of breaking as logically: quads sharing 2 edges
* will share 3 vertices and those 3 vertices may be attached to any number of quads.
* So in this case, continue scanning instead of breaking out of the loop
* because the `lb` to extract a grid from has not yet been encountered. */
continue;
}
grid->grid_index = base_mesh_loop_index;
multires_unsubdivide_extract_single_grid_from_face_edge(
context, l->f, l->e, !flip_grid, &context->base_mesh_grids[base_mesh_loop_index]);
context, l->f, l->e, !flip_grid, grid);
break;
}