Blender V4.3
editors/sculpt_paint/brushes/layer.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_math_vector.h"
21#include "BLI_math_vector.hh"
22#include "BLI_task.h"
23#include "BLI_task.hh"
24
30
32
33inline namespace layer_cc {
34
43
44BLI_NOINLINE static void offset_displacement_factors(const MutableSpan<float> displacement_factors,
45 const Span<float> factors,
46 const float strength)
47{
48 for (const int i : displacement_factors.index_range()) {
49 displacement_factors[i] += factors[i] * strength * (1.05f - std::abs(displacement_factors[i]));
50 }
51}
52
61BLI_NOINLINE static void reset_displacement_factors(const MutableSpan<float> displacement_factors,
62 const Span<float> factors,
63 const float strength)
64{
65 for (const int i : displacement_factors.index_range()) {
66 displacement_factors[i] += std::abs(factors[i] * strength * displacement_factors[i]) *
67 (displacement_factors[i] > 0.0f ? -1.0f : 1.0f);
68 }
69}
70
71BLI_NOINLINE static void clamp_displacement_factors(const MutableSpan<float> displacement_factors,
72 const Span<float> masks)
73{
74 if (masks.is_empty()) {
75 for (const int i : displacement_factors.index_range()) {
76 displacement_factors[i] = std::clamp(displacement_factors[i], -1.0f, 1.0f);
77 }
78 }
79 else {
80 for (const int i : displacement_factors.index_range()) {
81 const float clamp_mask = 1.0f - masks[i];
82 displacement_factors[i] = std::clamp(displacement_factors[i], -clamp_mask, clamp_mask);
83 }
84 }
85}
86
87BLI_NOINLINE static void calc_translations(const Span<float3> orig_positions,
88 const Span<float3> orig_normals,
89 const Span<float3> positions,
90 const Span<float> displacement_factors,
91 const Span<float> factors,
92 const float height,
93 const MutableSpan<float3> r_translations)
94{
95 for (const int i : positions.index_range()) {
96 const float3 offset = orig_normals[i] * height * displacement_factors[i];
97 const float3 translation = orig_positions[i] + offset - positions[i];
98 r_translations[i] = translation * factors[i];
99 }
100}
101
102BLI_NOINLINE static void calc_translations(const Span<float3> base_positions,
103 const Span<float3> base_normals,
104 const Span<int> verts,
105 const Span<float3> positions,
106 const Span<float> displacement_factors,
107 const Span<float> factors,
108 const float height,
109 const MutableSpan<float3> r_translations)
110{
111 for (const int i : positions.index_range()) {
112 const float3 offset = base_normals[verts[i]] * height * displacement_factors[i];
113 const float3 translation = base_positions[verts[i]] + offset - positions[i];
114 r_translations[i] = translation * factors[i];
115 }
116}
117
118static void calc_faces(const Depsgraph &depsgraph,
119 const Sculpt &sd,
120 const Brush &brush,
121 const MeshAttributeData &attribute_data,
122 const Span<float3> vert_normals,
123 const bool use_persistent_base,
124 const Span<float3> persistent_base_positions,
125 const Span<float3> persistent_base_normals,
126 Object &object,
128 LocalData &tls,
129 MutableSpan<float> layer_displacement_factor,
130 const PositionDeformData &position_data)
131{
132 const SculptSession &ss = *object.sculpt;
133 const StrokeCache &cache = *ss.cache;
134
135 const Span<int> verts = node.verts();
136 const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
137 const MutableSpan positions = gather_data_mesh(position_data.eval, verts, tls.positions);
138
139 tls.factors.resize(verts.size());
140 const MutableSpan<float> factors = tls.factors;
141 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
142 filter_region_clip_factors(ss, positions, factors);
143 if (brush.flag & BRUSH_FRONTFACE) {
144 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
145 }
146
147 tls.distances.resize(verts.size());
148 const MutableSpan<float> distances = tls.distances;
150 ss, orig_data.positions, eBrushFalloffShape(brush.falloff_shape), distances);
151 filter_distances_with_radius(cache.radius, distances, factors);
152 apply_hardness_to_distances(cache, distances);
153 calc_brush_strength_factors(cache, brush, distances, factors);
154
155 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
156
157 calc_brush_texture_factors(ss, brush, positions, factors);
158
159 if (attribute_data.mask.is_empty()) {
160 tls.masks.clear();
161 }
162 else {
163 tls.masks.resize(verts.size());
164 gather_data_mesh(attribute_data.mask, verts, tls.masks.as_mutable_span());
165 }
166 const MutableSpan<float> masks = tls.masks;
167
168 tls.displacement_factors.resize(verts.size());
169 const MutableSpan<float> displacement_factors = tls.displacement_factors;
170 gather_data_mesh(layer_displacement_factor.as_span(), verts, displacement_factors);
171
172 if (use_persistent_base) {
173 if (cache.invert) {
174 reset_displacement_factors(displacement_factors, tls.factors, cache.bstrength);
175 }
176 else {
177 offset_displacement_factors(displacement_factors, tls.factors, cache.bstrength);
178 }
179 clamp_displacement_factors(displacement_factors, masks);
180
181 scatter_data_mesh(displacement_factors.as_span(), verts, layer_displacement_factor);
182
183 tls.translations.resize(verts.size());
184 const MutableSpan<float3> translations = tls.translations;
185 calc_translations(persistent_base_positions,
186 persistent_base_normals,
187 verts,
188 positions,
189 displacement_factors,
190 tls.factors,
191 brush.height,
192 translations);
193
194 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
195 position_data.deform(translations, verts);
196 }
197 else {
198 offset_displacement_factors(displacement_factors, tls.factors, cache.bstrength);
199 clamp_displacement_factors(displacement_factors, masks);
200
201 scatter_data_mesh(displacement_factors.as_span(), verts, layer_displacement_factor);
202
203 tls.translations.resize(verts.size());
204 const MutableSpan<float3> translations = tls.translations;
206 orig_data.normals,
207 positions,
208 displacement_factors,
209 tls.factors,
210 brush.height,
211 translations);
212
213 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
214 position_data.deform(translations, verts);
215 }
216}
217
218static void calc_grids(const Depsgraph &depsgraph,
219 const Sculpt &sd,
220 const Brush &brush,
221 Object &object,
223 LocalData &tls,
224 MutableSpan<float> layer_displacement_factor)
225{
226 SculptSession &ss = *object.sculpt;
227 const StrokeCache &cache = *ss.cache;
228 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
229 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
230
231 const Span<int> grids = node.grids();
232 const OrigPositionData orig_data = orig_position_data_get_grids(object, node);
233 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
234
235 tls.factors.resize(positions.size());
236 const MutableSpan<float> factors = tls.factors;
237 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
238 filter_region_clip_factors(ss, positions, factors);
239 if (brush.flag & BRUSH_FRONTFACE) {
240 calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
241 }
242
243 tls.distances.resize(positions.size());
244 const MutableSpan<float> distances = tls.distances;
246 ss, orig_data.positions, eBrushFalloffShape(brush.falloff_shape), distances);
247 filter_distances_with_radius(cache.radius, distances, factors);
248 apply_hardness_to_distances(cache, distances);
249 calc_brush_strength_factors(cache, brush, distances, factors);
250
251 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
252
253 calc_brush_texture_factors(ss, brush, positions, factors);
254
255 const MutableSpan<float> displacement_factors = gather_data_grids(
256 subdiv_ccg, layer_displacement_factor.as_span(), grids, tls.displacement_factors);
257
258 offset_displacement_factors(displacement_factors, tls.factors, cache.bstrength);
259 if (key.has_mask) {
260 tls.masks.resize(positions.size());
261 mask::gather_mask_grids(subdiv_ccg, grids, tls.masks);
262 }
263 else {
264 tls.masks.clear();
265 }
266 clamp_displacement_factors(displacement_factors, tls.masks);
267
268 scatter_data_grids(subdiv_ccg, displacement_factors.as_span(), grids, layer_displacement_factor);
269
270 tls.translations.resize(positions.size());
271 const MutableSpan<float3> translations = tls.translations;
273 orig_data.normals,
274 positions,
275 displacement_factors,
276 tls.factors,
277 brush.height,
278 translations);
279
280 clip_and_lock_translations(sd, ss, positions, translations);
281 apply_translations(translations, grids, subdiv_ccg);
282}
283
284static void calc_bmesh(const Depsgraph &depsgraph,
285 const Sculpt &sd,
286 const Brush &brush,
287 Object &object,
289 LocalData &tls,
290 MutableSpan<float> layer_displacement_factor)
291{
292 SculptSession &ss = *object.sculpt;
293 const StrokeCache &cache = *ss.cache;
294
296
297 Array<float3> orig_positions(verts.size());
298 Array<float3> orig_normals(verts.size());
299 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
300
301 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
302
303 tls.factors.resize(verts.size());
304 const MutableSpan<float> factors = tls.factors;
306 filter_region_clip_factors(ss, positions, factors);
307 if (brush.flag & BRUSH_FRONTFACE) {
308 calc_front_face(cache.view_normal_symm, verts, factors);
309 }
310
311 tls.distances.resize(verts.size());
312 const MutableSpan<float> distances = tls.distances;
313 calc_brush_distances(ss, orig_positions, eBrushFalloffShape(brush.falloff_shape), distances);
314 filter_distances_with_radius(cache.radius, distances, factors);
315 apply_hardness_to_distances(cache, distances);
316 calc_brush_strength_factors(cache, brush, distances, factors);
317
318 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
319
320 calc_brush_texture_factors(ss, brush, positions, factors);
321
322 const MutableSpan<float> displacement_factors = gather_data_bmesh(
323 layer_displacement_factor.as_span(), verts, tls.displacement_factors);
324
325 offset_displacement_factors(displacement_factors, tls.factors, cache.bstrength);
326
327 tls.masks.resize(verts.size());
328 const MutableSpan<float> masks = tls.masks;
329 mask::gather_mask_bmesh(*ss.bm, verts, masks);
330 clamp_displacement_factors(displacement_factors, masks);
331
332 scatter_data_bmesh(displacement_factors.as_span(), verts, layer_displacement_factor);
333
334 tls.translations.resize(verts.size());
335 const MutableSpan<float3> translations = tls.translations;
336 calc_translations(orig_positions,
337 orig_normals,
338 positions,
339 displacement_factors,
340 tls.factors,
341 brush.height,
342 translations);
343
344 clip_and_lock_translations(sd, ss, positions, translations);
345 apply_translations(translations, verts);
346}
347
348} // namespace layer_cc
349
350void do_layer_brush(const Depsgraph &depsgraph,
351 const Sculpt &sd,
352 Object &object,
353 const IndexMask &node_mask)
354{
355 SculptSession &ss = *object.sculpt;
356 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
357 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
358
360 switch (pbvh.type()) {
362 Mesh &mesh = *static_cast<Mesh *>(object.data);
363 const PositionDeformData position_data(depsgraph, object);
364 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
365
366 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
367 const MeshAttributeData attribute_data(attributes);
368 const VArraySpan persistent_position = *attributes.lookup<float3>(".sculpt_persistent_co",
370 const VArraySpan persistent_normal = *attributes.lookup<float3>(".sculpt_persistent_no",
372
373 bke::SpanAttributeWriter<float> persistent_disp_attr;
374 bool use_persistent_base = false;
375 MutableSpan<float> displacement;
376 if (brush.flag & BRUSH_PERSISTENT) {
377 if (!persistent_position.is_empty() && !persistent_normal.is_empty()) {
378 persistent_disp_attr = attributes.lookup_or_add_for_write_span<float>(
379 ".sculpt_persistent_disp", bke::AttrDomain::Point);
380 if (persistent_disp_attr) {
381 use_persistent_base = true;
382 displacement = persistent_disp_attr.span;
383 }
384 }
385 }
386
387 if (displacement.is_empty()) {
390 0.0f);
391 }
392 displacement = ss.cache->layer_displacement_factor;
393 }
394
396 node_mask.foreach_index(GrainSize(1), [&](const int i) {
397 LocalData &tls = all_tls.local();
399 sd,
400 brush,
401 attribute_data,
402 vert_normals,
403 use_persistent_base,
404 persistent_position,
405 persistent_normal,
406 object,
407 nodes[i],
408 tls,
409 displacement,
410 position_data);
411 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
412 });
413 persistent_disp_attr.finish();
414 break;
415 }
417 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
418 MutableSpan<float3> positions = subdiv_ccg.positions;
420 ss.cache->layer_displacement_factor = Array<float>(positions.size(), 0.0f);
421 }
422 const MutableSpan<float> displacement = ss.cache->layer_displacement_factor;
424 node_mask.foreach_index(GrainSize(1), [&](const int i) {
425 LocalData &tls = all_tls.local();
426 calc_grids(depsgraph, sd, brush, object, nodes[i], tls, displacement);
427 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
428 });
429 break;
430 }
434 }
435 const MutableSpan<float> displacement = ss.cache->layer_displacement_factor;
437 node_mask.foreach_index(GrainSize(1), [&](const int i) {
438 LocalData &tls = all_tls.local();
439 calc_bmesh(depsgraph, sd, brush, object, nodes[i], tls, displacement);
441 });
442 break;
443 }
444 }
445 pbvh.tag_positions_changed(node_mask);
447}
448
449} // 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
@ BRUSH_PERSISTENT
eBrushFalloffShape
Object is a sort of wrapper for general info.
bool is_empty() const
Definition BLI_array.hh:253
constexpr bool is_empty() const
Definition BLI_span.hh:510
constexpr Span< T > as_span() const
Definition BLI_span.hh:662
constexpr IndexRange index_range() const
Definition BLI_span.hh:671
constexpr bool is_empty() const
Definition BLI_span.hh:261
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_node_bounds_bmesh(BMeshNode &node)
Definition pbvh.cc:1095
void update_node_bounds_mesh(Span< float3 > positions, MeshNode &node)
Definition pbvh.cc:1075
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2502
void update_node_bounds_grids(int grid_area, Span< float3 > positions, GridsNode &node)
Definition pbvh.cc:1084
void flush_bounds_to_parents(Tree &pbvh)
Definition pbvh.cc:1132
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 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_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const float4 &test_plane, const float strength, const MeshAttributeData &attribute_data, const Span< float3 > vert_normals, const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const PositionDeformData &position_data)
Definition clay.cc:58
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 BLI_NOINLINE void fill_factor_from_hide_and_mask(const Mesh &mesh, const Span< int > face_indices, const MutableSpan< float > r_factors)
static BLI_NOINLINE void offset_displacement_factors(const MutableSpan< float > displacement_factors, const Span< float > factors, const float strength)
static BLI_NOINLINE void clamp_displacement_factors(const MutableSpan< float > displacement_factors, const Span< float > masks)
static void calc_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const MeshAttributeData &attribute_data, const Span< float3 > vert_normals, const bool use_persistent_base, const Span< float3 > persistent_base_positions, const Span< float3 > persistent_base_normals, Object &object, bke::pbvh::MeshNode &node, LocalData &tls, MutableSpan< float > layer_displacement_factor, const PositionDeformData &position_data)
static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, bke::pbvh::BMeshNode &node, LocalData &tls, MutableSpan< float > layer_displacement_factor)
static BLI_NOINLINE void reset_displacement_factors(const MutableSpan< float > displacement_factors, const Span< float > factors, const float strength)
static BLI_NOINLINE void calc_translations(const Span< float3 > orig_positions, const Span< float3 > orig_normals, const Span< float3 > positions, const Span< float > displacement_factors, const Span< float > factors, const float height, const MutableSpan< float3 > r_translations)
static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, bke::pbvh::GridsNode &node, LocalData &tls, MutableSpan< float > layer_displacement_factor)
static BLI_NOINLINE void clamp_mask(const MutableSpan< float > masks)
void gather_mask_bmesh(const BMesh &bm, const Set< BMVert *, 0 > &verts, const MutableSpan< float > r_mask)
void gather_mask_grids(const SubdivCCG &subdiv_ccg, const Span< int > grids, const MutableSpan< float > r_mask)
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 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 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 do_layer_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6082
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
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
int SCULPT_vertex_count_get(const Object &object)
Definition sculpt.cc:153
char falloff_shape
float height
int has_mask
Definition BKE_ccg.hh:48
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
blender::Array< blender::float3 > positions
std::unique_ptr< auto_mask::Cache > automasking