Blender V4.3
smooth.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_mesh_types.h"
9#include "DNA_object_types.h"
10#include "DNA_scene_types.h"
11
12#include "BKE_key.hh"
13#include "BKE_mesh.hh"
14#include "BKE_paint.hh"
15#include "BKE_pbvh.hh"
16#include "BKE_subdiv_ccg.hh"
17
18#include "BLI_array.hh"
20#include "BLI_task.hh"
21#include "BLI_virtual_array.hh"
22
28
30
31inline namespace smooth_cc {
32
33static Vector<float> iteration_strengths(const float strength)
34{
35 constexpr int max_iterations = 4;
36
37 BLI_assert_msg(strength >= 0.0f,
38 "The smooth brush expects a non-negative strength to behave properly");
39 const float clamped_strength = std::min(strength, 1.0f);
40
41 const int count = int(clamped_strength * max_iterations);
42 const float last = max_iterations * (clamped_strength - float(count) / max_iterations);
44 result.append_n_times(1.0f, count);
45 result.append(last);
46 return result;
47}
48
57
58BLI_NOINLINE static void apply_positions_faces(const Depsgraph &depsgraph,
59 const Sculpt &sd,
60 const Brush &brush,
61 const MeshAttributeData &attribute_data,
62 const Span<float3> vert_normals,
63 const bke::pbvh::MeshNode &node,
64 const float strength,
65 Object &object,
66 LocalData &tls,
67 const Span<float3> new_positions,
68 const PositionDeformData &position_data)
69{
70 SculptSession &ss = *object.sculpt;
71
72 const Span<int> verts = node.verts();
73
75 brush,
76 object,
77 attribute_data,
78 position_data.eval,
79 vert_normals,
80 node,
81 tls.factors,
82 tls.distances);
83
84 scale_factors(tls.factors, strength);
85
86 tls.translations.resize(verts.size());
87 const MutableSpan<float3> translations = tls.translations;
88 translations_from_new_positions(new_positions, verts, position_data.eval, translations);
89 scale_translations(translations, tls.factors);
90
91 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
92 position_data.deform(translations, verts);
93}
94
95BLI_NOINLINE static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
96 const Sculpt &sd,
97 const Brush &brush,
98 Object &object,
99 const IndexMask &node_mask,
100 const float brush_strength)
101{
102 const SculptSession &ss = *object.sculpt;
103 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
105 Mesh &mesh = *static_cast<Mesh *>(object.data);
106 const OffsetIndices faces = mesh.faces();
107 const Span<int> corner_verts = mesh.corner_verts();
108 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
109 const MeshAttributeData attribute_data(mesh.attributes());
110
111 const PositionDeformData position_data(depsgraph, object);
112 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
113
114 Array<int> node_offset_data;
115 const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(
116 nodes, node_mask, node_offset_data);
117 Array<float3> new_positions(node_vert_offsets.total_size());
118
120
121 /* Calculate the new positions into a separate array in a separate loop because multiple loops
122 * are updated in parallel. Without this there would be non-threadsafe access to changing
123 * positions in other bke::pbvh::Tree nodes. */
124 for (const float strength : iteration_strengths(brush_strength)) {
125 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
126 LocalData &tls = all_tls.local();
127 const Span<int> verts = nodes[i].verts();
128 tls.vert_neighbors.resize(verts.size());
130 corner_verts,
131 vert_to_face_map,
133 attribute_data.hide_poly,
134 verts,
135 tls.vert_neighbors);
137 position_data.eval,
138 verts,
139 tls.vert_neighbors,
140 new_positions.as_mutable_span().slice(node_vert_offsets[pos]));
141 });
142
143 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
144 LocalData &tls = all_tls.local();
146 sd,
147 brush,
148 attribute_data,
149 vert_normals,
150 nodes[i],
151 strength,
152 object,
153 tls,
154 new_positions.as_span().slice(node_vert_offsets[pos]),
155 position_data);
156 });
157 }
158}
159
160static void calc_grids(const Depsgraph &depsgraph,
161 const Sculpt &sd,
162 const OffsetIndices<int> faces,
163 const Span<int> corner_verts,
164 const BitSpan boundary_verts,
165 Object &object,
166 const Brush &brush,
167 const float strength,
168 const bke::pbvh::GridsNode &node,
169 LocalData &tls)
170{
171 SculptSession &ss = *object.sculpt;
172 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
173
174 const Span<int> grids = node.grids();
175 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
176
177 calc_factors_common_grids(depsgraph, brush, object, positions, node, tls.factors, tls.distances);
178
179 scale_factors(tls.factors, strength);
180
181 tls.new_positions.resize(positions.size());
182 const MutableSpan<float3> new_positions = tls.new_positions;
184 faces, corner_verts, boundary_verts, subdiv_ccg, grids, new_positions);
185
186 tls.translations.resize(positions.size());
187 const MutableSpan<float3> translations = tls.translations;
188 translations_from_new_positions(new_positions, positions, translations);
189 scale_translations(translations, tls.factors);
190
191 clip_and_lock_translations(sd, ss, positions, translations);
192 apply_translations(translations, grids, subdiv_ccg);
193}
194
195static void calc_bmesh(const Depsgraph &depsgraph,
196 const Sculpt &sd,
197 Object &object,
198 const Brush &brush,
199 const float strength,
201 LocalData &tls)
202{
203 SculptSession &ss = *object.sculpt;
204
206 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
207
208 calc_factors_common_bmesh(depsgraph, brush, object, positions, node, tls.factors, tls.distances);
209
210 scale_factors(tls.factors, strength);
211
212 tls.new_positions.resize(verts.size());
213 const MutableSpan<float3> new_positions = tls.new_positions;
215
216 tls.translations.resize(verts.size());
217 const MutableSpan<float3> translations = tls.translations;
218 translations_from_new_positions(new_positions, positions, translations);
219 scale_translations(translations, tls.factors);
220
221 clip_and_lock_translations(sd, ss, positions, translations);
222 apply_translations(translations, verts);
223}
224
225} // namespace smooth_cc
226
227void do_smooth_brush(const Depsgraph &depsgraph,
228 const Sculpt &sd,
229 Object &object,
230 const IndexMask &node_mask,
231 const float brush_strength)
232{
233 SculptSession &ss = *object.sculpt;
234 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
235 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
236
238
239 switch (pbvh.type()) {
241 do_smooth_brush_mesh(depsgraph, sd, brush, object, node_mask, brush_strength);
242 break;
244 const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
245 const OffsetIndices faces = base_mesh.faces();
246 const Span<int> corner_verts = base_mesh.corner_verts();
247
249 for (const float strength : iteration_strengths(brush_strength)) {
251 node_mask.foreach_index(GrainSize(1), [&](const int i) {
252 LocalData &tls = all_tls.local();
254 sd,
255 faces,
256 corner_verts,
258 object,
259 brush,
260 strength,
261 nodes[i],
262 tls);
263 });
264 }
265 break;
266 }
271 for (const float strength : iteration_strengths(brush_strength)) {
273 node_mask.foreach_index(GrainSize(1), [&](const int i) {
274 LocalData &tls = all_tls.local();
275 calc_bmesh(depsgraph, sd, object, brush, strength, nodes[i], tls);
276 });
277 }
278 break;
279 }
280 }
281 pbvh.tag_positions_changed(node_mask);
282 bke::pbvh::update_bounds(depsgraph, object, pbvh);
283}
284
285} // namespace blender::ed::sculpt_paint
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:654
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_unique_verts(blender::bke::pbvh::BMeshNode *node)
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define BLI_NOINLINE
Object is a sort of wrapper for general info.
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
#define BM_VERT
Span< T > as_span() const
Definition BLI_array.hh:232
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:237
void append_n_times(const T &value, const int64_t n)
void tag_positions_changed(const IndexMask &node_mask)
Definition pbvh.cc:549
Span< NodeT > nodes() const
void deform(MutableSpan< float3 > translations, Span< int > verts) const
Definition sculpt.cc:7139
void foreach_index(Fn &&fn) const
const Depsgraph * depsgraph
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static float verts[][3]
int count
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2846
void update_bounds(const Depsgraph &depsgraph, const Object &object, Tree &pbvh)
Definition pbvh.cc:1183
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2502
static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float3 &direction, const float strength, bke::pbvh::BMeshNode &node, LocalData &tls)
void ensure_boundary_info(Object &object)
Definition sculpt.cc:5770
static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float4 &test_plane, const float strength, bke::pbvh::GridsNode &node, LocalData &tls)
Definition clay.cc:95
static std::array< float, 4 > iteration_strengths(const float strength, const int stroke_iteration)
Definition relax.cc:92
static Vector< float > iteration_strengths(const float strength)
Definition smooth.cc:33
static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float strength, bke::pbvh::BMeshNode &node, LocalData &tls)
Definition smooth.cc:195
static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, const OffsetIndices< int > faces, const Span< int > corner_verts, const BitSpan boundary_verts, Object &object, const Brush &brush, const float strength, const bke::pbvh::GridsNode &node, LocalData &tls)
Definition smooth.cc:160
static BLI_NOINLINE void apply_positions_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const MeshAttributeData &attribute_data, const Span< float3 > vert_normals, const bke::pbvh::MeshNode &node, const float strength, Object &object, LocalData &tls, const Span< float3 > new_positions, const PositionDeformData &position_data)
Definition smooth.cc:58
static BLI_NOINLINE void do_smooth_brush_mesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, const IndexMask &node_mask, const float brush_strength)
Definition smooth.cc:95
void neighbor_position_average_interior_grids(const OffsetIndices< int > faces, const Span< int > corner_verts, const BitSpan boundary_verts, const SubdivCCG &subdiv_ccg, const Span< int > grids, const MutableSpan< float3 > new_positions)
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)
void neighbor_position_average_interior_bmesh(const Set< BMVert *, 0 > &verts, const MutableSpan< float3 > new_positions)
MutableSpan< float3 > gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span< int > grids, Vector< float3 > &positions)
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6054
void calc_vert_neighbors_interior(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face, BitSpan boundary_verts, Span< bool > hide_poly, Span< int > verts, MutableSpan< Vector< int > > result)
Definition sculpt.cc:7385
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:6270
void calc_factors_common_mesh_indexed(const Depsgraph &depsgraph, const Brush &brush, const Object &object, const MeshAttributeData &attribute_data, Span< float3 > vert_positions, Span< float3 > vert_normals, const bke::pbvh::MeshNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6199
void scale_translations(MutableSpan< float3 > translations, Span< float > factors)
Definition sculpt.cc:7210
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7227
void translations_from_new_positions(Span< float3 > new_positions, Span< int > verts, Span< float3 > old_positions, MutableSpan< float3 > translations)
Definition sculpt.cc:7257
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7022
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6958
void do_smooth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask, const float brush_strength)
Definition smooth.cc:227
OffsetIndices< int > create_node_vert_offsets(const Span< bke::pbvh::MeshNode > nodes, const IndexMask &nodes_mask, Array< int > &node_data)
Definition sculpt.cc:7296
void calc_factors_common_bmesh(const Depsgraph &depsgraph, const Brush &brush, const Object &object, Span< float3 > positions, bke::pbvh::BMeshNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6304
static float brush_strength(const Sculpt &sd, const blender::ed::sculpt_paint::StrokeCache &cache, const float feather, const UnifiedPaintSettings &ups, const PaintModeSettings &)
Definition sculpt.cc:2067
SculptVertexInfo vertex_info
Definition BKE_paint.hh:458
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::BitVector boundary
Definition BKE_paint.hh:351