Sculpt: Initial data oriented refactor for draw sharp brush

Part of #118145.

Pull Request: https://projects.blender.org/blender/blender/pulls/123103
This commit is contained in:
Raul Fernandez 2024-07-03 22:10:00 +02:00 committed by Raul Fernandez Hernandez
parent 3d0c556289
commit 750e3a6fba
4 changed files with 249 additions and 1 deletions

@ -120,6 +120,7 @@ set(SRC
brushes/crease.cc
brushes/draw_face_sets.cc
brushes/draw_vector_displacement.cc
brushes/draw_sharp.cc
brushes/draw.cc
brushes/fill.cc
brushes/flatten.cc

@ -0,0 +1,246 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "editors/sculpt_paint/brushes/types.hh"
#include "DNA_brush_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_key.hh"
#include "BKE_mesh.hh"
#include "BKE_paint.hh"
#include "BKE_pbvh.hh"
#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"
#include "BLI_task.h"
#include "BLI_task.hh"
#include "editors/sculpt_paint/mesh_brush_common.hh"
#include "editors/sculpt_paint/sculpt_intern.hh"
namespace blender::ed::sculpt_paint {
inline namespace draw_sharp_cc {
struct LocalData {
Vector<float3> positions;
Vector<float> factors;
Vector<float> distances;
Vector<float3> translations;
};
static void calc_faces_sharp(const Sculpt &sd,
const Brush &brush,
const float3 &offset,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const PBVHNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
{
SculptSession &ss = *object.sculpt;
const StrokeCache &cache = *ss.cache;
Mesh &mesh = *static_cast<Mesh *>(object.data);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
const Span<int> verts = bke::pbvh::node_unique_verts(node);
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);
if (brush.flag & BRUSH_FRONTFACE) {
calc_front_face(cache.view_normal, orig_data.normals, factors);
}
tls.distances.reinitialize(verts.size());
const MutableSpan<float> distances = tls.distances;
calc_brush_distances(
ss, orig_data.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);
if (cache.automasking) {
auto_mask::calc_vert_factors(object, *cache.automasking, node, verts, factors);
}
calc_brush_texture_factors(ss, brush, orig_data.positions, factors);
tls.translations.reinitialize(verts.size());
const MutableSpan<float3> translations = tls.translations;
translations_from_offset_and_factors(offset, factors, translations);
write_translations(sd, object, orig_data.positions, verts, translations, positions_orig);
}
static void calc_grids_sharp(const Sculpt &sd,
Object &object,
const Brush &brush,
const float3 &offset,
const PBVHNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
const StrokeCache &cache = *ss.cache;
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
const OrigPositionData orig_data = orig_position_data_get_grids(object, node);
const Span<int> grids = bke::pbvh::node_grid_indices(node);
const int grid_verts_num = grids.size() * key.grid_area;
tls.factors.reinitialize(grid_verts_num);
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
filter_region_clip_factors(ss, orig_data.positions, factors);
if (brush.flag & BRUSH_FRONTFACE) {
calc_front_face(cache.view_normal, orig_data.normals, grids, factors);
}
tls.distances.reinitialize(grid_verts_num);
const MutableSpan<float> distances = tls.distances;
calc_brush_distances(
ss, orig_data.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);
if (cache.automasking) {
auto_mask::calc_grids_factors(object, *cache.automasking, node, grids, factors);
}
calc_brush_texture_factors(ss, brush, orig_data.positions, factors);
tls.translations.reinitialize(grid_verts_num);
const MutableSpan<float3> translations = tls.translations;
translations_from_offset_and_factors(offset, factors, translations);
clip_and_lock_translations(sd, ss, orig_data.positions, translations);
apply_translations(translations, grids, subdiv_ccg);
}
static void calc_bmesh_sharp(const Sculpt &sd,
Object &object,
const Brush &brush,
const float3 &offset,
PBVHNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
const StrokeCache &cache = *ss.cache;
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&node);
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.factors.reinitialize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(*ss.bm, verts, factors);
filter_region_clip_factors(ss, orig_positions, factors);
if (brush.flag & BRUSH_FRONTFACE) {
calc_front_face(cache.view_normal, orig_normals, factors);
}
tls.distances.reinitialize(verts.size());
const MutableSpan<float> distances = tls.distances;
calc_brush_distances(ss, orig_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);
if (cache.automasking) {
auto_mask::calc_vert_factors(object, *cache.automasking, node, verts, factors);
}
calc_brush_texture_factors(ss, brush, orig_positions, factors);
tls.translations.reinitialize(verts.size());
const MutableSpan<float3> translations = tls.translations;
translations_from_offset_and_factors(offset, factors, translations);
clip_and_lock_translations(sd, ss, orig_positions, translations);
apply_translations(translations, verts);
}
} // namespace draw_sharp_cc
static void offset_positions(const Sculpt &sd,
Object &object,
const float3 &offset,
Span<PBVHNode *> nodes)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (BKE_pbvh_type(*object.sculpt->pbvh)) {
case PBVH_FACES: {
Mesh &mesh = *static_cast<Mesh *>(object.data);
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);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_faces_sharp(sd,
brush,
offset,
positions_eval,
vert_normals,
*nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
}
});
break;
}
case PBVH_GRIDS:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids_sharp(sd, object, brush, offset, *nodes[i], tls);
}
});
break;
case PBVH_BMESH:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh_sharp(sd, object, brush, offset, *nodes[i], tls);
}
});
break;
}
}
void do_draw_sharp_brush(const Sculpt &sd, Object &object, Span<PBVHNode *> nodes)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
float3 effective_normal;
SCULPT_tilt_effective_normal_get(ss, brush, effective_normal);
const float3 offset = effective_normal * ss.cache->radius * ss.cache->scale *
ss.cache->bstrength;
offset_positions(sd, object, offset, nodes);
}
} // namespace blender::ed::sculpt_paint

@ -25,6 +25,7 @@ void do_draw_face_sets_brush(const Sculpt &sd, Object &object, Span<PBVHNode *>
void do_draw_brush(const Sculpt &sd, Object &object, Span<PBVHNode *> nodes);
/** A simple normal-direction displacement based on image texture RGB/XYZ values. */
void do_draw_vector_displacement_brush(const Sculpt &sd, Object &object, Span<PBVHNode *> nodes);
void do_draw_sharp_brush(const Sculpt &sd, Object &object, Span<PBVHNode *> nodes);
void do_fill_brush(const Sculpt &sd, Object &object, Span<PBVHNode *> nodes);
void do_flatten_brush(const Sculpt &sd, Object &ob, Span<PBVHNode *> nodes);
void do_grab_brush(const Sculpt &sd, Object &ob, Span<PBVHNode *> nodes);

@ -3878,7 +3878,7 @@ static void do_brush_action(const Scene &scene,
pose::do_pose_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_DRAW_SHARP:
SCULPT_do_draw_sharp_brush(sd, ob, nodes);
do_draw_sharp_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_ELASTIC_DEFORM:
SCULPT_do_elastic_deform_brush(sd, ob, nodes);