Blender V5.0
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_mesh.hh"
13#include "BKE_paint.hh"
14#include "BKE_paint_bvh.hh"
15#include "BKE_subdiv_ccg.hh"
16
17#include "BLI_array.hh"
19#include "BLI_task.hh"
20
26
27#include "bmesh.hh"
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
58
60 const bke::pbvh::MeshNode &node,
61 Object &object,
62 LocalData &tls,
63 const Span<float> factors,
64 const Span<float3> new_positions,
65 const PositionDeformData &position_data)
66{
67 SculptSession &ss = *object.sculpt;
68
69 const Span<int> verts = node.verts();
70
71 tls.translations.resize(verts.size());
72 const MutableSpan<float3> translations = tls.translations;
73 translations_from_new_positions(new_positions, verts, position_data.eval, translations);
74 scale_translations(translations, factors);
75
76 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
77 position_data.deform(translations, verts);
78}
79
80BLI_NOINLINE static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
81 const Sculpt &sd,
82 const Brush &brush,
83 Object &object,
84 const IndexMask &node_mask,
85 const float brush_strength)
86{
87 const SculptSession &ss = *object.sculpt;
90 Mesh &mesh = *static_cast<Mesh *>(object.data);
91 const OffsetIndices faces = mesh.faces();
92 const Span<int> corner_verts = mesh.corner_verts();
93 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
94 const MeshAttributeData attribute_data(mesh);
95
96 const PositionDeformData position_data(depsgraph, object);
97 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
98
99 Array<int> node_offset_data;
100 const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(
101 nodes, node_mask, node_offset_data);
102 Array<float3> new_positions(node_vert_offsets.total_size());
103 Array<float> all_factors(node_vert_offsets.total_size());
104 Array<float> all_distances(node_vert_offsets.total_size());
105
107
108 /* Calculate the new positions into a separate array in a separate loop because multiple loops
109 * are updated in parallel. Without this there would be non-threadsafe access to changing
110 * positions in other bke::pbvh::Tree nodes. */
111 for (const float strength : iteration_strengths(brush_strength)) {
112 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
113 LocalData &tls = all_tls.local();
114 const Span<int> verts = nodes[i].verts();
115 const MutableSpan<float> node_factors = all_factors.as_mutable_span().slice(
116 node_vert_offsets[pos]);
118 depsgraph,
119 brush,
120 object,
121 attribute_data,
122 position_data.eval,
123 vert_normals,
124 nodes[i],
125 node_factors,
126 all_distances.as_mutable_span().slice(node_vert_offsets[pos]));
127 scale_factors(node_factors, strength);
129 corner_verts,
130 vert_to_face_map,
132 attribute_data.hide_poly,
133 verts,
134 node_factors,
135 tls.neighbor_offsets,
136 tls.neighbor_data);
138 position_data.eval,
139 verts,
140 neighbors,
141 new_positions.as_mutable_span().slice(node_vert_offsets[pos]));
142 });
143
144 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
145 LocalData &tls = all_tls.local();
147 nodes[i],
148 object,
149 tls,
150 all_factors.as_mutable_span().slice(node_vert_offsets[pos]),
151 new_positions.as_span().slice(node_vert_offsets[pos]),
152 position_data);
153 });
154 }
155}
156
157static void calc_grids(const Depsgraph &depsgraph,
158 const Sculpt &sd,
160 const Span<int> corner_verts,
161 const BitSpan boundary_verts,
162 Object &object,
163 const Brush &brush,
164 const float strength,
165 const bke::pbvh::GridsNode &node,
166 LocalData &tls)
167{
168 SculptSession &ss = *object.sculpt;
169 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
170
171 const Span<int> grids = node.grids();
172 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
173
174 calc_factors_common_grids(depsgraph, brush, object, positions, node, tls.factors, tls.distances);
175
176 scale_factors(tls.factors, strength);
177
178 tls.new_positions.resize(positions.size());
179 const MutableSpan<float3> new_positions = tls.new_positions;
181 faces, corner_verts, boundary_verts, subdiv_ccg, grids, tls.factors, new_positions);
182
183 tls.translations.resize(positions.size());
184 const MutableSpan<float3> translations = tls.translations;
185 translations_from_new_positions(new_positions, positions, translations);
186 scale_translations(translations, tls.factors);
187
188 clip_and_lock_translations(sd, ss, positions, translations);
189 apply_translations(translations, grids, subdiv_ccg);
190}
191
192static void calc_bmesh(const Depsgraph &depsgraph,
193 const Sculpt &sd,
194 Object &object,
195 const Brush &brush,
196 const float strength,
198 LocalData &tls)
199{
200 SculptSession &ss = *object.sculpt;
201
203 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
204
205 calc_factors_common_bmesh(depsgraph, brush, object, positions, node, tls.factors, tls.distances);
206
207 scale_factors(tls.factors, strength);
208
209 tls.new_positions.resize(verts.size());
210 const MutableSpan<float3> new_positions = tls.new_positions;
212
213 tls.translations.resize(verts.size());
214 const MutableSpan<float3> translations = tls.translations;
215 translations_from_new_positions(new_positions, positions, translations);
216 scale_translations(translations, tls.factors);
217
218 clip_and_lock_translations(sd, ss, positions, translations);
219 apply_translations(translations, verts);
220}
221
222} // namespace smooth_cc
223
224void do_smooth_brush(const Depsgraph &depsgraph,
225 const Sculpt &sd,
226 Object &object,
227 const IndexMask &node_mask,
228 const float brush_strength)
229{
230 SculptSession &ss = *object.sculpt;
231 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
232 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
233
235
236 switch (pbvh.type()) {
238 do_smooth_brush_mesh(depsgraph, sd, brush, object, node_mask, brush_strength);
239 break;
241 const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
242 const OffsetIndices faces = base_mesh.faces();
243 const Span<int> corner_verts = base_mesh.corner_verts();
244
246 for (const float strength : iteration_strengths(brush_strength)) {
248 node_mask.foreach_index(GrainSize(1), [&](const int i) {
249 LocalData &tls = all_tls.local();
251 sd,
252 faces,
253 corner_verts,
255 object,
256 brush,
257 strength,
258 nodes[i],
259 tls);
260 });
261 }
262 break;
263 }
267 for (const float strength : iteration_strengths(brush_strength)) {
269 node_mask.foreach_index(GrainSize(1), [&](const int i) {
270 LocalData &tls = all_tls.local();
271 calc_bmesh(depsgraph, sd, object, brush, strength, nodes[i], tls);
272 });
273 }
274 break;
275 }
276 }
277 pbvh.tag_positions_changed(node_mask);
278 pbvh.update_bounds(depsgraph, object);
279}
280
281} // namespace blender::ed::sculpt_paint::brushes
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:650
A BVH for high poly meshes.
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:53
#define BLI_NOINLINE
Object is a sort of wrapper for general info.
BPy_StructRNA * depsgraph
Span< T > as_span() const
Definition BLI_array.hh:243
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:248
constexpr int64_t size() const
Definition BLI_span.hh:493
void tag_positions_changed(const IndexMask &node_mask)
Definition pbvh.cc:635
Span< NodeT > nodes() const
void update_bounds(const Depsgraph &depsgraph, const Object &object)
Definition pbvh.cc:1386
void foreach_index(Fn &&fn) const
nullptr float
static float verts[][3]
uint pos
int count
static char faces[256]
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:1059
void ensure_boundary_info(Object &object)
Definition sculpt.cc:6073
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)
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:93
static std::array< float, 4 > iteration_strengths(const float strength, const int stroke_iteration)
Definition relax.cc:90
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:80
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:192
static BLI_NOINLINE void apply_positions_faces(const Sculpt &sd, const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const Span< float > factors, const Span< float3 > new_positions, const PositionDeformData &position_data)
Definition smooth.cc:59
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:157
static Vector< float > iteration_strengths(const float strength)
Definition smooth.cc:33
void do_smooth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask, float brush_strength)
Definition smooth.cc:224
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 GroupedSpan< int > vert_neighbors, const MutableSpan< T > dst)
void neighbor_position_average_interior_bmesh(const Set< BMVert *, 0 > &verts, const Span< float > factors, 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:6367
void vert_random_access_ensure(Object &object)
Definition sculpt.cc:141
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 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:6512
void scale_translations(MutableSpan< float3 > translations, Span< float > factors)
Definition sculpt.cc:7495
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7512
void translations_from_new_positions(Span< float3 > new_positions, Span< int > verts, Span< float3 > old_positions, MutableSpan< float3 > translations)
Definition sculpt.cc:7542
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7335
OffsetIndices< int > create_node_vert_offsets(Span< bke::pbvh::MeshNode > nodes, const IndexMask &node_mask, Array< int > &node_data)
Definition sculpt.cc:7563
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:7268
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:6637
GroupedSpan< int > 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, Vector< int > &r_offset_data, Vector< int > &r_data)
Definition sculpt.cc:7739
static float brush_strength(const Sculpt &sd, const blender::ed::sculpt_paint::StrokeCache &cache, const float feather, const PaintModeSettings &)
Definition sculpt.cc:2175
SculptVertexInfo vertex_info
Definition BKE_paint.hh:462
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
blender::BitVector boundary
Definition BKE_paint.hh:334
i
Definition text_draw.cc:230