Sculpt: use new brush API for the rest of the layer brush

Part of #118145.
Replace the PBVH vertex iterator macro.
This commit is contained in:
Hans Goudey
2024-07-16 11:39:29 -04:00
parent b7ce539305
commit 5bd7560894
2 changed files with 168 additions and 106 deletions

View File

@@ -37,8 +37,83 @@ struct LocalData {
Vector<float> distances;
Vector<float> masks;
Vector<float> displacement_factors;
Vector<float3> translations;
};
BLI_NOINLINE static void offset_displacement_factors(const MutableSpan<float> displacement_factors,
const Span<float> factors,
const float strength)
{
for (const int i : displacement_factors.index_range()) {
displacement_factors[i] += factors[i] * strength * (1.05f - std::abs(displacement_factors[i]));
}
}
/**
* When using persistent base, the layer brush (holding Control) invert mode resets the
* height of the layer to 0. This makes possible to clean edges of previously added layers
* on top of the base.
*
* The main direction of the layers is inverted using the regular brush strength with the
* brush direction property.
*/
BLI_NOINLINE static void reset_displacement_factors(const MutableSpan<float> displacement_factors,
const Span<float> factors,
const float strength)
{
for (const int i : displacement_factors.index_range()) {
displacement_factors[i] += std::abs(factors[i] * strength * displacement_factors[i]) *
(displacement_factors[i] > 0.0f ? -1.0f : 1.0f);
}
}
BLI_NOINLINE static void clamp_displacement_factors(const MutableSpan<float> displacement_factors,
const Span<float> masks)
{
if (masks.is_empty()) {
for (const int i : displacement_factors.index_range()) {
displacement_factors[i] = std::clamp(displacement_factors[i], -1.0f, 1.0f);
}
}
else {
for (const int i : displacement_factors.index_range()) {
const float clamp_mask = 1.0f - masks[i];
displacement_factors[i] = std::clamp(displacement_factors[i], -clamp_mask, clamp_mask);
}
}
}
BLI_NOINLINE static void calc_translations(const Span<float3> orig_positions,
const Span<float3> orig_normals,
const Span<float3> positions,
const Span<float> displacement_factors,
const Span<float> factors,
const float height,
const MutableSpan<float3> r_translations)
{
for (const int i : positions.index_range()) {
const float3 offset = orig_normals[i] * height * displacement_factors[i];
const float3 translation = orig_positions[i] + offset - positions[i];
r_translations[i] = translation * factors[i];
}
}
BLI_NOINLINE static void calc_translations(const Span<float3> base_positions,
const Span<float3> base_normals,
const Span<int> verts,
const Span<float3> positions,
const Span<float> displacement_factors,
const Span<float> factors,
const float height,
const MutableSpan<float3> r_translations)
{
for (const int i : positions.index_range()) {
const float3 offset = base_normals[verts[i]] * height * displacement_factors[i];
const float3 translation = base_positions[verts[i]] + offset - positions[i];
r_translations[i] = translation * factors[i];
}
}
static void calc_faces(const Sculpt &sd,
const Brush &brush,
const Span<float3> positions_eval,
@@ -50,7 +125,8 @@ static void calc_faces(const Sculpt &sd,
Object &object,
PBVHNode &node,
LocalData &tls,
MutableSpan<float> layer_displacement_factor)
MutableSpan<float> layer_displacement_factor,
MutableSpan<float3> positions_orig)
{
const SculptSession &ss = *object.sculpt;
const StrokeCache &cache = *ss.cache;
@@ -58,18 +134,21 @@ static void calc_faces(const Sculpt &sd,
const Span<int> verts = bke::pbvh::node_unique_verts(node);
tls.positions.reinitialize(verts.size());
const MutableSpan<float3> positions = tls.positions;
array_utils::gather(positions_eval, verts, positions);
tls.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
filter_region_clip_factors(ss, positions_eval, verts, factors);
filter_region_clip_factors(ss, positions, factors);
if (brush.flag & BRUSH_FRONTFACE) {
calc_front_face(cache.view_normal, vert_normals, verts, factors);
}
tls.distances.reinitialize(verts.size());
const MutableSpan<float> distances = tls.distances;
calc_brush_distances(
ss, positions_eval, verts, eBrushFalloffShape(brush.falloff_shape), 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);
@@ -78,7 +157,7 @@ static void calc_faces(const Sculpt &sd,
auto_mask::calc_vert_factors(object, *cache.automasking, node, verts, factors);
}
calc_brush_texture_factors(ss, brush, positions_eval, verts, factors);
calc_brush_texture_factors(ss, brush, positions, factors);
if (mask_attribute.is_empty()) {
tls.masks.clear();
@@ -89,67 +168,54 @@ static void calc_faces(const Sculpt &sd,
}
const MutableSpan<float> masks = tls.masks;
PBVHVertexIter vd;
const float bstrength = cache.bstrength;
const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
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);
if (use_persistent_base) {
BKE_pbvh_vertex_iter_begin (*ss.pbvh, &node, vd, PBVH_ITER_UNIQUE) {
float *disp_factor = &displacement_factors[vd.i];
/* When using persistent base, the layer brush (holding Control) invert mode resets the
* height of the layer to 0. This makes possible to clean edges of previously added layers
* on top of the base. */
/* The main direction of the layers is inverted using the regular brush strength with the
* brush direction property. */
if (cache.invert) {
(*disp_factor) += std::abs(factors[vd.i] * bstrength * (*disp_factor)) *
((*disp_factor) > 0.0f ? -1.0f : 1.0f);
}
else {
(*disp_factor) += factors[vd.i] * bstrength * (1.05f - std::abs(*disp_factor));
}
const float clamp_mask = masks.is_empty() ? 1.0f : (1.0f - masks[vd.i]);
*disp_factor = std::clamp(*disp_factor, -clamp_mask, clamp_mask);
float3 normal = persistent_base_normals[vd.index];
normal *= brush.height;
float3 final_co = persistent_base_positions[vd.index] + normal * *disp_factor;
float3 vdisp = final_co - float3(vd.co);
vdisp *= factors[vd.i];
final_co = float3(vd.co) + vdisp;
SCULPT_clip(sd, ss, vd.co, final_co);
if (cache.invert) {
reset_displacement_factors(displacement_factors, factors, cache.bstrength);
}
BKE_pbvh_vertex_iter_end;
else {
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);
tls.translations.reinitialize(verts.size());
const MutableSpan<float3> translations = tls.translations;
calc_translations(persistent_base_positions,
persistent_base_normals,
verts,
positions,
displacement_factors,
factors,
brush.height,
translations);
write_translations(sd, object, positions_eval, verts, translations, positions_orig);
}
else {
BKE_pbvh_vertex_iter_begin (*ss.pbvh, &node, vd, PBVH_ITER_UNIQUE) {
float *disp_factor = &displacement_factors[vd.i];
offset_displacement_factors(displacement_factors, factors, cache.bstrength);
clamp_displacement_factors(displacement_factors, masks);
(*disp_factor) += factors[vd.i] * bstrength * (1.05f - std::abs(*disp_factor));
const float clamp_mask = masks.is_empty() ? 1.0f : (1.0f - masks[vd.i]);
*disp_factor = std::clamp(*disp_factor, -clamp_mask, clamp_mask);
array_utils::scatter(displacement_factors.as_span(), verts, layer_displacement_factor);
float3 normal = orig_data.normals[vd.i];
normal *= brush.height;
float3 final_co = orig_data.positions[vd.i] + normal * *disp_factor;
const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
float3 vdisp = final_co - float3(vd.co);
vdisp *= factors[vd.i];
final_co = float3(vd.co) + vdisp;
tls.translations.reinitialize(verts.size());
const MutableSpan<float3> translations = tls.translations;
calc_translations(orig_data.positions,
orig_data.normals,
positions,
displacement_factors,
factors,
brush.height,
translations);
SCULPT_clip(sd, ss, vd.co, final_co);
}
BKE_pbvh_vertex_iter_end;
write_translations(sd, object, positions_eval, verts, translations, positions_orig);
}
array_utils::scatter(displacement_factors.as_span(), verts, layer_displacement_factor);
}
static void calc_grids(const Sculpt &sd,
@@ -200,30 +266,32 @@ static void calc_grids(const Sculpt &sd,
const MutableSpan<float> displacement_factors = tls.displacement_factors;
gather_data_grids(subdiv_ccg, layer_displacement_factor.as_span(), grids, displacement_factors);
PBVHVertexIter vd;
const float bstrength = cache.bstrength;
const OrigPositionData orig_data = orig_position_data_get_grids(object, node);
BKE_pbvh_vertex_iter_begin (*ss.pbvh, &node, vd, PBVH_ITER_UNIQUE) {
float *disp_factor = &displacement_factors[vd.i];
(*disp_factor) += factors[vd.i] * bstrength * (1.05f - std::abs(*disp_factor));
const float clamp_mask = 1.0f - masks[vd.i];
*disp_factor = std::clamp(*disp_factor, -clamp_mask, clamp_mask);
float3 normal = orig_data.normals[vd.i];
normal *= brush.height;
float3 final_co = orig_data.positions[vd.i] + normal * *disp_factor;
float3 vdisp = final_co - float3(vd.co);
vdisp *= factors[vd.i];
final_co = float3(vd.co) + vdisp;
SCULPT_clip(sd, ss, vd.co, final_co);
offset_displacement_factors(displacement_factors, factors, cache.bstrength);
if (key.has_mask) {
tls.masks.reinitialize(grid_verts_num);
mask::gather_mask_grids(subdiv_ccg, grids, masks);
}
BKE_pbvh_vertex_iter_end;
else {
tls.masks.clear();
}
clamp_displacement_factors(displacement_factors, tls.masks);
scatter_data_grids(subdiv_ccg, displacement_factors.as_span(), grids, layer_displacement_factor);
const OrigPositionData orig_data = orig_position_data_get_grids(object, node);
tls.translations.reinitialize(grid_verts_num);
const MutableSpan<float3> translations = tls.translations;
calc_translations(orig_data.positions,
orig_data.normals,
positions,
displacement_factors,
factors,
brush.height,
translations);
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, grids, subdiv_ccg);
}
static void calc_bmesh(const Sculpt &sd,
@@ -263,42 +331,35 @@ static void calc_bmesh(const Sculpt &sd,
calc_brush_texture_factors(ss, brush, positions, factors);
PBVHVertexIter vd;
const float bstrength = cache.bstrength;
tls.displacement_factors.reinitialize(verts.size());
const MutableSpan<float> displacement_factors = tls.displacement_factors;
gather_data_vert_bmesh(layer_displacement_factor.as_span(), verts, displacement_factors);
offset_displacement_factors(displacement_factors, factors, cache.bstrength);
tls.masks.reinitialize(verts.size());
const MutableSpan<float> masks = tls.masks;
mask::gather_mask_bmesh(*ss.bm, verts, masks);
clamp_displacement_factors(displacement_factors, masks);
scatter_data_vert_bmesh(displacement_factors.as_span(), verts, layer_displacement_factor);
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);
tls.masks.reinitialize(verts.size());
const MutableSpan<float> masks = tls.masks;
mask::gather_mask_bmesh(*ss.bm, verts, masks);
tls.translations.reinitialize(verts.size());
const MutableSpan<float3> translations = tls.translations;
calc_translations(orig_positions,
orig_normals,
positions,
displacement_factors,
factors,
brush.height,
translations);
tls.displacement_factors.reinitialize(verts.size());
const MutableSpan<float> displacement_factors = tls.displacement_factors;
gather_data_vert_bmesh(layer_displacement_factor.as_span(), verts, displacement_factors);
BKE_pbvh_vertex_iter_begin (*ss.pbvh, &node, vd, PBVH_ITER_UNIQUE) {
float *disp_factor = &displacement_factors[vd.i];
(*disp_factor) += factors[vd.i] * bstrength * (1.05f - std::abs(*disp_factor));
const float clamp_mask = 1.0f - masks[vd.i];
*disp_factor = std::clamp(*disp_factor, -clamp_mask, clamp_mask);
float3 normal = orig_normals[vd.i];
normal *= brush.height;
float3 final_co = orig_positions[vd.i] + normal * *disp_factor;
float3 vdisp = final_co - float3(vd.co);
vdisp *= factors[vd.i];
final_co = float3(vd.co) + vdisp;
SCULPT_clip(sd, ss, vd.co, final_co);
}
BKE_pbvh_vertex_iter_end;
scatter_data_vert_bmesh(displacement_factors.as_span(), verts, layer_displacement_factor);
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, verts);
}
} // namespace layer_cc
@@ -320,6 +381,7 @@ void do_layer_brush(const Sculpt &sd, Object &object, Span<PBVHNode *> nodes)
const PBVH &pbvh = *ss.pbvh;
const Span<float3> positions_eval = BKE_pbvh_get_vert_positions(pbvh);
const Span<float3> vert_normals = BKE_pbvh_get_vert_normals(pbvh);
const MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
const VArraySpan masks = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
@@ -361,7 +423,8 @@ void do_layer_brush(const Sculpt &sd, Object &object, Span<PBVHNode *> nodes)
object,
*nodes[i],
tls,
displacement);
displacement,
positions_orig);
}
});
});

View File

@@ -6027,7 +6027,6 @@ static void sculpt_stroke_update_step(bContext *C,
if ((ELEM(brush.sculpt_tool,
SCULPT_TOOL_BOUNDARY,
SCULPT_TOOL_CLOTH,
SCULPT_TOOL_LAYER,
SCULPT_TOOL_MASK,
SCULPT_TOOL_PAINT,
SCULPT_TOOL_POSE,