mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Fix #158858: Multires modifier unsubdivide is broken
Regression in [0] caused by failing to find geometry in the last
topological step being treated as an error.
The last X/Y steps don't need to be performed so skip them
as well as the error checking.
[0]: 02483b533c
Ref !158881
This commit is contained in:
parent
328a73b294
commit
a690120c46
1 changed files with 55 additions and 43 deletions
|
|
@ -737,9 +737,6 @@ static bool multires_unsubdivide_extract_single_grid_from_face_edge(
|
|||
initial_edge_y = edge_temp;
|
||||
}
|
||||
|
||||
int grid_x = 0;
|
||||
int grid_y = 0;
|
||||
|
||||
BMVert *current_vertex_x = initial_vertex;
|
||||
BMEdge *edge_x = initial_edge_x;
|
||||
|
||||
|
|
@ -750,17 +747,18 @@ static bool multires_unsubdivide_extract_single_grid_from_face_edge(
|
|||
BMFace *current_face = f1;
|
||||
BMFace *grid_face = f1;
|
||||
|
||||
const bool has_original_grid_data = context->num_original_levels > 0;
|
||||
|
||||
/* If the data is going to be extracted from the already existing grids, there is no need to go
|
||||
* to the last vertex of the iteration as that coordinate is also included in the grids
|
||||
* corresponding to the loop of the face of the previous iteration. */
|
||||
int grid_iteration_max_steps = grid_size;
|
||||
if (context->num_original_levels > 0) {
|
||||
grid_iteration_max_steps = grid_size - 1;
|
||||
}
|
||||
const int grid_iteration_max_steps = grid_size - (has_original_grid_data ? 1 : 0);
|
||||
const int grid_iteration_last_step = grid_iteration_max_steps - 1;
|
||||
|
||||
/* Iterate over the mesh vertices in a grid pattern using the axis defined by the two initial
|
||||
* edges. */
|
||||
while (grid_y < grid_iteration_max_steps) {
|
||||
for (const int grid_y : IndexRange(grid_iteration_max_steps)) {
|
||||
const bool grid_y_has_next = grid_y != grid_iteration_last_step;
|
||||
|
||||
grid_face = current_face;
|
||||
|
||||
|
|
@ -769,53 +767,67 @@ static bool multires_unsubdivide_extract_single_grid_from_face_edge(
|
|||
return false;
|
||||
}
|
||||
|
||||
while (grid_x < grid_iteration_max_steps) {
|
||||
if (context->num_original_levels == 0) {
|
||||
/* If there were no grids on the original mesh, extract the data directly from the
|
||||
* vertices. */
|
||||
for (const int grid_x : IndexRange(grid_iteration_max_steps)) {
|
||||
/* Don't step into the next edge at the end,
|
||||
* since failing to walk past the end is *not* an error. */
|
||||
const bool grid_x_has_next = grid_x != grid_iteration_last_step;
|
||||
if (has_original_grid_data) {
|
||||
/* If there were grids in the original mesh,
|
||||
* extract the data from the grids. */
|
||||
store_grid_data(context, grid, current_vertex_x, grid_face, grid_x, grid_y);
|
||||
}
|
||||
else {
|
||||
/* If there were no grids on the original mesh,
|
||||
* extract the data directly from the vertices. */
|
||||
store_vertex_data(grid, current_vertex_x, grid_x, grid_y);
|
||||
}
|
||||
if (grid_x_has_next) {
|
||||
edge_x = edge_step(current_vertex_x, edge_x, ¤t_vertex_x);
|
||||
if (edge_x == nullptr) [[unlikely]] {
|
||||
return false;
|
||||
}
|
||||
if (has_original_grid_data) {
|
||||
grid_face = face_step(edge_x, grid_face);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* If there were grids in the original mesh, extract the data from the grids and iterate
|
||||
* over the faces. */
|
||||
store_grid_data(context, grid, current_vertex_x, grid_face, grid_x, grid_y);
|
||||
edge_x = edge_step(current_vertex_x, edge_x, ¤t_vertex_x);
|
||||
if (edge_x == nullptr) [[unlikely]] {
|
||||
return false;
|
||||
/* Clear as a signal not to reuse, allow dead assignments. */
|
||||
edge_x = nullptr;
|
||||
grid_face = nullptr;
|
||||
UNUSED_VARS(edge_x, grid_face);
|
||||
}
|
||||
}
|
||||
|
||||
if (grid_y_has_next) {
|
||||
if (edge_y == nullptr) [[unlikely]] {
|
||||
return false;
|
||||
}
|
||||
edge_y = edge_step(current_vertex_y, edge_y, ¤t_vertex_y);
|
||||
current_vertex_x = current_vertex_y;
|
||||
|
||||
/* Get the next edge_x to extract the next row of the grid. This needs to be done because
|
||||
* there may be two edges connected to current_vertex_x that belong to two different grids.
|
||||
*/
|
||||
BMIter iter;
|
||||
BMEdge *ed;
|
||||
edge_x = nullptr;
|
||||
BM_ITER_ELEM (ed, &iter, current_vertex_x, BM_EDGES_OF_VERT) {
|
||||
if (ed != prev_edge_y && BM_edge_in_face(ed, current_face)) {
|
||||
edge_x = ed;
|
||||
break;
|
||||
}
|
||||
grid_face = face_step(edge_x, grid_face);
|
||||
}
|
||||
/* May be null, check on next access (if this isn't the end of iteration). */
|
||||
current_face = edge_x ? face_step(edge_x, current_face) : nullptr;
|
||||
|
||||
grid_x++;
|
||||
prev_edge_y = edge_y;
|
||||
}
|
||||
grid_x = 0;
|
||||
|
||||
if (edge_y == nullptr) [[unlikely]] {
|
||||
return false;
|
||||
else {
|
||||
/* Clear as a signal not to reuse, allow dead assignments. */
|
||||
edge_y = nullptr;
|
||||
grid_face = nullptr;
|
||||
UNUSED_VARS(edge_x, grid_face);
|
||||
}
|
||||
edge_y = edge_step(current_vertex_y, edge_y, ¤t_vertex_y);
|
||||
current_vertex_x = current_vertex_y;
|
||||
|
||||
/* Get the next edge_x to extract the next row of the grid. This needs to be done because there
|
||||
* may be two edges connected to current_vertex_x that belong to two different grids. */
|
||||
BMIter iter;
|
||||
BMEdge *ed;
|
||||
edge_x = nullptr;
|
||||
BM_ITER_ELEM (ed, &iter, current_vertex_x, BM_EDGES_OF_VERT) {
|
||||
if (ed != prev_edge_y && BM_edge_in_face(ed, current_face)) {
|
||||
edge_x = ed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* May be null, check on next access (if this isn't the end of iteration). */
|
||||
current_face = edge_x ? face_step(edge_x, current_face) : nullptr;
|
||||
|
||||
prev_edge_y = edge_y;
|
||||
grid_y++;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue