Blender V4.3
editors/sculpt_paint/brushes/mask.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_pbvh.hh"
13#include "BKE_subdiv_ccg.hh"
14
15#include "BLI_array.hh"
17#include "BLI_math_vector.hh"
18#include "BLI_span.hh"
19#include "BLI_task.h"
20
26
28inline namespace mask_cc {
29
37
38BLI_NOINLINE static void apply_factors(const float strength,
39 const Span<float> current_masks,
40 const Span<float> factors,
41 const MutableSpan<float> masks)
42{
43 BLI_assert(current_masks.size() == masks.size());
44 BLI_assert(factors.size() == masks.size());
45 for (const int i : masks.index_range()) {
46 masks[i] += factors[i] * current_masks[i] * strength;
47 }
48}
49
51{
52 for (float &mask : masks) {
53 mask = std::clamp(mask, 0.0f, 1.0f);
54 }
55}
56
57static void calc_faces(const Depsgraph &depsgraph,
58 const Brush &brush,
59 const float strength,
60 const Span<float3> positions,
61 const Span<float3> vert_normals,
62 const bke::pbvh::MeshNode &node,
63 Object &object,
64 const Span<bool> hide_vert,
65 LocalData &tls,
66 const MutableSpan<float> mask)
67{
68 SculptSession &ss = *object.sculpt;
69 const StrokeCache &cache = *ss.cache;
70
71 const Span<int> verts = node.verts();
72
73 tls.factors.resize(verts.size());
74 const MutableSpan<float> factors = tls.factors;
75 fill_factor_from_hide(hide_vert, verts, factors);
76 filter_region_clip_factors(ss, positions, verts, factors);
77 if (brush.flag & BRUSH_FRONTFACE) {
78 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
79 }
80
81 tls.distances.resize(verts.size());
82 const MutableSpan<float> distances = tls.distances;
83 calc_brush_distances(ss, positions, verts, eBrushFalloffShape(brush.falloff_shape), distances);
84 filter_distances_with_radius(cache.radius, distances, factors);
85 apply_hardness_to_distances(cache, distances);
86 calc_brush_strength_factors(cache, brush, distances, factors);
87
88 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
89
90 calc_brush_texture_factors(ss, brush, positions, verts, factors);
91
92 tls.new_masks.resize(verts.size());
93 const MutableSpan<float> new_masks = tls.new_masks;
94 gather_data_mesh(mask.as_span(), verts, new_masks);
95
96 tls.current_masks = tls.new_masks;
97 const MutableSpan<float> current_masks = tls.current_masks;
98 if (strength > 0.0f) {
99 mask::invert_mask(current_masks);
100 }
101 apply_factors(strength, current_masks, factors, new_masks);
102 clamp_mask(new_masks);
103
104 scatter_data_mesh(new_masks.as_span(), verts, mask);
105}
106
107static void calc_grids(const Depsgraph &depsgraph,
108 Object &object,
109 const Brush &brush,
110 const float strength,
112 LocalData &tls)
113{
114 SculptSession &ss = *object.sculpt;
115 const StrokeCache &cache = *ss.cache;
116 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
117
118 const Span<int> grids = node.grids();
119 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
120
121 tls.factors.resize(positions.size());
122 const MutableSpan<float> factors = tls.factors;
123 fill_factor_from_hide(subdiv_ccg, grids, factors);
124 filter_region_clip_factors(ss, positions, factors);
125 if (brush.flag & BRUSH_FRONTFACE) {
126 calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
127 }
128
129 tls.distances.resize(positions.size());
130 const MutableSpan<float> distances = tls.distances;
131 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
132 filter_distances_with_radius(cache.radius, distances, factors);
133 apply_hardness_to_distances(cache, distances);
134 calc_brush_strength_factors(cache, brush, distances, factors);
135
136 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
137
138 calc_brush_texture_factors(ss, brush, positions, factors);
139
140 tls.new_masks.resize(positions.size());
141 const MutableSpan<float> new_masks = tls.new_masks;
142 mask::gather_mask_grids(subdiv_ccg, grids, new_masks);
143
144 tls.current_masks = tls.new_masks;
145 const MutableSpan<float> current_masks = tls.current_masks;
146 if (strength > 0.0f) {
147 mask::invert_mask(current_masks);
148 }
149 apply_factors(strength, current_masks, factors, new_masks);
150 clamp_mask(new_masks);
151
152 mask::scatter_mask_grids(new_masks.as_span(), subdiv_ccg, grids);
153}
154
155static void calc_bmesh(const Depsgraph &depsgraph,
156 Object &object,
157 const Brush &brush,
158 const float strength,
160 LocalData &tls)
161{
162 SculptSession &ss = *object.sculpt;
163 const BMesh &bm = *ss.bm;
164 const StrokeCache &cache = *ss.cache;
165
167 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
168
169 tls.factors.resize(verts.size());
170 const MutableSpan<float> factors = tls.factors;
172 filter_region_clip_factors(ss, positions, factors);
173 if (brush.flag & BRUSH_FRONTFACE) {
174 calc_front_face(cache.view_normal_symm, verts, factors);
175 }
176
177 tls.distances.resize(verts.size());
178 const MutableSpan<float> distances = tls.distances;
179 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
180 filter_distances_with_radius(cache.radius, distances, factors);
181 apply_hardness_to_distances(cache, distances);
182 calc_brush_strength_factors(cache, brush, distances, factors);
183
184 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
185
186 calc_brush_texture_factors(ss, brush, positions, factors);
187
188 tls.new_masks.resize(verts.size());
189 const MutableSpan<float> new_masks = tls.new_masks;
190 mask::gather_mask_bmesh(bm, verts, new_masks);
191
192 tls.current_masks = tls.new_masks;
193 const MutableSpan<float> current_masks = tls.current_masks;
194 if (strength > 0.0f) {
195 mask::invert_mask(current_masks);
196 }
197 apply_factors(strength, current_masks, factors, new_masks);
198 clamp_mask(new_masks);
199
201}
202
203} // namespace mask_cc
204
205void do_mask_brush(const Depsgraph &depsgraph,
206 const Sculpt &sd,
207 Object &object,
208 const IndexMask &node_mask)
209{
210 SculptSession &ss = *object.sculpt;
211 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
212 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
213 const float bstrength = ss.cache->bstrength;
214
216 switch (pbvh.type()) {
219 Mesh &mesh = *static_cast<Mesh *>(object.data);
220 const Span<float3> positions = bke::pbvh::vert_positions_eval(depsgraph, object);
221 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
222
223 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
224
225 bke::SpanAttributeWriter<float> mask = attributes.lookup_or_add_for_write_span<float>(
226 ".sculpt_mask", bke::AttrDomain::Point);
227 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
228
229 node_mask.foreach_index(GrainSize(1), [&](const int i) {
230 LocalData &tls = all_tls.local();
232 brush,
233 bstrength,
234 positions,
235 vert_normals,
236 nodes[i],
237 object,
238 hide_vert,
239 tls,
240 mask.span);
241 bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]);
242 });
243 mask.finish();
244 break;
245 }
247 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
248 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
249 MutableSpan<float> masks = subdiv_ccg.masks;
251 node_mask.foreach_index(GrainSize(1), [&](const int i) {
252 LocalData &tls = all_tls.local();
253 calc_grids(depsgraph, object, brush, bstrength, nodes[i], tls);
254 bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
255 });
256 break;
257 }
259 const int mask_offset = CustomData_get_offset_named(
260 &ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
262 node_mask.foreach_index(GrainSize(1), [&](const int i) {
263 LocalData &tls = all_tls.local();
264 calc_bmesh(depsgraph, object, brush, bstrength, nodes[i], tls);
265 bke::pbvh::node_update_mask_bmesh(mask_offset, nodes[i]);
266 });
267 break;
268 }
269 }
270 pbvh.tag_masks_changed(node_mask);
271}
272
273} // namespace blender::ed::sculpt_paint
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
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_assert(a)
Definition BLI_assert.h:50
#define BLI_NOINLINE
@ BRUSH_FRONTFACE
eBrushFalloffShape
@ CD_PROP_FLOAT
Object is a sort of wrapper for general info.
ATTR_WARN_UNUSED_RESULT BMesh * bm
constexpr Span< T > as_span() const
Definition BLI_span.hh:662
constexpr int64_t size() const
Definition BLI_span.hh:253
void resize(const int64_t new_size)
Span< NodeT > nodes() const
void tag_masks_changed(const IndexMask &node_mask)
Definition pbvh.cc:586
void foreach_index(Fn &&fn) const
const Depsgraph * depsgraph
static float verts[][3]
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2846
void node_update_mask_bmesh(int mask_offset, BMeshNode &node)
Definition pbvh.cc:1277
void node_update_mask_mesh(Span< float > mask, MeshNode &node)
Definition pbvh.cc:1219
void node_update_mask_grids(const CCGKey &key, Span< float > masks, GridsNode &node)
Definition pbvh.cc:1247
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2502
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2482
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 void calc_grids(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float strength, bke::pbvh::GridsNode &node, LocalData &tls)
static BLI_NOINLINE void clamp_mask(const MutableSpan< float > masks)
static void calc_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float strength, bke::pbvh::BMeshNode &node, LocalData &tls)
static BLI_NOINLINE void apply_factors(const float strength, const Span< float > current_masks, const Span< float > factors, const MutableSpan< float > masks)
static void calc_faces(const Depsgraph &depsgraph, const Brush &brush, const float strength, const Span< float3 > positions, const Span< float3 > vert_normals, const bke::pbvh::MeshNode &node, Object &object, const Span< bool > hide_vert, LocalData &tls, const MutableSpan< float > mask)
void scatter_mask_grids(const Span< float > mask, SubdivCCG &subdiv_ccg, const Span< int > grids)
void scatter_mask_bmesh(const Span< float > mask, const BMesh &bm, const Set< BMVert *, 0 > &verts)
void gather_mask_bmesh(const BMesh &bm, const Set< BMVert *, 0 > &verts, const MutableSpan< float > r_mask)
void invert_mask(const MutableSpan< float > masks)
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 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 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 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 scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6122
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6082
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 fill_factor_from_hide(Span< bool > hide_vert, Span< int > verts, MutableSpan< float > r_factors)
Definition sculpt.cc:6442
void do_mask_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
CustomData vdata
char falloff_shape
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:427
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::Array< float > masks
std::unique_ptr< auto_mask::Cache > automasking