Cleanup: Sculpt: Use generic functions for mesh data gather/scatter

For meshes (in comparison to multires grids and BMesh) there is nothing
special about position, normals, or mask arrays. We can use the same
functions for gathering and scattering all the arrays. This also gives us
a somewhat nicer temporary solution for the issue of the `array_utils`
utilities using multithreading forcing us to use task isolation. Now the
brushes don't use those utilities.
This commit is contained in:
Hans Goudey
2024-07-24 23:10:52 -04:00
parent 8418ec4952
commit e1a30b09eb
22 changed files with 172 additions and 187 deletions

View File

@@ -16,7 +16,6 @@
#include "BKE_subdiv_ccg.hh"
#include "BLI_array.hh"
#include "BLI_array_utils.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_geom.h"
#include "BLI_math_matrix.h"
@@ -57,7 +56,7 @@ static void calc_faces(const Sculpt &sd,
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<int> verts = bke::pbvh::node_unique_verts(node);
const MutableSpan positions = gather_mesh_positions(positions_eval, verts, tls.positions);
const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions);
tls.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;

View File

@@ -11,7 +11,6 @@
#include "BKE_pbvh.hh"
#include "BKE_subdiv_ccg.hh"
#include "BLI_array_utils.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_base.hh"
#include "BLI_task.h"

View File

@@ -16,7 +16,6 @@
#include "BKE_subdiv_ccg.hh"
#include "BLI_array.hh"
#include "BLI_array_utils.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_matrix.hh"
#include "BLI_math_vector.hh"

View File

@@ -16,7 +16,6 @@
#include "BKE_subdiv_ccg.hh"
#include "BLI_array.hh"
#include "BLI_array_utils.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_vector.hh"
#include "BLI_task.hh"
@@ -80,7 +79,7 @@ static void calc_faces(const Sculpt &sd,
tls.translations.reinitialize(verts.size());
const MutableSpan<float3> translations = tls.translations;
array_utils::gather(all_translations, verts, translations);
gather_data_mesh(all_translations, verts, translations);
scale_translations(translations, factors);
write_translations(sd, object, positions_eval, verts, translations, positions_orig);
@@ -195,12 +194,12 @@ static void calc_translations_faces(const Span<float3> vert_positions,
tls.new_positions.reinitialize(verts.size());
const MutableSpan<float3> new_positions = tls.new_positions;
smooth::neighbor_position_average_mesh(vert_positions, verts, neighbors, new_positions);
smooth::neighbor_data_average_mesh(vert_positions, neighbors, new_positions);
tls.translations.reinitialize(verts.size());
const MutableSpan<float3> translations = tls.translations;
translations_from_new_positions(new_positions, verts, vert_positions, translations);
array_utils::scatter(translations.as_span(), verts, all_translations);
scatter_data_mesh(translations.as_span(), verts, all_translations);
}
static void calc_translations_grids(const SubdivCCG &subdiv_ccg,
@@ -261,17 +260,15 @@ static void precalc_translations(Object &object, const MutableSpan<float3> trans
const Span<int> corner_verts = mesh.corner_verts();
threading::parallel_for(effective_nodes.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
threading::isolate_task([&]() {
for (const int i : range) {
calc_translations_faces(positions_eval,
faces,
corner_verts,
ss.vert_to_face_map,
*effective_nodes[i],
tls,
translations);
}
});
for (const int i : range) {
calc_translations_faces(positions_eval,
faces,
corner_verts,
ss.vert_to_face_map,
*effective_nodes[i],
tls,
translations);
}
});
break;
}
@@ -323,21 +320,19 @@ void do_enhance_details_brush(const Sculpt &sd, Object &object, Span<bke::pbvh::
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
threading::isolate_task([&]() {
for (const int i : range) {
calc_faces(sd,
brush,
positions_eval,
vert_normals,
translations,
strength,
*nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
}
});
for (const int i : range) {
calc_faces(sd,
brush,
positions_eval,
vert_normals,
translations,
strength,
*nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
}
});
break;
}

View File

@@ -81,7 +81,7 @@ static void calc_faces(const Sculpt &sd,
calc_brush_texture_factors(ss, brush, positions_eval, verts, factors);
const MutableSpan translations = gather_mesh_normals(vert_normals, verts, tls.translations);
const MutableSpan translations = gather_data_mesh(vert_normals, verts, tls.translations);
apply_scale(translations, scale);
scale_translations(translations, factors);

View File

@@ -16,7 +16,6 @@
#include "BKE_subdiv_ccg.hh"
#include "BLI_array.hh"
#include "BLI_array_utils.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_vector.h"
#include "BLI_math_vector.hh"
@@ -133,7 +132,7 @@ static void calc_faces(const Sculpt &sd,
const Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<int> verts = bke::pbvh::node_unique_verts(node);
const MutableSpan positions = gather_mesh_positions(positions_eval, verts, tls.positions);
const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions);
tls.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;
@@ -161,13 +160,13 @@ static void calc_faces(const Sculpt &sd,
}
else {
tls.masks.reinitialize(verts.size());
array_utils::gather(mask_attribute, verts, tls.masks.as_mutable_span());
gather_data_mesh(mask_attribute, verts, tls.masks.as_mutable_span());
}
const MutableSpan<float> masks = tls.masks;
tls.displacement_factors.reinitialize(verts.size());
const MutableSpan<float> displacement_factors = tls.displacement_factors;
array_utils::gather(layer_displacement_factor.as_span(), verts, displacement_factors);
gather_data_mesh(layer_displacement_factor.as_span(), verts, displacement_factors);
if (use_persistent_base) {
if (cache.invert) {
@@ -178,7 +177,7 @@ static void calc_faces(const Sculpt &sd,
}
clamp_displacement_factors(displacement_factors, masks);
array_utils::scatter(displacement_factors.as_span(), verts, layer_displacement_factor);
scatter_data_mesh(displacement_factors.as_span(), verts, layer_displacement_factor);
tls.translations.reinitialize(verts.size());
const MutableSpan<float3> translations = tls.translations;
@@ -197,7 +196,7 @@ static void calc_faces(const Sculpt &sd,
offset_displacement_factors(displacement_factors, factors, cache.bstrength);
clamp_displacement_factors(displacement_factors, masks);
array_utils::scatter(displacement_factors.as_span(), verts, layer_displacement_factor);
scatter_data_mesh(displacement_factors.as_span(), verts, layer_displacement_factor);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
@@ -392,23 +391,21 @@ void do_layer_brush(const Sculpt &sd, Object &object, Span<bke::pbvh::Node *> no
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
threading::isolate_task([&]() {
for (const int i : range) {
calc_faces(sd,
brush,
positions_eval,
vert_normals,
masks,
use_persistent_base,
persistent_position,
persistent_normal,
object,
*nodes[i],
tls,
displacement,
positions_orig);
}
});
for (const int i : range) {
calc_faces(sd,
brush,
positions_eval,
vert_normals,
masks,
use_persistent_base,
persistent_position,
persistent_normal,
object,
*nodes[i],
tls,
displacement,
positions_orig);
}
});
persistent_disp_attr.finish();
break;

View File

@@ -13,7 +13,6 @@
#include "BKE_subdiv_ccg.hh"
#include "BLI_array.hh"
#include "BLI_array_utils.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_vector.hh"
#include "BLI_span.hh"
@@ -98,7 +97,7 @@ static void calc_faces(const Brush &brush,
tls.new_masks.reinitialize(verts.size());
const MutableSpan<float> new_masks = tls.new_masks;
array_utils::gather(mask.as_span(), verts, new_masks);
gather_data_mesh(mask.as_span(), verts, new_masks);
tls.current_masks = tls.new_masks;
const MutableSpan<float> current_masks = tls.current_masks;
@@ -108,7 +107,7 @@ static void calc_faces(const Brush &brush,
apply_factors(strength, current_masks, factors, new_masks);
clamp_mask(new_masks);
array_utils::scatter(new_masks.as_span(), verts, mask);
scatter_data_mesh(new_masks.as_span(), verts, mask);
}
static void calc_grids(Object &object,
@@ -232,20 +231,11 @@ void do_mask_brush(const Sculpt &sd, Object &object, Span<bke::pbvh::Node *> nod
".sculpt_mask", bke::AttrDomain::Point);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::isolate_task([&]() {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_faces(brush,
bstrength,
positions,
vert_normals,
*nodes[i],
object,
mesh,
tls,
mask.span);
}
});
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_faces(
brush, bstrength, positions, vert_normals, *nodes[i], object, mesh, tls, mask.span);
}
});
mask.finish();
break;

View File

@@ -139,7 +139,7 @@ static void sample_node_surface_mesh(const Object &object,
const Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<int> verts = bke::pbvh::node_unique_verts(node);
const MutableSpan positions = gather_mesh_positions(vert_positions, verts, tls.positions);
const MutableSpan positions = gather_data_mesh(vert_positions, verts, tls.positions);
tls.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;
@@ -166,7 +166,7 @@ static void sample_node_surface_mesh(const Object &object,
MutableSpan<float3> local_positions = tls.local_positions;
transform_positions(positions, mat, local_positions);
const MutableSpan normals = gather_mesh_normals(vert_normals, verts, tls.normals);
const MutableSpan normals = gather_data_mesh(vert_normals, verts, tls.normals);
accumulate_samples(positions, local_positions, normals, factors, sample);
}
@@ -343,7 +343,7 @@ static void calc_faces(const Sculpt &sd,
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<int> verts = bke::pbvh::node_unique_verts(node);
const MutableSpan positions = gather_mesh_positions(positions_eval, verts, tls.positions);
const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions);
tls.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;

View File

@@ -76,7 +76,7 @@ static void calc_faces(const Sculpt &sd,
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<int> verts = bke::pbvh::node_unique_verts(node);
const MutableSpan positions = gather_mesh_positions(positions_eval, verts, tls.positions);
const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions);
tls.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;

View File

@@ -146,7 +146,7 @@ BLI_NOINLINE static void do_smooth_brush_mesh(const Sculpt &sd,
hide_poly,
verts,
tls.vert_neighbors);
smooth::neighbor_position_average_mesh(
smooth::neighbor_data_average_mesh_check_loose(
positions_eval,
verts,
tls.vert_neighbors,

View File

@@ -10,7 +10,6 @@
#include "BKE_mesh.hh"
#include "BKE_subdiv_ccg.hh"
#include "BLI_array_utils.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_base.hh"
#include "BLI_task.h"
@@ -62,7 +61,7 @@ static void calc_smooth_masks_faces(const OffsetIndices<int> faces,
tls.vert_neighbors.reinitialize(verts.size());
calc_vert_neighbors(faces, corner_verts, vert_to_face_map, hide_poly, verts, tls.vert_neighbors);
const Span<Vector<int>> vert_neighbors = tls.vert_neighbors;
mask::average_neighbor_mask_mesh(masks, vert_neighbors, new_masks);
smooth::neighbor_data_average_mesh(masks, vert_neighbors, new_masks);
}
static void apply_masks_faces(const Brush &brush,
@@ -107,12 +106,12 @@ static void apply_masks_faces(const Brush &brush,
tls.new_masks.reinitialize(verts.size());
const MutableSpan<float> new_masks = tls.new_masks;
array_utils::gather(mask.as_span(), verts, new_masks);
gather_data_mesh(mask.as_span(), verts, new_masks);
mask::mix_new_masks(mask_averages, factors, new_masks);
mask::clamp_mask(new_masks);
array_utils::scatter(new_masks.as_span(), verts, mask);
scatter_data_mesh(new_masks.as_span(), verts, mask);
}
static void do_smooth_brush_mesh(const Brush &brush,
@@ -160,20 +159,18 @@ static void do_smooth_brush_mesh(const Brush &brush,
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::isolate_task([&]() {
LocalData &tls = all_tls.local();
for (const int i : range) {
apply_masks_faces(brush,
positions_eval,
vert_normals,
*nodes[i],
strength,
object,
tls,
new_masks.as_span().slice(node_vert_offsets[i]),
mask.span);
}
});
LocalData &tls = all_tls.local();
for (const int i : range) {
apply_masks_faces(brush,
positions_eval,
vert_normals,
*nodes[i],
strength,
object,
tls,
new_masks.as_span().slice(node_vert_offsets[i]),
mask.span);
}
});
}
mask.finish();

View File

@@ -17,7 +17,6 @@
#include "BKE_subdiv_ccg.hh"
#include "BLI_array.hh"
#include "BLI_array_utils.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_matrix.hh"
#include "BLI_math_rotation.h"
@@ -175,7 +174,7 @@ static void calc_faces(const Sculpt &sd,
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<int> verts = bke::pbvh::node_unique_verts(node);
const MutableSpan positions = gather_mesh_positions(positions_eval, verts, tls.positions);
const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions);
tls.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;

View File

@@ -170,7 +170,7 @@ static void calc_faces(const Sculpt &sd,
const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
const Span<int> verts = bke::pbvh::node_unique_verts(node);
const MutableSpan positions = gather_mesh_positions(positions_eval, verts, tls.positions);
const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions);
tls.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;

View File

@@ -90,17 +90,6 @@ void transform_positions(Span<float3> src, const float4x4 &transform, MutableSpa
*/
/** Fill the output array with all positions in the geometry referenced by the indices. */
void gather_mesh_positions(Span<float3> vert_postions,
Span<int> verts,
MutableSpan<float3> positions);
inline MutableSpan<float3> gather_mesh_positions(const Span<float3> vert_positions,
const Span<int> verts,
Vector<float3> &positions)
{
positions.resize(verts.size());
gather_mesh_positions(vert_positions, verts, positions.as_mutable_span());
return positions;
}
void gather_grids_positions(const CCGKey &key,
const Span<CCGElem *> elems,
const Span<int> grids,
@@ -124,18 +113,20 @@ inline MutableSpan<float3> gather_bmesh_positions(const Set<BMVert *, 0> &verts,
}
/** Fill the output array with all normals in the grids referenced by the indices. */
inline MutableSpan<float3> gather_mesh_normals(const Span<float3> vert_normals,
const Span<int> verts,
Vector<float3> &normals)
{
return gather_mesh_positions(vert_normals, verts, normals);
}
void gather_grids_normals(const SubdivCCG &subdiv_ccg,
Span<int> grids,
MutableSpan<float3> normals);
void gather_bmesh_normals(const Set<BMVert *, 0> &verts, MutableSpan<float3> normals);
/** Gather data from an array aligned with all geometry vertices. */
template<typename T> void gather_data_mesh(Span<T> src, Span<int> indices, MutableSpan<T> dst);
template<typename T>
MutableSpan<T> gather_data_mesh(const Span<T> src, const Span<int> indices, Vector<T> &dst)
{
dst.resize(indices.size());
gather_data_mesh(src, indices, dst.as_mutable_span());
return dst;
}
template<typename T>
void gather_data_grids(const SubdivCCG &subdiv_ccg,
Span<T> src,
@@ -145,6 +136,7 @@ template<typename T>
void gather_data_vert_bmesh(Span<T> src, const Set<BMVert *, 0> &verts, MutableSpan<T> node_data);
/** Scatter data from an array of the node's data to the referenced geometry vertices. */
template<typename T> void scatter_data_mesh(Span<T> src, Span<int> indices, MutableSpan<T> dst);
template<typename T>
void scatter_data_grids(const SubdivCCG &subdiv_ccg,
Span<T> node_data,

View File

@@ -506,9 +506,6 @@ void gather_mask_bmesh(const BMesh &bm, const Set<BMVert *, 0> &verts, MutableSp
void scatter_mask_grids(Span<float> mask, SubdivCCG &subdiv_ccg, Span<int> grids);
void scatter_mask_bmesh(Span<float> mask, const BMesh &bm, const Set<BMVert *, 0> &verts);
void average_neighbor_mask_mesh(Span<float> masks,
Span<Vector<int>> vert_neighbors,
MutableSpan<float> new_masks);
void average_neighbor_mask_grids(const SubdivCCG &subdiv_ccg,
Span<int> grids,
MutableSpan<float> new_masks);

View File

@@ -185,24 +185,6 @@ void scatter_mask_bmesh(const Span<float> mask, const BMesh &bm, const Set<BMVer
}
}
static float average_masks(const Span<float> masks, const Span<int> indices)
{
float sum = 0;
for (const int i : indices) {
sum += masks[i];
}
return sum / float(indices.size());
}
void average_neighbor_mask_mesh(const Span<float> masks,
const Span<Vector<int>> vert_neighbors,
const MutableSpan<float> new_masks)
{
for (const int i : vert_neighbors.index_range()) {
new_masks[i] = average_masks(masks, vert_neighbors[i]);
}
}
static float average_masks(const CCGKey &key,
const Span<CCGElem *> elems,
const Span<SubdivCCGCoord> coords)

View File

@@ -5643,7 +5643,7 @@ void flush_update_step(bContext *C, UpdateType update_type)
ED_region_tag_redraw(&region);
if (update_type == UpdateType::Image) {
/* Early exit when only need to update the images. We don't want to tag any geometry updates
* that would rebuilt the bke::pbvh::Tree. */
* that would rebuild the bke::pbvh::Tree. */
return;
}
}
@@ -6604,17 +6604,6 @@ void SCULPT_cube_tip_init(const Sculpt & /*sd*/,
namespace blender::ed::sculpt_paint {
void gather_mesh_positions(Span<float3> vert_postions,
Span<int> verts,
MutableSpan<float3> positions)
{
BLI_assert(verts.size() == positions.size());
for (const int i : verts.index_range()) {
positions[i] = vert_postions[verts[i]];
}
}
void gather_grids_positions(const CCGKey &key,
const Span<CCGElem *> elems,
const Span<int> grids,
@@ -6668,6 +6657,16 @@ void gather_bmesh_normals(const Set<BMVert *, 0> &verts, const MutableSpan<float
}
}
template<typename T>
void gather_data_mesh(const Span<T> src, const Span<int> indices, const MutableSpan<T> dst)
{
BLI_assert(indices.size() == dst.size());
for (const int i : indices.index_range()) {
dst[i] = src[indices[i]];
}
}
template<typename T>
void gather_data_grids(const SubdivCCG &subdiv_ccg,
const Span<T> src,
@@ -6698,6 +6697,16 @@ void gather_data_vert_bmesh(const Span<T> src,
}
}
template<typename T>
void scatter_data_mesh(const Span<T> src, const Span<int> indices, const MutableSpan<T> dst)
{
BLI_assert(indices.size() == src.size());
for (const int i : indices.index_range()) {
dst[indices[i]] = src[i];
}
}
template<typename T>
void scatter_data_grids(const SubdivCCG &subdiv_ccg,
const Span<T> node_data,
@@ -6728,6 +6737,8 @@ void scatter_data_vert_bmesh(const Span<T> node_data,
}
}
template void gather_data_mesh<float>(Span<float>, Span<int>, MutableSpan<float>);
template void gather_data_mesh<float3>(Span<float3>, Span<int>, MutableSpan<float3>);
template void gather_data_grids<float>(const SubdivCCG &,
Span<float>,
Span<int>,
@@ -6743,6 +6754,8 @@ template void gather_data_vert_bmesh<float3>(Span<float3>,
const Set<BMVert *, 0> &,
MutableSpan<float3>);
template void scatter_data_mesh<float>(Span<float>, Span<int>, MutableSpan<float>);
template void scatter_data_mesh<float3>(Span<float3>, Span<int>, MutableSpan<float3>);
template void scatter_data_grids<float>(const SubdivCCG &,
Span<float>,
Span<int>,

View File

@@ -1687,10 +1687,13 @@ void neighbor_position_average_bmesh(const Set<BMVert *, 0> &verts,
void neighbor_position_average_interior_bmesh(const Set<BMVert *, 0> &verts,
MutableSpan<float3> new_positions);
void neighbor_position_average_mesh(Span<float3> positions,
Span<int> verts,
Span<Vector<int>> vert_neighbors,
MutableSpan<float3> new_positions);
template<typename T>
void neighbor_data_average_mesh(Span<T> src, Span<Vector<int>> vert_neighbors, MutableSpan<T> dst);
template<typename T>
void neighbor_data_average_mesh_check_loose(Span<T> src,
Span<int> verts,
Span<Vector<int>> vert_neighbors,
MutableSpan<T> dst);
/* Surface Smooth Brush. */

View File

@@ -1009,7 +1009,7 @@ static void bake_mask_mesh(const Object &object,
tls.mask.reinitialize(verts.size());
const MutableSpan<float> node_mask = tls.mask;
array_utils::gather(mask.as_span(), verts, node_mask);
gather_data_mesh(mask.as_span(), verts, node_mask);
calc_new_masks(mode, node_mask, new_mask);
mix_new_masks(new_mask, factors, node_mask);

View File

@@ -58,8 +58,8 @@ static void apply_projection_mesh(const Sculpt &sd,
undo::push_node(object, &node, undo::Type::Position);
const Span<int> verts = bke::pbvh::node_unique_verts(node);
const MutableSpan positions = gather_mesh_positions(positions_eval, verts, tls.positions);
const MutableSpan normals = gather_mesh_normals(vert_normals, verts, tls.normals);
const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions);
const MutableSpan normals = gather_data_mesh(vert_normals, verts, tls.normals);
tls.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;

View File

@@ -27,34 +27,65 @@
namespace blender::ed::sculpt_paint::smooth {
static float3 average_positions(const Span<float3> positions, const Span<int> indices)
template<typename T> T calc_average(const Span<T> positions, const Span<int> indices)
{
const float factor = math::rcp(float(indices.size()));
float3 result(0);
T result{};
for (const int i : indices) {
result += positions[i] * factor;
}
return result;
}
void neighbor_position_average_mesh(const Span<float3> positions,
const Span<int> verts,
const Span<Vector<int>> vert_neighbors,
const MutableSpan<float3> new_positions)
template<typename T>
void neighbor_data_average_mesh_check_loose(const Span<T> src,
const Span<int> verts,
const Span<Vector<int>> vert_neighbors,
const MutableSpan<T> dst)
{
BLI_assert(vert_neighbors.size() == new_positions.size());
BLI_assert(verts.size() == dst.size());
BLI_assert(vert_neighbors.size() == dst.size());
for (const int i : vert_neighbors.index_range()) {
const Span<int> neighbors = vert_neighbors[i];
if (neighbors.is_empty()) {
new_positions[i] = positions[verts[i]];
dst[i] = src[verts[i]];
}
else {
new_positions[i] = average_positions(positions, neighbors);
dst[i] = calc_average(src, neighbors);
}
}
}
template void neighbor_data_average_mesh_check_loose<float>(Span<float>,
Span<int>,
Span<Vector<int>>,
MutableSpan<float>);
template void neighbor_data_average_mesh_check_loose<float3>(Span<float3>,
Span<int>,
Span<Vector<int>>,
MutableSpan<float3>);
template<typename T>
void neighbor_data_average_mesh(const Span<T> src,
const Span<Vector<int>> vert_neighbors,
const MutableSpan<T> dst)
{
BLI_assert(vert_neighbors.size() == dst.size());
for (const int i : vert_neighbors.index_range()) {
BLI_assert(!vert_neighbors[i].is_empty());
dst[i] = calc_average(src, vert_neighbors[i]);
}
}
template void neighbor_data_average_mesh<float>(Span<float>,
Span<Vector<int>>,
MutableSpan<float>);
template void neighbor_data_average_mesh<float3>(Span<float3>,
Span<Vector<int>>,
MutableSpan<float3>);
static float3 average_positions(const CCGKey &key,
const Span<CCGElem *> elems,
const Span<SubdivCCGCoord> coords)

View File

@@ -364,7 +364,7 @@ static void elastic_transform_node_mesh(const Sculpt &sd,
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
const Span<int> verts = bke::pbvh::node_unique_verts(node);
const MutableSpan positions = gather_mesh_positions(positions_eval, verts, tls.positions);
const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions);
/* TODO: Using the factors array is unnecessary when there are no hidden vertices and no mask. */
tls.factors.reinitialize(verts.size());
@@ -801,28 +801,20 @@ static float3 average_mask_border_position(const Object &object,
AveragePositionAccumulation{},
[&](const IndexRange range, AveragePositionAccumulation sum) {
LocalData &tls = all_tls.local();
threading::isolate_task([&]() {
for (const bke::pbvh::Node *node : nodes.as_span().slice(range)) {
const Span<int> verts = bke::pbvh::node_unique_verts(*node);
for (const bke::pbvh::Node *node : nodes.as_span().slice(range)) {
const Span<int> verts = bke::pbvh::node_unique_verts(*node);
MutableSpan positions = gather_data_mesh(vert_positions, verts, tls.positions);
MutableSpan masks = gather_data_mesh(mask_attr, verts, tls.masks);
tls.positions.reinitialize(verts.size());
const MutableSpan<float3> positions = tls.positions;
array_utils::gather(vert_positions, verts, positions);
tls.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide(mesh, verts, factors);
tls.masks.reinitialize(verts.size());
const MutableSpan<float> masks = tls.masks;
array_utils::gather(mask_attr, verts, masks);
mask_border_weight_calc(masks, factors);
filter_positions_pivot_symmetry(positions, pivot, symm, factors);
tls.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide(mesh, verts, factors);
mask_border_weight_calc(masks, factors);
filter_positions_pivot_symmetry(positions, pivot, symm, factors);
accumulate_weighted_average_position(positions, factors, sum);
}
});
accumulate_weighted_average_position(positions, factors, sum);
}
return sum;
},
combine_average_position_accumulation);