Fix #128820: Mask filter behaves incorrectly with hidden faces
The usage of `hide::node_visible_verts` in this function does not work as intended, as the resulting span is misaligned with the sliced per-node mask data. To fix this issue, this commit adds a similar helper function to copy all hidden vert data and applies changes to all of the node vertices. Pull Request: https://projects.blender.org/blender/blender/pulls/128828
This commit is contained in:
@@ -46,6 +46,23 @@ enum class FilterType {
|
||||
ContrastDecrease = 6,
|
||||
};
|
||||
|
||||
BLI_NOINLINE static void copy_old_hidden_mask_mesh(const Span<int> verts,
|
||||
const Span<bool> hide_vert,
|
||||
const Span<float> mask,
|
||||
const MutableSpan<float> new_mask)
|
||||
{
|
||||
BLI_assert(verts.size() == new_mask.size());
|
||||
if (hide_vert.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const int i : verts.index_range()) {
|
||||
if (hide_vert[verts[i]]) {
|
||||
new_mask[i] = mask[verts[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BLI_NOINLINE static void multiply_add(const Span<float> src,
|
||||
const float factor,
|
||||
const float offset,
|
||||
@@ -109,7 +126,6 @@ struct FilterLocalData {
|
||||
|
||||
static void apply_new_mask_mesh(const Depsgraph &depsgraph,
|
||||
Object &object,
|
||||
const Span<bool> hide_vert,
|
||||
const IndexMask &node_mask,
|
||||
const OffsetIndices<int> node_verts,
|
||||
const Span<float> new_mask,
|
||||
@@ -117,15 +133,13 @@ static void apply_new_mask_mesh(const Depsgraph &depsgraph,
|
||||
{
|
||||
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
|
||||
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
|
||||
threading::EnumerableThreadSpecific<Vector<int>> all_tls;
|
||||
|
||||
Array<bool> node_changed(node_mask.min_array_size(), false);
|
||||
|
||||
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
|
||||
Vector<int> &tls = all_tls.local();
|
||||
const Span<int> verts = hide::node_visible_verts(nodes[i], hide_vert, tls);
|
||||
const Span<int> verts = nodes[i].verts();
|
||||
const Span<float> new_node_mask = new_mask.slice(node_verts[pos]);
|
||||
if (array_utils::indexed_data_equal<float>(mask, verts, new_node_mask)) {
|
||||
if (array_utils::indexed_data_equal<float>(mask, verts, new_mask)) {
|
||||
return;
|
||||
}
|
||||
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
|
||||
@@ -142,6 +156,7 @@ static void smooth_mask_mesh(const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const GroupedSpan<int> vert_to_face_map,
|
||||
const Span<bool> hide_poly,
|
||||
const Span<bool> hide_vert,
|
||||
const Span<float> mask,
|
||||
const bke::pbvh::MeshNode &node,
|
||||
FilterLocalData &tls,
|
||||
@@ -154,12 +169,14 @@ static void smooth_mask_mesh(const OffsetIndices<int> faces,
|
||||
calc_vert_neighbors(faces, corner_verts, vert_to_face_map, hide_poly, verts, neighbors);
|
||||
|
||||
smooth::neighbor_data_average_mesh(mask, neighbors, new_mask);
|
||||
copy_old_hidden_mask_mesh(verts, hide_vert, mask, new_mask);
|
||||
}
|
||||
|
||||
static void sharpen_mask_mesh(const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const GroupedSpan<int> vert_to_face_map,
|
||||
const Span<bool> hide_poly,
|
||||
const Span<bool> hide_vert,
|
||||
const Span<float> mask,
|
||||
const bke::pbvh::MeshNode &node,
|
||||
FilterLocalData &tls,
|
||||
@@ -178,12 +195,14 @@ static void sharpen_mask_mesh(const OffsetIndices<int> faces,
|
||||
smooth::neighbor_data_average_mesh(mask, neighbors, new_mask);
|
||||
|
||||
sharpen_masks(node_mask, new_mask);
|
||||
copy_old_hidden_mask_mesh(verts, hide_vert, mask, new_mask);
|
||||
}
|
||||
|
||||
static void grow_mask_mesh(const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const GroupedSpan<int> vert_to_face_map,
|
||||
const Span<bool> hide_poly,
|
||||
const Span<bool> hide_vert,
|
||||
const Span<float> mask,
|
||||
const bke::pbvh::MeshNode &node,
|
||||
FilterLocalData &tls,
|
||||
@@ -201,12 +220,14 @@ static void grow_mask_mesh(const OffsetIndices<int> faces,
|
||||
new_mask[i] = std::max(mask[neighbor], new_mask[i]);
|
||||
}
|
||||
}
|
||||
copy_old_hidden_mask_mesh(verts, hide_vert, mask, new_mask);
|
||||
}
|
||||
|
||||
static void shrink_mask_mesh(const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const GroupedSpan<int> vert_to_face_map,
|
||||
const Span<bool> hide_poly,
|
||||
const Span<bool> hide_vert,
|
||||
const Span<float> mask,
|
||||
const bke::pbvh::MeshNode &node,
|
||||
FilterLocalData &tls,
|
||||
@@ -224,6 +245,7 @@ static void shrink_mask_mesh(const OffsetIndices<int> faces,
|
||||
new_mask[i] = std::min(mask[neighbor], new_mask[i]);
|
||||
}
|
||||
}
|
||||
copy_old_hidden_mask_mesh(verts, hide_vert, mask, new_mask);
|
||||
}
|
||||
|
||||
static bool increase_contrast_mask_mesh(const Depsgraph &depsgraph,
|
||||
@@ -240,6 +262,7 @@ static bool increase_contrast_mask_mesh(const Depsgraph &depsgraph,
|
||||
tls.new_mask.resize(verts.size());
|
||||
const MutableSpan<float> new_mask = tls.new_mask;
|
||||
mask_increase_contrast(node_mask, new_mask);
|
||||
copy_old_hidden_mask_mesh(verts, hide_vert, mask, new_mask);
|
||||
|
||||
if (node_mask == new_mask.as_span()) {
|
||||
return false;
|
||||
@@ -265,6 +288,7 @@ static bool decrease_contrast_mask_mesh(const Depsgraph &depsgraph,
|
||||
tls.new_mask.resize(verts.size());
|
||||
const MutableSpan<float> new_mask = tls.new_mask;
|
||||
mask_decrease_contrast(node_mask, new_mask);
|
||||
copy_old_hidden_mask_mesh(verts, hide_vert, mask, new_mask);
|
||||
|
||||
if (node_mask == new_mask.as_span()) {
|
||||
return false;
|
||||
@@ -721,13 +745,13 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
|
||||
corner_verts,
|
||||
vert_to_face_map,
|
||||
hide_poly,
|
||||
hide_vert,
|
||||
mask.span,
|
||||
nodes[i],
|
||||
tls,
|
||||
new_masks.as_mutable_span().slice(node_offsets[pos]));
|
||||
});
|
||||
apply_new_mask_mesh(
|
||||
*depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span);
|
||||
apply_new_mask_mesh(*depsgraph, ob, node_mask, node_offsets, new_masks, mask.span);
|
||||
break;
|
||||
}
|
||||
case FilterType::Sharpen: {
|
||||
@@ -737,13 +761,13 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
|
||||
corner_verts,
|
||||
vert_to_face_map,
|
||||
hide_poly,
|
||||
hide_vert,
|
||||
mask.span,
|
||||
nodes[i],
|
||||
tls,
|
||||
new_masks.as_mutable_span().slice(node_offsets[pos]));
|
||||
});
|
||||
apply_new_mask_mesh(
|
||||
*depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span);
|
||||
apply_new_mask_mesh(*depsgraph, ob, node_mask, node_offsets, new_masks, mask.span);
|
||||
break;
|
||||
}
|
||||
case FilterType::Grow: {
|
||||
@@ -753,13 +777,13 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
|
||||
corner_verts,
|
||||
vert_to_face_map,
|
||||
hide_poly,
|
||||
hide_vert,
|
||||
mask.span,
|
||||
nodes[i],
|
||||
tls,
|
||||
new_masks.as_mutable_span().slice(node_offsets[pos]));
|
||||
});
|
||||
apply_new_mask_mesh(
|
||||
*depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span);
|
||||
apply_new_mask_mesh(*depsgraph, ob, node_mask, node_offsets, new_masks, mask.span);
|
||||
break;
|
||||
}
|
||||
case FilterType::Shrink: {
|
||||
@@ -769,13 +793,13 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
|
||||
corner_verts,
|
||||
vert_to_face_map,
|
||||
hide_poly,
|
||||
hide_vert,
|
||||
mask.span,
|
||||
nodes[i],
|
||||
tls,
|
||||
new_masks.as_mutable_span().slice(node_offsets[pos]));
|
||||
});
|
||||
apply_new_mask_mesh(
|
||||
*depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span);
|
||||
apply_new_mask_mesh(*depsgraph, ob, node_mask, node_offsets, new_masks, mask.span);
|
||||
break;
|
||||
}
|
||||
case FilterType::ContrastIncrease: {
|
||||
|
||||
Reference in New Issue
Block a user