Fix: Sculpt: Smooth brush crash and node data iteration issues

IndexMask iteration from 347ec1acd7 was incorrect
in the cases where we stored temporary data in contiguous sections
per PBVH node. We now call `.local()` once per PBVH node. If that
becomes a bottleneck it's avoidable, for now it's simpler though.
This commit is contained in:
Hans Goudey
2024-08-30 09:57:58 -04:00
parent 870d664e31
commit b4287a4902
6 changed files with 456 additions and 528 deletions

View File

@@ -168,49 +168,45 @@ static void do_relax_face_sets_brush_mesh(const Depsgraph &depsgraph,
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<MeshLocalData> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
MeshLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_factors_faces(depsgraph,
brush,
positions_eval,
vert_normals,
strength,
relax_face_sets,
object,
nodes[i],
tls,
factors.as_mutable_span().slice(node_vert_offsets[i]));
});
calc_factors_faces(depsgraph,
brush,
positions_eval,
vert_normals,
strength,
relax_face_sets,
object,
nodes[i],
tls,
factors.as_mutable_span().slice(node_vert_offsets[pos]));
});
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
MeshLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_faces(
positions_eval,
vert_normals,
faces,
corner_verts,
ss.vert_to_face_map,
ss.vertex_info.boundary,
ss.face_sets,
hide_poly,
relax_face_sets,
bke::pbvh::node_unique_verts(nodes[i]),
factors.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
});
smooth::calc_relaxed_translations_faces(
positions_eval,
vert_normals,
faces,
corner_verts,
ss.vert_to_face_map,
ss.vertex_info.boundary,
ss.face_sets,
hide_poly,
relax_face_sets,
bke::pbvh::node_unique_verts(nodes[i]),
factors.as_span().slice(node_vert_offsets[pos]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[pos]));
});
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
apply_positions_faces(depsgraph,
sd,
positions_eval,
bke::pbvh::node_unique_verts(nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
translations.as_mutable_span().slice(node_vert_offsets[pos]),
positions_orig);
});
}
@@ -294,48 +290,44 @@ static void do_relax_face_sets_brush_grids(const Depsgraph &depsgraph,
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<GridLocalData> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
GridLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_factors_grids(depsgraph,
brush,
corner_verts,
faces,
nodes[i],
strength,
relax_face_sets,
object,
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
factors.as_mutable_span().slice(node_vert_offsets[i]));
});
calc_factors_grids(depsgraph,
brush,
corner_verts,
faces,
nodes[i],
strength,
relax_face_sets,
object,
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
factors.as_mutable_span().slice(node_vert_offsets[pos]));
});
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
GridLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_grids(
subdiv_ccg,
faces,
corner_verts,
ss.face_sets,
ss.vert_to_face_map,
ss.vertex_info.boundary,
bke::pbvh::node_grid_indices(nodes[i]),
relax_face_sets,
factors.as_span().slice(node_vert_offsets[i]),
current_positions.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
});
smooth::calc_relaxed_translations_grids(
subdiv_ccg,
faces,
corner_verts,
ss.face_sets,
ss.vert_to_face_map,
ss.vertex_info.boundary,
bke::pbvh::node_grid_indices(nodes[i]),
relax_face_sets,
factors.as_span().slice(node_vert_offsets[pos]),
current_positions.as_span().slice(node_vert_offsets[pos]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[pos]));
});
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
apply_positions_grids(sd,
bke::pbvh::node_grid_indices(nodes[i]),
object,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
translations.as_mutable_span().slice(node_vert_offsets[i]));
current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
translations.as_mutable_span().slice(node_vert_offsets[pos]));
});
}
@@ -396,40 +388,36 @@ static void do_relax_face_sets_brush_bmesh(const Depsgraph &depsgraph,
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<BMeshLocalData> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
BMeshLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_factors_bmesh(depsgraph,
object,
brush,
nodes[i],
strength,
relax_face_sets,
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
factors.as_mutable_span().slice(node_vert_offsets[i]));
});
calc_factors_bmesh(depsgraph,
object,
brush,
nodes[i],
strength,
relax_face_sets,
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
factors.as_mutable_span().slice(node_vert_offsets[pos]));
});
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
BMeshLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_bmesh(
BKE_pbvh_bmesh_node_unique_verts(&nodes[i]),
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
relax_face_sets,
factors.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
});
smooth::calc_relaxed_translations_bmesh(
BKE_pbvh_bmesh_node_unique_verts(&nodes[i]),
current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
relax_face_sets,
factors.as_span().slice(node_vert_offsets[pos]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[pos]));
});
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
apply_positions_bmesh(sd,
BKE_pbvh_bmesh_node_unique_verts(&nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
current_positions.as_span().slice(node_vert_offsets[i]));
translations.as_mutable_span().slice(node_vert_offsets[pos]),
current_positions.as_span().slice(node_vert_offsets[pos]));
});
}
@@ -501,46 +489,42 @@ static void do_topology_relax_brush_mesh(const Depsgraph &depsgraph,
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<MeshLocalData> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
MeshLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_topology_relax_factors_faces(depsgraph,
brush,
strength,
object,
nodes[i],
tls,
factors.as_mutable_span().slice(node_vert_offsets[i]));
});
calc_topology_relax_factors_faces(depsgraph,
brush,
strength,
object,
nodes[i],
tls,
factors.as_mutable_span().slice(node_vert_offsets[pos]));
});
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
MeshLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_faces(
positions_eval,
vert_normals,
faces,
corner_verts,
ss.vert_to_face_map,
ss.vertex_info.boundary,
ss.face_sets,
hide_poly,
false,
bke::pbvh::node_unique_verts(nodes[i]),
factors.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
});
smooth::calc_relaxed_translations_faces(
positions_eval,
vert_normals,
faces,
corner_verts,
ss.vert_to_face_map,
ss.vertex_info.boundary,
ss.face_sets,
hide_poly,
false,
bke::pbvh::node_unique_verts(nodes[i]),
factors.as_span().slice(node_vert_offsets[pos]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[pos]));
});
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
apply_positions_faces(depsgraph,
sd,
positions_eval,
bke::pbvh::node_unique_verts(nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
translations.as_mutable_span().slice(node_vert_offsets[pos]),
positions_orig);
});
}
@@ -613,46 +597,42 @@ static void do_topology_relax_brush_grids(const Depsgraph &depsgraph,
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<GridLocalData> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
GridLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_topology_relax_factors_grids(
depsgraph,
brush,
strength,
object,
nodes[i],
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
factors.as_mutable_span().slice(node_vert_offsets[i]));
});
calc_topology_relax_factors_grids(
depsgraph,
brush,
strength,
object,
nodes[i],
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
factors.as_mutable_span().slice(node_vert_offsets[pos]));
});
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
GridLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_grids(
subdiv_ccg,
faces,
corner_verts,
ss.face_sets,
ss.vert_to_face_map,
ss.vertex_info.boundary,
bke::pbvh::node_grid_indices(nodes[i]),
false,
factors.as_span().slice(node_vert_offsets[i]),
current_positions.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
});
smooth::calc_relaxed_translations_grids(
subdiv_ccg,
faces,
corner_verts,
ss.face_sets,
ss.vert_to_face_map,
ss.vertex_info.boundary,
bke::pbvh::node_grid_indices(nodes[i]),
false,
factors.as_span().slice(node_vert_offsets[pos]),
current_positions.as_span().slice(node_vert_offsets[pos]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[pos]));
});
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
apply_positions_grids(sd,
bke::pbvh::node_grid_indices(nodes[i]),
object,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
translations.as_mutable_span().slice(node_vert_offsets[i]));
current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
translations.as_mutable_span().slice(node_vert_offsets[pos]));
});
}
@@ -715,40 +695,36 @@ static void do_topology_relax_brush_bmesh(const Depsgraph &depsgraph,
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<BMeshLocalData> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
BMeshLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_topology_relax_factors_bmesh(
depsgraph,
object,
brush,
nodes[i],
strength,
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
factors.as_mutable_span().slice(node_vert_offsets[i]));
});
calc_topology_relax_factors_bmesh(
depsgraph,
object,
brush,
nodes[i],
strength,
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
factors.as_mutable_span().slice(node_vert_offsets[pos]));
});
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
BMeshLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_bmesh(
BKE_pbvh_bmesh_node_unique_verts(&nodes[i]),
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
false,
factors.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
});
smooth::calc_relaxed_translations_bmesh(
BKE_pbvh_bmesh_node_unique_verts(&nodes[i]),
current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
false,
factors.as_span().slice(node_vert_offsets[pos]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[pos]));
});
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
apply_positions_bmesh(sd,
BKE_pbvh_bmesh_node_unique_verts(&nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
current_positions.as_span().slice(node_vert_offsets[i]));
translations.as_mutable_span().slice(node_vert_offsets[pos]),
current_positions.as_span().slice(node_vert_offsets[pos]));
});
}
/** \} */

View File

@@ -132,41 +132,37 @@ BLI_NOINLINE static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
* are updated in parallel. Without this there would be non-threadsafe access to changing
* positions in other bke::pbvh::Tree nodes. */
for (const float strength : iteration_strengths(brush_strength)) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.vert_neighbors.resize(verts.size());
calc_vert_neighbors_interior(faces,
corner_verts,
ss.vert_to_face_map,
ss.vertex_info.boundary,
hide_poly,
verts,
tls.vert_neighbors);
smooth::neighbor_data_average_mesh_check_loose(
positions_eval,
verts,
tls.vert_neighbors,
new_positions.as_mutable_span().slice(node_vert_offsets[i]));
});
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.vert_neighbors.resize(verts.size());
calc_vert_neighbors_interior(faces,
corner_verts,
ss.vert_to_face_map,
ss.vertex_info.boundary,
hide_poly,
verts,
tls.vert_neighbors);
smooth::neighbor_data_average_mesh_check_loose(
positions_eval,
verts,
tls.vert_neighbors,
new_positions.as_mutable_span().slice(node_vert_offsets[pos]));
});
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
apply_positions_faces(depsgraph,
sd,
brush,
positions_eval,
vert_normals,
nodes[i],
strength,
object,
tls,
new_positions.as_span().slice(node_vert_offsets[i]),
positions_orig);
});
apply_positions_faces(depsgraph,
sd,
brush,
positions_eval,
vert_normals,
nodes[i],
strength,
object,
tls,
new_positions.as_span().slice(node_vert_offsets[pos]),
positions_orig);
});
}
}

View File

@@ -147,34 +147,30 @@ static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
for (const float strength : iteration_strengths(brush_strength)) {
/* Calculate new masks into a separate array to avoid non-threadsafe access of values from
* neighboring nodes. */
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_smooth_masks_faces(faces,
corner_verts,
ss.vert_to_face_map,
hide_poly,
bke::pbvh::node_unique_verts(nodes[i]),
mask.span.as_span(),
tls,
new_masks.as_mutable_span().slice(node_vert_offsets[i]));
});
calc_smooth_masks_faces(faces,
corner_verts,
ss.vert_to_face_map,
hide_poly,
bke::pbvh::node_unique_verts(nodes[i]),
mask.span.as_span(),
tls,
new_masks.as_mutable_span().slice(node_vert_offsets[pos]));
});
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
apply_masks_faces(depsgraph,
brush,
positions_eval,
vert_normals,
nodes[i],
strength,
object,
tls,
new_masks.as_span().slice(node_vert_offsets[i]),
mask.span);
});
apply_masks_faces(depsgraph,
brush,
positions_eval,
vert_normals,
nodes[i],
strength,
object,
tls,
new_masks.as_span().slice(node_vert_offsets[pos]),
mask.span);
});
}
mask.finish();

View File

@@ -73,99 +73,89 @@ BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph
Array<float> all_factors(node_offsets.total_size());
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
fill_factor_from_hide_and_mask(mesh, verts, factors);
filter_region_clip_factors(ss, positions_eval, verts, factors);
if (brush.flag & BRUSH_FRONTFACE) {
calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
}
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
fill_factor_from_hide_and_mask(mesh, verts, factors);
filter_region_clip_factors(ss, positions_eval, verts, factors);
if (brush.flag & BRUSH_FRONTFACE) {
calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
}
tls.distances.resize(verts.size());
const MutableSpan<float> distances = tls.distances;
calc_brush_distances(
ss, positions_eval, verts, eBrushFalloffShape(brush.falloff_shape), distances);
filter_distances_with_radius(cache.radius, distances, factors);
apply_hardness_to_distances(cache, distances);
calc_brush_strength_factors(cache, brush, distances, factors);
tls.distances.resize(verts.size());
const MutableSpan<float> distances = tls.distances;
calc_brush_distances(
ss, positions_eval, verts, eBrushFalloffShape(brush.falloff_shape), distances);
filter_distances_with_radius(cache.radius, distances, factors);
apply_hardness_to_distances(cache, distances);
calc_brush_strength_factors(cache, brush, distances, factors);
auto_mask::calc_vert_factors(
depsgraph, object, cache.automasking.get(), nodes[i], verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, cache.automasking.get(), nodes[i], verts, factors);
calc_brush_texture_factors(ss, brush, positions_eval, verts, factors);
calc_brush_texture_factors(ss, brush, positions_eval, verts, factors);
scale_factors(factors, cache.bstrength);
clamp_factors(factors);
});
scale_factors(factors, cache.bstrength);
clamp_factors(factors);
});
for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
tls.vert_neighbors.resize(verts.size());
calc_vert_neighbors(
faces, corner_verts, ss.vert_to_face_map, hide_poly, verts, tls.vert_neighbors);
tls.vert_neighbors.resize(verts.size());
calc_vert_neighbors(
faces, corner_verts, ss.vert_to_face_map, hide_poly, verts, tls.vert_neighbors);
tls.average_positions.resize(verts.size());
const MutableSpan<float3> average_positions = tls.average_positions;
smooth::neighbor_data_average_mesh(positions_eval, tls.vert_neighbors, average_positions);
tls.average_positions.resize(verts.size());
const MutableSpan<float3> average_positions = tls.average_positions;
smooth::neighbor_data_average_mesh(positions_eval, tls.vert_neighbors, average_positions);
tls.laplacian_disp.resize(verts.size());
const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
tls.translations.resize(verts.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_laplacian_step(positions,
orig_data.positions,
average_positions,
alpha,
laplacian_disp,
translations);
scale_translations(translations, factors);
tls.laplacian_disp.resize(verts.size());
const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
tls.translations.resize(verts.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_laplacian_step(
positions, orig_data.positions, average_positions, alpha, laplacian_disp, translations);
scale_translations(translations, factors);
scatter_data_mesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
scatter_data_mesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
});
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
});
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const MutableSpan<float3> laplacian_disp = gather_data_mesh(
all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
const MutableSpan<float3> laplacian_disp = gather_data_mesh(
all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
tls.vert_neighbors.resize(verts.size());
calc_vert_neighbors(
faces, corner_verts, ss.vert_to_face_map, hide_poly, verts, tls.vert_neighbors);
tls.vert_neighbors.resize(verts.size());
calc_vert_neighbors(
faces, corner_verts, ss.vert_to_face_map, hide_poly, verts, tls.vert_neighbors);
tls.average_positions.resize(verts.size());
const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
smooth::neighbor_data_average_mesh(
all_laplacian_disp.as_span(), tls.vert_neighbors, average_laplacian_disps);
tls.average_positions.resize(verts.size());
const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
smooth::neighbor_data_average_mesh(
all_laplacian_disp.as_span(), tls.vert_neighbors, average_laplacian_disps);
tls.translations.resize(verts.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_displace_step(
laplacian_disp, average_laplacian_disps, beta, translations);
scale_translations(translations, factors);
tls.translations.resize(verts.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_displace_step(
laplacian_disp, average_laplacian_disps, beta, translations);
scale_translations(translations, factors);
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
});
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
});
}
}
@@ -192,92 +182,82 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids(
Array<float> all_factors(node_offsets.total_size());
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
filter_region_clip_factors(ss, positions, factors);
if (brush.flag & BRUSH_FRONTFACE) {
calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
}
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
filter_region_clip_factors(ss, positions, factors);
if (brush.flag & BRUSH_FRONTFACE) {
calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
}
tls.distances.resize(positions.size());
const MutableSpan<float> distances = tls.distances;
calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
filter_distances_with_radius(cache.radius, distances, factors);
apply_hardness_to_distances(cache, distances);
calc_brush_strength_factors(cache, brush, distances, factors);
tls.distances.resize(positions.size());
const MutableSpan<float> distances = tls.distances;
calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
filter_distances_with_radius(cache.radius, distances, factors);
apply_hardness_to_distances(cache, distances);
calc_brush_strength_factors(cache, brush, distances, factors);
auto_mask::calc_grids_factors(
depsgraph, object, cache.automasking.get(), nodes[i], grids, factors);
auto_mask::calc_grids_factors(
depsgraph, object, cache.automasking.get(), nodes[i], grids, factors);
calc_brush_texture_factors(ss, brush, positions, factors);
calc_brush_texture_factors(ss, brush, positions, factors);
scale_factors(factors, cache.bstrength);
clamp_factors(factors);
});
scale_factors(factors, cache.bstrength);
clamp_factors(factors);
});
for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
tls.average_positions.resize(positions.size());
const MutableSpan<float3> average_positions = tls.average_positions;
smooth::neighbor_position_average_grids(subdiv_ccg, grids, average_positions);
tls.average_positions.resize(positions.size());
const MutableSpan<float3> average_positions = tls.average_positions;
smooth::neighbor_position_average_grids(subdiv_ccg, grids, average_positions);
tls.laplacian_disp.resize(positions.size());
const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
tls.translations.resize(positions.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_laplacian_step(positions,
orig_data.positions,
average_positions,
alpha,
laplacian_disp,
translations);
scale_translations(translations, factors);
tls.laplacian_disp.resize(positions.size());
const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
tls.translations.resize(positions.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_laplacian_step(
positions, orig_data.positions, average_positions, alpha, laplacian_disp, translations);
scale_translations(translations, factors);
scatter_data_grids(subdiv_ccg, laplacian_disp.as_span(), grids, all_laplacian_disp);
scatter_data_grids(subdiv_ccg, laplacian_disp.as_span(), grids, all_laplacian_disp);
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, grids, subdiv_ccg);
});
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, grids, subdiv_ccg);
});
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const MutableSpan<float3> laplacian_disp = gather_data_grids(
subdiv_ccg, all_laplacian_disp.as_span(), grids, tls.laplacian_disp);
const MutableSpan<float3> laplacian_disp = gather_data_grids(
subdiv_ccg, all_laplacian_disp.as_span(), grids, tls.laplacian_disp);
tls.average_positions.resize(positions.size());
const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
smooth::average_data_grids(
subdiv_ccg, all_laplacian_disp.as_span(), grids, average_laplacian_disps);
tls.average_positions.resize(positions.size());
const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
smooth::average_data_grids(
subdiv_ccg, all_laplacian_disp.as_span(), grids, average_laplacian_disps);
tls.translations.resize(positions.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_displace_step(
laplacian_disp, average_laplacian_disps, beta, translations);
scale_translations(translations, factors);
tls.translations.resize(positions.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_displace_step(
laplacian_disp, average_laplacian_disps, beta, translations);
scale_translations(translations, factors);
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, grids, subdiv_ccg);
});
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, grids, subdiv_ccg);
});
}
}
@@ -302,89 +282,83 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh(
Array<float> all_factors(node_offsets.total_size());
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
fill_factor_from_hide_and_mask(*ss.bm, verts, factors);
filter_region_clip_factors(ss, positions, factors);
if (brush.flag & BRUSH_FRONTFACE) {
calc_front_face(cache.view_normal_symm, verts, factors);
}
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
fill_factor_from_hide_and_mask(*ss.bm, verts, factors);
filter_region_clip_factors(ss, positions, factors);
if (brush.flag & BRUSH_FRONTFACE) {
calc_front_face(cache.view_normal_symm, verts, factors);
}
tls.distances.resize(positions.size());
const MutableSpan<float> distances = tls.distances;
calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
filter_distances_with_radius(cache.radius, distances, factors);
apply_hardness_to_distances(cache, distances);
calc_brush_strength_factors(cache, brush, distances, factors);
tls.distances.resize(positions.size());
const MutableSpan<float> distances = tls.distances;
calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
filter_distances_with_radius(cache.radius, distances, factors);
apply_hardness_to_distances(cache, distances);
calc_brush_strength_factors(cache, brush, distances, factors);
auto_mask::calc_vert_factors(
depsgraph, object, cache.automasking.get(), nodes[i], verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, cache.automasking.get(), nodes[i], verts, factors);
calc_brush_texture_factors(ss, brush, positions, factors);
calc_brush_texture_factors(ss, brush, positions, factors);
scale_factors(factors, cache.bstrength);
clamp_factors(factors);
});
scale_factors(factors, cache.bstrength);
clamp_factors(factors);
});
for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
Array<float3> orig_positions(verts.size());
Array<float3> orig_normals(verts.size());
orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
Array<float3> orig_positions(verts.size());
Array<float3> orig_normals(verts.size());
orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
tls.average_positions.resize(positions.size());
const MutableSpan<float3> average_positions = tls.average_positions;
smooth::neighbor_position_average_bmesh(verts, average_positions);
tls.average_positions.resize(positions.size());
const MutableSpan<float3> average_positions = tls.average_positions;
smooth::neighbor_position_average_bmesh(verts, average_positions);
tls.laplacian_disp.resize(positions.size());
const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
tls.translations.resize(positions.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_laplacian_step(
positions, orig_positions, average_positions, alpha, laplacian_disp, translations);
scale_translations(translations, factors);
tls.laplacian_disp.resize(positions.size());
const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
tls.translations.resize(positions.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_laplacian_step(
positions, orig_positions, average_positions, alpha, laplacian_disp, translations);
scale_translations(translations, factors);
scatter_data_vert_bmesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
scatter_data_vert_bmesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, verts);
});
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, verts);
});
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const MutableSpan<float3> laplacian_disp = gather_data_vert_bmesh(
all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
const MutableSpan<float3> laplacian_disp = gather_data_vert_bmesh(
all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
tls.average_positions.resize(positions.size());
const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
smooth::average_data_bmesh(all_laplacian_disp.as_span(), verts, average_laplacian_disps);
tls.average_positions.resize(positions.size());
const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
smooth::average_data_bmesh(all_laplacian_disp.as_span(), verts, average_laplacian_disps);
tls.translations.resize(positions.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_displace_step(
laplacian_disp, average_laplacian_disps, beta, translations);
scale_translations(translations, factors);
tls.translations.resize(positions.size());
const MutableSpan<float3> translations = tls.translations;
smooth::surface_smooth_displace_step(
laplacian_disp, average_laplacian_disps, beta, translations);
scale_translations(translations, factors);
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, verts);
});
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, verts);
});
}
}

View File

@@ -7396,11 +7396,11 @@ void transform_positions(const float4x4 &transform, const MutableSpan<float3> po
}
OffsetIndices<int> create_node_vert_offsets(const Span<bke::pbvh::MeshNode> nodes,
const IndexMask &nodes_mask,
const IndexMask &node_mask,
Array<int> &node_data)
{
node_data.reinitialize(nodes.size() + 1);
nodes_mask.foreach_index([&](const int i, const int pos) {
node_data.reinitialize(node_mask.size() + 1);
node_mask.foreach_index([&](const int i, const int pos) {
node_data[pos] = bke::pbvh::node_unique_verts(nodes[i]).size();
});
return offset_indices::accumulate_counts_to_offsets(node_data);
@@ -7408,22 +7408,22 @@ OffsetIndices<int> create_node_vert_offsets(const Span<bke::pbvh::MeshNode> node
OffsetIndices<int> create_node_vert_offsets(const CCGKey &key,
const Span<bke::pbvh::GridsNode> nodes,
const IndexMask &nodes_mask,
const IndexMask &node_mask,
Array<int> &node_data)
{
node_data.reinitialize(nodes.size() + 1);
nodes_mask.foreach_index([&](const int i, const int pos) {
node_data.reinitialize(node_mask.size() + 1);
node_mask.foreach_index([&](const int i, const int pos) {
node_data[pos] = bke::pbvh::node_grid_indices(nodes[i]).size() * key.grid_area;
});
return offset_indices::accumulate_counts_to_offsets(node_data);
}
OffsetIndices<int> create_node_vert_offsets_bmesh(const Span<bke::pbvh::BMeshNode> nodes,
const IndexMask &nodes_mask,
const IndexMask &node_mask,
Array<int> &node_data)
{
node_data.reinitialize(nodes.size() + 1);
nodes_mask.foreach_index([&](const int i, const int pos) {
node_data.reinitialize(node_mask.size() + 1);
node_mask.foreach_index([&](const int i, const int pos) {
node_data[pos] =
BKE_pbvh_bmesh_node_unique_verts(const_cast<bke::pbvh::BMeshNode *>(&nodes[i])).size();
});

View File

@@ -116,18 +116,16 @@ static void apply_new_mask_mesh(const Depsgraph &depsgraph,
{
MutableSpan<bke::pbvh::MeshNode> nodes = object.sculpt->pbvh->nodes<bke::pbvh::MeshNode>();
threading::EnumerableThreadSpecific<Vector<int>> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
Vector<int> &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = hide::node_visible_verts(nodes[i], hide_vert, tls);
const Span<float> new_node_mask = new_mask.slice(node_verts[i]);
if (array_utils::indexed_data_equal<float>(mask, verts, new_node_mask)) {
return;
}
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
scatter_data_mesh(new_node_mask, verts, mask);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
const Span<int> verts = hide::node_visible_verts(nodes[i], hide_vert, tls);
const Span<float> new_node_mask = new_mask.slice(node_verts[pos]);
if (array_utils::indexed_data_equal<float>(mask, verts, new_node_mask)) {
return;
}
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
scatter_data_mesh(new_node_mask, verts, mask);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
}
@@ -297,9 +295,9 @@ static void apply_new_mask_grids(const Depsgraph &depsgraph,
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float> new_node_mask = new_mask.slice(node_verts[i]);
const Span<float> new_node_mask = new_mask.slice(node_verts[pos]);
if (mask_equals_array_grids(subdiv_ccg.grids, key, grids, new_node_mask)) {
return;
}
@@ -498,9 +496,9 @@ static void apply_new_mask_bmesh(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
BMesh &bm = *ss.bm;
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float> new_node_mask = new_mask.slice(node_verts[i]);
const Span<float> new_node_mask = new_mask.slice(node_verts[pos]);
if (mask_equals_array_bmesh(mask_offset, verts, new_node_mask)) {
return;
}
@@ -694,72 +692,64 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
for ([[maybe_unused]] const int iteration : IndexRange(iterations)) {
switch (filter_type) {
case FilterType::Smooth: {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
smooth_mask_mesh(faces,
corner_verts,
vert_to_face_map,
hide_poly,
mask.span,
nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[i]));
});
});
apply_new_mask_mesh(
*depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span);
break;
}
case FilterType::Sharpen: {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
sharpen_mask_mesh(faces,
corner_verts,
vert_to_face_map,
hide_poly,
mask.span,
nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[i]));
});
});
apply_new_mask_mesh(
*depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span);
break;
}
case FilterType::Grow: {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
grow_mask_mesh(faces,
smooth_mask_mesh(faces,
corner_verts,
vert_to_face_map,
hide_poly,
mask.span,
nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[i]));
});
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);
break;
}
case FilterType::Sharpen: {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
FilterLocalData &tls = all_tls.local();
sharpen_mask_mesh(faces,
corner_verts,
vert_to_face_map,
hide_poly,
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);
break;
}
case FilterType::Grow: {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
FilterLocalData &tls = all_tls.local();
grow_mask_mesh(faces,
corner_verts,
vert_to_face_map,
hide_poly,
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);
break;
}
case FilterType::Shrink: {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
shrink_mask_mesh(faces,
corner_verts,
vert_to_face_map,
hide_poly,
mask.span,
nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[i]));
});
shrink_mask_mesh(faces,
corner_verts,
vert_to_face_map,
hide_poly,
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);
@@ -800,36 +790,34 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
for ([[maybe_unused]] const int iteration : IndexRange(iterations)) {
switch (filter_type) {
case FilterType::Smooth: {
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
smooth_mask_grids(
subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[pos]));
});
apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Sharpen: {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
sharpen_mask_grids(
subdiv_ccg, nodes[i], tls, new_masks.as_mutable_span().slice(node_offsets[i]));
});
sharpen_mask_grids(
subdiv_ccg, nodes[i], tls, new_masks.as_mutable_span().slice(node_offsets[pos]));
});
apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Grow: {
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
grow_mask_grids(
subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[pos]));
});
apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Shrink: {
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
shrink_mask_grids(
subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[pos]));
});
apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks);
break;
@@ -871,39 +859,37 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
for ([[maybe_unused]] const int iteration : IndexRange(iterations)) {
switch (filter_type) {
case FilterType::Smooth: {
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
smooth_mask_bmesh(
mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[pos]));
});
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Sharpen: {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
sharpen_mask_bmesh(bm,
mask_offset,
nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[i]));
});
sharpen_mask_bmesh(bm,
mask_offset,
nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[pos]));
});
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Grow: {
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
grow_mask_bmesh(
mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[pos]));
});
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Shrink: {
node_mask.foreach_index(GrainSize(1), [&](const int i) {
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
shrink_mask_bmesh(
mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[pos]));
});
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks);
break;