Blender V4.3
surface_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_pbvh.hh"
15#include "BKE_subdiv_ccg.hh"
16
17#include "BLI_array.hh"
18#include "BLI_array_utils.hh"
20#include "BLI_task.hh"
21#include "BLI_virtual_array.hh"
22
27
29
30inline namespace surface_smooth_cc {
31
41
43{
44 for (float &factor : factors) {
45 factor = std::clamp(factor, 0.0f, 1.0f);
46 }
47}
48
50 const Sculpt &sd,
51 const Brush &brush,
52 const IndexMask &node_mask,
53 Object &object,
54 const MutableSpan<float3> all_laplacian_disp)
55{
56 const SculptSession &ss = *object.sculpt;
58 const StrokeCache &cache = *ss.cache;
59 const float alpha = brush.surface_smooth_shape_preservation;
60 const float beta = brush.surface_smooth_current_vertex;
62
63 Mesh &mesh = *static_cast<Mesh *>(object.data);
64 const OffsetIndices faces = mesh.faces();
65 const Span<int> corner_verts = mesh.corner_verts();
66 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
67 const MeshAttributeData attribute_data(mesh.attributes());
68
69 const PositionDeformData position_data(depsgraph, object);
70 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
71
72 Array<int> node_offset_data;
73 const OffsetIndices node_offsets = create_node_vert_offsets(nodes, node_mask, node_offset_data);
74 Array<float> all_factors(node_offsets.total_size());
75
77 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
78 LocalData &tls = all_tls.local();
79 const Span<int> verts = nodes[i].verts();
80
81 const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
82 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
83 filter_region_clip_factors(ss, position_data.eval, verts, factors);
84 if (brush.flag & BRUSH_FRONTFACE) {
85 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
86 }
87
88 tls.distances.resize(verts.size());
89 const MutableSpan<float> distances = tls.distances;
91 ss, position_data.eval, verts, eBrushFalloffShape(brush.falloff_shape), distances);
92 filter_distances_with_radius(cache.radius, distances, factors);
93 apply_hardness_to_distances(cache, distances);
94 calc_brush_strength_factors(cache, brush, distances, factors);
95
97 depsgraph, object, cache.automasking.get(), nodes[i], verts, factors);
98
99 calc_brush_texture_factors(ss, brush, position_data.eval, verts, factors);
100
101 scale_factors(factors, cache.bstrength);
102 clamp_factors(factors);
103 });
104
105 for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) {
106 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
107 LocalData &tls = all_tls.local();
108 const Span<int> verts = nodes[i].verts();
109 const MutableSpan positions = gather_data_mesh(position_data.eval, verts, tls.positions);
110 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
111 const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
112
113 tls.vert_neighbors.resize(verts.size());
115 corner_verts,
116 vert_to_face_map,
117 attribute_data.hide_poly,
118 verts,
119 tls.vert_neighbors);
120
121 tls.average_positions.resize(verts.size());
122 const MutableSpan<float3> average_positions = tls.average_positions;
124 position_data.eval, tls.vert_neighbors, average_positions);
125
126 tls.laplacian_disp.resize(verts.size());
127 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
128 tls.translations.resize(verts.size());
129 const MutableSpan<float3> translations = tls.translations;
131 positions, orig_data.positions, average_positions, alpha, laplacian_disp, translations);
132 scale_translations(translations, factors);
133
134 scatter_data_mesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
135
136 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
137 position_data.deform(translations, verts);
138 });
139
140 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
141 LocalData &tls = all_tls.local();
142 const Span<int> verts = nodes[i].verts();
143 const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
144
145 const MutableSpan<float3> laplacian_disp = gather_data_mesh(
146 all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
147
148 tls.vert_neighbors.resize(verts.size());
150 corner_verts,
151 vert_to_face_map,
152 attribute_data.hide_poly,
153 verts,
154 tls.vert_neighbors);
155
156 tls.average_positions.resize(verts.size());
157 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
159 all_laplacian_disp.as_span(), tls.vert_neighbors, average_laplacian_disps);
160
161 tls.translations.resize(verts.size());
162 const MutableSpan<float3> translations = tls.translations;
164 laplacian_disp, average_laplacian_disps, beta, translations);
165 scale_translations(translations, factors);
166
167 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
168 position_data.deform(translations, verts);
169 });
170 }
171}
172
174 const Depsgraph &depsgraph,
175 const Sculpt &sd,
176 const Brush &brush,
177 const IndexMask &node_mask,
178 Object &object,
179 const MutableSpan<float3> all_laplacian_disp)
180{
181 const SculptSession &ss = *object.sculpt;
182 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
183 const StrokeCache &cache = *ss.cache;
184 const float alpha = brush.surface_smooth_shape_preservation;
185 const float beta = brush.surface_smooth_current_vertex;
187
188 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
189
190 Array<int> node_offset_data;
191 const OffsetIndices node_offsets = create_node_vert_offsets(
192 BKE_subdiv_ccg_key_top_level(subdiv_ccg), nodes, node_mask, node_offset_data);
193 Array<float> all_factors(node_offsets.total_size());
194
196 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
197 LocalData &tls = all_tls.local();
198 const Span<int> grids = nodes[i].grids();
199 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
200
201 const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
202 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
203 filter_region_clip_factors(ss, positions, factors);
204 if (brush.flag & BRUSH_FRONTFACE) {
205 calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
206 }
207
208 tls.distances.resize(positions.size());
209 const MutableSpan<float> distances = tls.distances;
210 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
211 filter_distances_with_radius(cache.radius, distances, factors);
212 apply_hardness_to_distances(cache, distances);
213 calc_brush_strength_factors(cache, brush, distances, factors);
214
216 depsgraph, object, cache.automasking.get(), nodes[i], grids, factors);
217
218 calc_brush_texture_factors(ss, brush, positions, factors);
219
220 scale_factors(factors, cache.bstrength);
221 clamp_factors(factors);
222 });
223
224 for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) {
225 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
226 LocalData &tls = all_tls.local();
227 const Span<int> grids = nodes[i].grids();
228 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
229 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
230 const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
231
232 tls.average_positions.resize(positions.size());
233 const MutableSpan<float3> average_positions = tls.average_positions;
235 subdiv_ccg, subdiv_ccg.positions.as_span(), grids, average_positions);
236
237 tls.laplacian_disp.resize(positions.size());
238 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
239 tls.translations.resize(positions.size());
240 const MutableSpan<float3> translations = tls.translations;
242 positions, orig_data.positions, average_positions, alpha, laplacian_disp, translations);
243 scale_translations(translations, factors);
244
245 scatter_data_grids(subdiv_ccg, laplacian_disp.as_span(), grids, all_laplacian_disp);
246
247 clip_and_lock_translations(sd, ss, positions, translations);
248 apply_translations(translations, grids, subdiv_ccg);
249 });
250
251 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
252 LocalData &tls = all_tls.local();
253 const Span<int> grids = nodes[i].grids();
254 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
255 const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
256
257 const MutableSpan<float3> laplacian_disp = gather_data_grids(
258 subdiv_ccg, all_laplacian_disp.as_span(), grids, tls.laplacian_disp);
259
260 tls.average_positions.resize(positions.size());
261 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
263 subdiv_ccg, all_laplacian_disp.as_span(), grids, average_laplacian_disps);
264
265 tls.translations.resize(positions.size());
266 const MutableSpan<float3> translations = tls.translations;
268 laplacian_disp, average_laplacian_disps, beta, translations);
269 scale_translations(translations, factors);
270
271 clip_and_lock_translations(sd, ss, positions, translations);
272 apply_translations(translations, grids, subdiv_ccg);
273 });
274 }
275}
276
278 const Depsgraph &depsgraph,
279 const Sculpt &sd,
280 const Brush &brush,
281 const IndexMask &node_mask,
282 Object &object,
283 const MutableSpan<float3> all_laplacian_disp)
284{
285 const SculptSession &ss = *object.sculpt;
286 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
287 const StrokeCache &cache = *ss.cache;
288 const float alpha = brush.surface_smooth_shape_preservation;
289 const float beta = brush.surface_smooth_current_vertex;
291
292 Array<int> node_offset_data;
294 nodes, node_mask, node_offset_data);
295 Array<float> all_factors(node_offsets.total_size());
296
298 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
299 LocalData &tls = all_tls.local();
301 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
302
303 const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
305 filter_region_clip_factors(ss, positions, factors);
306 if (brush.flag & BRUSH_FRONTFACE) {
307 calc_front_face(cache.view_normal_symm, verts, factors);
308 }
309
310 tls.distances.resize(positions.size());
311 const MutableSpan<float> distances = tls.distances;
312 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
313 filter_distances_with_radius(cache.radius, distances, factors);
314 apply_hardness_to_distances(cache, distances);
315 calc_brush_strength_factors(cache, brush, distances, factors);
316
318 depsgraph, object, cache.automasking.get(), nodes[i], verts, factors);
319
320 calc_brush_texture_factors(ss, brush, positions, factors);
321
322 scale_factors(factors, cache.bstrength);
323 clamp_factors(factors);
324 });
325
326 for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) {
327 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
328 LocalData &tls = all_tls.local();
330 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
331 Array<float3> orig_positions(verts.size());
332 Array<float3> orig_normals(verts.size());
333 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
334 const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
335
336 tls.average_positions.resize(positions.size());
337 const MutableSpan<float3> average_positions = tls.average_positions;
339
340 tls.laplacian_disp.resize(positions.size());
341 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
342 tls.translations.resize(positions.size());
343 const MutableSpan<float3> translations = tls.translations;
345 positions, orig_positions, average_positions, alpha, laplacian_disp, translations);
346 scale_translations(translations, factors);
347
348 scatter_data_bmesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
349
350 clip_and_lock_translations(sd, ss, positions, translations);
351 apply_translations(translations, verts);
352 });
353
354 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
355 LocalData &tls = all_tls.local();
357 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
358 const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
359
360 const MutableSpan<float3> laplacian_disp = gather_data_bmesh(
361 all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
362
363 tls.average_positions.resize(positions.size());
364 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
365 smooth::average_data_bmesh(all_laplacian_disp.as_span(), verts, average_laplacian_disps);
366
367 tls.translations.resize(positions.size());
368 const MutableSpan<float3> translations = tls.translations;
370 laplacian_disp, average_laplacian_disps, beta, translations);
371 scale_translations(translations, factors);
372
373 clip_and_lock_translations(sd, ss, positions, translations);
374 apply_translations(translations, verts);
375 });
376 }
377}
378
379} // namespace surface_smooth_cc
380
381void do_surface_smooth_brush(const Depsgraph &depsgraph,
382 const Sculpt &sd,
383 Object &object,
384 const IndexMask &node_mask)
385{
386 SculptSession &ss = *object.sculpt;
387 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
388 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
389
390 switch (pbvh.type()) {
393 depsgraph, sd, brush, node_mask, object, ss.cache->surface_smooth_laplacian_disp);
394 break;
397 depsgraph, sd, brush, node_mask, object, ss.cache->surface_smooth_laplacian_disp);
398 break;
399 }
403 depsgraph, sd, brush, node_mask, object, ss.cache->surface_smooth_laplacian_disp);
404 break;
405 }
406 }
407 pbvh.tag_positions_changed(node_mask);
408 bke::pbvh::update_bounds(depsgraph, object, pbvh);
409}
410
411} // 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)
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
#define BLI_NOINLINE
@ BRUSH_FRONTFACE
eBrushFalloffShape
Object is a sort of wrapper for general info.
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
constexpr Span< T > as_span() const
Definition BLI_span.hh:662
void resize(const int64_t new_size)
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
static float verts[][3]
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
void calc_grids_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, const bke::pbvh::GridsNode &node, Span< int > grids, MutableSpan< float > factors)
void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, const bke::pbvh::MeshNode &node, Span< int > verts, MutableSpan< float > factors)
static BLI_NOINLINE void fill_factor_from_hide_and_mask(const Mesh &mesh, const Span< int > face_indices, const MutableSpan< float > r_factors)
void average_data_bmesh(const Span< T > src, const Set< BMVert *, 0 > &verts, const MutableSpan< T > dst)
void surface_smooth_laplacian_step(const Span< float3 > positions, const Span< float3 > orig_positions, const Span< float3 > average_positions, const float alpha, MutableSpan< float3 > laplacian_disp, MutableSpan< float3 > translations)
void surface_smooth_displace_step(const Span< float3 > laplacian_disp, const Span< float3 > average_laplacian_disp, const float beta, const MutableSpan< float3 > translations)
void neighbor_data_average_mesh(const Span< T > src, const Span< Vector< int > > vert_neighbors, const MutableSpan< T > dst)
void average_data_grids(const SubdivCCG &subdiv_ccg, const Span< T > src, const Span< int > grids, const MutableSpan< T > dst)
void neighbor_position_average_bmesh(const Set< BMVert *, 0 > &verts, const MutableSpan< float3 > new_positions)
static BLI_NOINLINE void do_surface_smooth_brush_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const IndexMask &node_mask, Object &object, const MutableSpan< float3 > all_laplacian_disp)
static BLI_NOINLINE void do_surface_smooth_brush_grids(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const IndexMask &node_mask, Object &object, const MutableSpan< float3 > all_laplacian_disp)
static BLI_NOINLINE void clamp_factors(const MutableSpan< float > factors)
static BLI_NOINLINE void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const IndexMask &node_mask, Object &object, const MutableSpan< float3 > all_laplacian_disp)
MutableSpan< float3 > gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span< int > grids, Vector< float3 > &positions)
void scatter_data_bmesh(Span< T > node_data, const Set< BMVert *, 0 > &verts, MutableSpan< T > dst)
Definition sculpt.cc:6148
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6054
void calc_brush_strength_factors(const StrokeCache &cache, const Brush &brush, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:6889
void gather_data_grids(const SubdivCCG &subdiv_ccg, Span< T > src, Span< int > grids, MutableSpan< T > node_data)
Definition sculpt.cc:6092
void apply_hardness_to_distances(float radius, float hardness, MutableSpan< float > distances)
Definition sculpt.cc:6862
void filter_distances_with_radius(float radius, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:6772
void do_surface_smooth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
OffsetIndices< int > create_node_vert_offsets_bmesh(const Span< bke::pbvh::BMeshNode > nodes, const IndexMask &nodes_mask, Array< int > &node_data)
Definition sculpt.cc:7318
void filter_region_clip_factors(const SculptSession &ss, Span< float3 > vert_positions, Span< int > verts, MutableSpan< float > factors)
Definition sculpt.cc:6639
void gather_data_bmesh(Span< T > src, const Set< BMVert *, 0 > &verts, MutableSpan< T > node_data)
Definition sculpt.cc:6108
void calc_brush_distances(const SculptSession &ss, Span< float3 > vert_positions, Span< int > vert_indices, eBrushFalloffShape falloff_shape, MutableSpan< float > r_distances)
Definition sculpt.cc:6722
void orig_position_data_gather_bmesh(const BMLog &bm_log, const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions, MutableSpan< float3 > normals)
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 clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7022
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6122
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6958
OrigPositionData orig_position_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node)
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6082
void calc_vert_neighbors(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face, Span< bool > hide_poly, Span< int > verts, MutableSpan< Vector< int > > result)
Definition sculpt.cc:7330
OrigPositionData orig_position_data_get_grids(const Object &object, const bke::pbvh::GridsNode &node)
void calc_front_face(const float3 &view_normal, Span< float3 > normals, MutableSpan< float > factors)
Definition sculpt.cc:6581
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_brush_texture_factors(const SculptSession &ss, const Brush &brush, Span< float3 > vert_positions, Span< int > vert_indices, MutableSpan< float > factors)
Definition sculpt.cc:6898
void scatter_data_grids(const SubdivCCG &subdiv_ccg, Span< T > node_data, Span< int > grids, MutableSpan< T > dst)
Definition sculpt.cc:6132
char falloff_shape
int surface_smooth_iterations
float surface_smooth_current_vertex
float surface_smooth_shape_preservation
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:427
BMLog * bm_log
Definition BKE_paint.hh:402
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
std::unique_ptr< auto_mask::Cache > automasking
ccl_device_inline float beta(float x, float y)
Definition util/math.h:833