Blender V5.0
multires_displacement_smear.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "DNA_brush_types.h"
8#include "DNA_object_types.h"
9#include "DNA_scene_types.h"
10
11#include "BKE_paint.hh"
12#include "BKE_paint_bvh.hh"
13#include "BKE_subdiv_ccg.hh"
14
16#include "BLI_math_vector.hh"
17#include "BLI_task.hh"
18
21
23
25
31
32static void calc_node(const Depsgraph &depsgraph,
33 Object &object,
34 const Brush &brush,
35 const float strength,
36 const bke::pbvh::GridsNode &node,
37 LocalData &tls)
38{
39 SculptSession &ss = *object.sculpt;
40 const StrokeCache &cache = *ss.cache;
41 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
42 MutableSpan<float3> ccg_positions = subdiv_ccg.positions;
43 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
44
45 const Span<int> grids = node.grids();
46 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
47
48 calc_factors_common_grids(depsgraph, brush, object, positions, node, tls.factors, tls.distances);
49
50 scale_factors(tls.factors, strength);
51
52 for (const int i : grids.index_range()) {
53 const IndexRange node_grid_range = bke::ccg::grid_range(key.grid_area, i);
54 const IndexRange grid_range = bke::ccg::grid_range(key.grid_area, grids[i]);
55 const int grid = grids[i];
56 for (const int y : IndexRange(key.grid_size)) {
57 for (const int x : IndexRange(key.grid_size)) {
58 const int offset = CCG_grid_xy_to_index(key.grid_size, x, y);
59 const int node_vert = node_grid_range[offset];
60 const int vert = grid_range[offset];
61
62 float3 current_disp;
63 switch (brush.smear_deform_type) {
65 current_disp = cache.location_symm - cache.last_location_symm;
66 break;
68 current_disp = cache.location_symm - ccg_positions[vert];
69 break;
71 current_disp = ccg_positions[vert] - cache.location_symm;
72 break;
73 }
74
75 const float3 current_disp_norm = math::normalize(current_disp);
76
77 SubdivCCGCoord coord{};
78 coord.grid_index = grid;
79 coord.x = x;
80 coord.y = y;
81
82 float3 interp_limit_surface_disp = cache.displacement_smear.prev_displacement[vert];
83 float weights_accum = 1.0f;
84
85 SubdivCCGNeighbors neighbors;
86 BKE_subdiv_ccg_neighbor_coords_get(*ss.subdiv_ccg, coord, false, neighbors);
87
88 for (const SubdivCCGCoord neighbor : neighbors.coords) {
89 const int neighbor_index = neighbor.to_index(key);
90 const float3 vert_disp = cache.displacement_smear.limit_surface_co[neighbor_index] -
92 const float3 &neighbor_limit_surface_disp =
93 cache.displacement_smear.prev_displacement[neighbor_index];
94 const float3 vert_disp_norm = math::normalize(vert_disp);
95
96 if (math::dot(current_disp_norm, vert_disp_norm) >= 0.0f) {
97 continue;
98 }
99
100 const float disp_interp = std::clamp(
101 -math::dot(current_disp_norm, vert_disp_norm), 0.0f, 1.0f);
102 interp_limit_surface_disp += neighbor_limit_surface_disp * disp_interp;
103 weights_accum += disp_interp;
104 }
105
106 interp_limit_surface_disp *= math::rcp(weights_accum);
107
108 float3 new_co = cache.displacement_smear.limit_surface_co[vert] +
109 interp_limit_surface_disp;
110 ccg_positions[vert] = math::interpolate(
111 ccg_positions[vert], new_co, tls.factors[node_vert]);
112 }
113 }
114 }
115}
116
117BLI_NOINLINE static void eval_all_limit_positions(const SubdivCCG &subdiv_ccg,
118 const MutableSpan<float3> limit_positions)
119{
120 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
121 threading::parallel_for(IndexRange(subdiv_ccg.grids_num), 1024, [&](const IndexRange range) {
122 for (const int grid : range) {
123 const MutableSpan grid_limit_positions = limit_positions.slice(
124 bke::ccg::grid_range(key.grid_area, grid));
125 BKE_subdiv_ccg_eval_limit_positions(subdiv_ccg, key, grid, grid_limit_positions);
126 }
127 });
128}
129
131 const Span<float3> positions,
132 const CCGKey &key,
133 const bke::pbvh::GridsNode &node,
134 const MutableSpan<float3> prev_displacement)
135{
136 for (const int grid : node.grids()) {
137 for (const int i : bke::ccg::grid_range(key.grid_area, grid)) {
138 prev_displacement[i] = positions[i] - limit_positions[i];
139 }
140 }
141}
142
143} // namespace multires_displacement_smear_cc
144
146 const Sculpt &sd,
147 Object &ob,
148 const IndexMask &node_mask)
149{
150 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
151 SculptSession &ss = *ob.sculpt;
154
155 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
156 MutableSpan<float3> positions = subdiv_ccg.positions;
157 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
158
159 if (ss.cache->displacement_smear.limit_surface_co.is_empty()) {
162
164 }
165
166 node_mask.foreach_index(GrainSize(1), [&](const int i) {
168 subdiv_ccg.positions,
169 key,
170 nodes[i],
172 });
173
174 const float strength = std::clamp(ss.cache->bstrength, 0.0f, 1.0f);
175
177 node_mask.foreach_index(GrainSize(1), [&](const int i) {
178 LocalData &tls = all_tls.local();
179 calc_node(depsgraph, ob, brush, strength, nodes[i], tls);
180 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
181 });
182 pbvh.tag_positions_changed(node_mask);
184}
185
186} // namespace blender::ed::sculpt_paint::brushes
int CCG_grid_xy_to_index(const int grid_size, const int x, const int y)
Definition BKE_ccg.hh:73
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:650
A BVH for high poly meshes.
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, bool include_duplicates, SubdivCCGNeighbors &r_neighbors)
#define BLI_NOINLINE
@ BRUSH_SMEAR_DEFORM_PINCH
@ BRUSH_SMEAR_DEFORM_EXPAND
@ BRUSH_SMEAR_DEFORM_DRAG
Object is a sort of wrapper for general info.
BPy_StructRNA * depsgraph
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
void tag_positions_changed(const IndexMask &node_mask)
Definition pbvh.cc:635
Span< NodeT > nodes() const
void flush_bounds_to_parents()
Definition pbvh.cc:1306
void foreach_index(Fn &&fn) const
IndexRange grid_range(const int grid_area, const int grid)
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
void update_node_bounds_grids(int grid_area, Span< float3 > positions, GridsNode &node)
Definition pbvh.cc:1283
static void calc_node(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float strength, bke::pbvh::GridsNode &node, LocalData &tls)
static void calc_node(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float strength, const bke::pbvh::GridsNode &node, LocalData &tls)
static BLI_NOINLINE void eval_all_limit_positions(const SubdivCCG &subdiv_ccg, const MutableSpan< float3 > limit_positions)
static BLI_NOINLINE void store_node_prev_displacement(const Span< float3 > limit_positions, const Span< float3 > positions, const CCGKey &key, const bke::pbvh::GridsNode &node, const MutableSpan< float3 > prev_displacement)
void do_displacement_smear_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const IndexMask &node_mask)
MutableSpan< float3 > gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span< int > grids, Vector< float3 > &positions)
void calc_factors_common_grids(const Depsgraph &depsgraph, const Brush &brush, const Object &object, Span< float3 > positions, const bke::pbvh::GridsNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6603
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7512
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T interpolate(const T &a, const T &b, const FactorT &t)
T rcp(const T &a)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
VecBase< float, 3 > float3
int smear_deform_type
int grid_size
Definition BKE_ccg.hh:33
int grid_area
Definition BKE_ccg.hh:35
struct SculptSession * sculpt
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:417
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
int to_index(const CCGKey &key) const
SubdivCCGNeighborCoords coords
blender::Array< blender::float3 > positions
struct blender::ed::sculpt_paint::StrokeCache::@002250273023223321360377071017315321037224215265 displacement_smear
i
Definition text_draw.cc:230