Blender V4.3
sculpt_mask_init.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "MEM_guardedalloc.h"
10
12#include "BLI_hash.h"
13#include "BLI_task.h"
14#include "BLI_time.h"
15
16#include "DNA_object_types.h"
17
18#include "BKE_ccg.hh"
19#include "BKE_context.hh"
20#include "BKE_layer.hh"
21#include "BKE_mesh.hh"
22#include "BKE_multires.hh"
23#include "BKE_paint.hh"
24#include "BKE_pbvh_api.hh"
25#include "BKE_subdiv_ccg.hh"
26
27#include "WM_api.hh"
28#include "WM_types.hh"
29
30#include "RNA_access.hh"
31#include "RNA_define.hh"
32
33#include "paint_intern.hh"
34#include "paint_mask.hh"
35#include "sculpt_face_set.hh"
36#include "sculpt_hide.hh"
37#include "sculpt_intern.hh"
38#include "sculpt_islands.hh"
39#include "sculpt_undo.hh"
40
41#include "bmesh.hh"
42
44
45enum class InitMode {
46 Random,
47 FaceSet,
48 Island,
49};
50
51void write_mask_mesh(const Depsgraph &depsgraph,
52 Object &object,
53 const IndexMask &node_mask,
55{
56 Mesh &mesh = *static_cast<Mesh *>(object.data);
57 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
58 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
59
60 undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask);
61
62 bke::SpanAttributeWriter mask = attributes.lookup_or_add_for_write_span<float>(
63 ".sculpt_mask", bke::AttrDomain::Point);
64 if (!mask) {
65 return;
66 }
70 node_mask.foreach_index(GrainSize(1), [&](const int i) {
71 Vector<int> &index_data = all_index_data.local();
72 write_fn(mask.span, hide::node_visible_verts(nodes[i], hide_vert, index_data));
73 bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]);
74 });
75 pbvh.tag_masks_changed(node_mask);
76 mask.finish();
77}
78
79static void init_mask_grids(
80 Main &bmain,
81 Scene &scene,
82 Depsgraph &depsgraph,
83 Object &object,
84 const IndexMask &node_mask,
85 FunctionRef<void(const BitGroupVector<> &, int, MutableSpan<float>)> write_fn)
86{
88 BKE_sculpt_mask_layers_ensure(&depsgraph, &bmain, &object, mmd);
89
90 SculptSession &ss = *object.sculpt;
93 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
94 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
95 MutableSpan<float> masks = subdiv_ccg.masks;
96 const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
97
98 undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask);
99
100 node_mask.foreach_index(GrainSize(1), [&](const int i) {
101 for (const int grid : nodes[i].grids()) {
102 write_fn(grid_hidden, grid, masks.slice(bke::ccg::grid_range(key, grid)));
103 }
104 bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
105 });
106 pbvh.tag_masks_changed(node_mask);
108}
109
111{
112 const View3D *v3d = CTX_wm_view3d(C);
113 const Base *base = CTX_data_active_base(C);
114 if (!BKE_base_is_visible(v3d, base)) {
115 return OPERATOR_CANCELLED;
116 }
117 const Scene &scene = *CTX_data_scene(C);
119 SculptSession &ss = *ob.sculpt;
121
123
125 IndexMaskMemory memory;
126 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
127 if (node_mask.is_empty()) {
128 return OPERATOR_CANCELLED;
129 }
130
131 undo::push_begin(scene, ob, op);
132
133 const InitMode mode = InitMode(RNA_enum_get(op->ptr, "mode"));
134 const int seed = BLI_time_now_seconds();
135
136 switch (pbvh.type()) {
138 switch (mode) {
139 case InitMode::Random:
140 write_mask_mesh(depsgraph, ob, node_mask, [&](MutableSpan<float> mask, Span<int> verts) {
141 for (const int vert : verts) {
142 mask[vert] = BLI_hash_int_01(vert + seed);
143 }
144 });
145 break;
146 case InitMode::FaceSet: {
147 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
148 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
149 const bke::AttributeAccessor attributes = mesh.attributes();
150 const VArraySpan face_sets = *attributes.lookup_or_default<int>(
151 ".sculpt_face_set", bke::AttrDomain::Face, 1);
152
153 write_mask_mesh(depsgraph, ob, node_mask, [&](MutableSpan<float> mask, Span<int> verts) {
154 for (const int vert : verts) {
155 const int face_set = face_set::vert_face_set_get(vert_to_face_map, face_sets, vert);
156 mask[vert] = BLI_hash_int_01(face_set + seed);
157 }
158 });
159 break;
160 }
161 case InitMode::Island:
163 write_mask_mesh(depsgraph, ob, node_mask, [&](MutableSpan<float> mask, Span<int> verts) {
164 for (const int vert : verts) {
165 const int island = islands::vert_id_get(ss, vert);
166 mask[vert] = BLI_hash_int_01(island + seed);
167 }
168 });
169 break;
170 }
171 break;
172 }
174 Main &bmain = *CTX_data_main(C);
175 Scene &scene = *CTX_data_scene(C);
176 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
177 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
178 switch (mode) {
179 case InitMode::Random: {
180 init_mask_grids(bmain,
181 scene,
182 depsgraph,
183 ob,
184 node_mask,
185 [&](const BitGroupVector<> &grid_hidden,
186 const int grid_index,
187 MutableSpan<float> grid_masks) {
188 const int verts_start = grid_index * key.grid_area;
190 key, grid_hidden, grid_index, [&](const int i) {
191 grid_masks[i] = BLI_hash_int_01(verts_start + i + seed);
192 });
193 });
194 break;
195 }
196 case InitMode::FaceSet: {
197 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
198 const bke::AttributeAccessor attributes = mesh.attributes();
199 const VArraySpan face_sets = *attributes.lookup_or_default<int>(
200 ".sculpt_face_set", bke::AttrDomain::Face, 1);
201 const Span<int> grid_to_face = subdiv_ccg.grid_to_face_map;
203 bmain,
204 scene,
205 depsgraph,
206 ob,
207 node_mask,
208 [&](const BitGroupVector<> &grid_hidden,
209 const int grid_index,
210 MutableSpan<float> grid_masks) {
211 const int face_set = face_sets[grid_to_face[grid_index]];
212 const float value = BLI_hash_int_01(face_set + seed);
214 key, grid_hidden, grid_index, [&](const int i) { grid_masks[i] = value; });
215 });
216 break;
217 }
218 case InitMode::Island: {
220 init_mask_grids(bmain,
221 scene,
222 depsgraph,
223 ob,
224 node_mask,
225 [&](const BitGroupVector<> &grid_hidden,
226 const int grid_index,
227 MutableSpan<float> grid_masks) {
228 const int verts_start = grid_index * key.grid_area;
230 key, grid_hidden, grid_index, [&](const int i) {
231 const int island = islands::vert_id_get(ss, verts_start + i);
232 grid_masks[i] = BLI_hash_int_01(island + seed);
233 });
234 });
235 break;
236 }
237 }
238 break;
239 }
242 const int offset = CustomData_get_offset_named(&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
243 node_mask.foreach_index(GrainSize(1), [&](const int i) {
244 for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
246 continue;
247 }
248 switch (mode) {
249 case InitMode::Random:
251 break;
252 case InitMode::FaceSet: {
253 BM_ELEM_CD_SET_FLOAT(vert, offset, 0.0f);
254 break;
255 }
256 case InitMode::Island:
258 vert,
259 offset,
261 break;
262 }
263 }
264 bke::pbvh::node_update_mask_bmesh(offset, nodes[i]);
265 });
266 pbvh.tag_masks_changed(node_mask);
267 break;
268 }
269 }
270
271 undo::push_end(ob);
272
274 return OPERATOR_FINISHED;
275}
276
278{
279 ot->name = "Init Mask";
280 ot->description = "Creates a new mask for the entire mesh";
281 ot->idname = "SCULPT_OT_mask_init";
282
285
287
288 static EnumPropertyItem modes[] = {
289 {int(InitMode::Random), "RANDOM_PER_VERTEX", 0, "Random per Vertex", ""},
290 {int(InitMode::FaceSet), "RANDOM_PER_FACE_SET", 0, "Random per Face Set", ""},
291 {int(InitMode::Island), "RANDOM_PER_LOOSE_PART", 0, "Random per Loose Part", ""},
292 {0, nullptr, 0, nullptr, nullptr},
293 };
294 RNA_def_enum(ot->srna, "mode", modes, int(InitMode::Random), "Mode", "");
295}
296
297} // namespace blender::ed::sculpt_paint::mask
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
Main * CTX_data_main(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
bool BKE_base_is_visible(const View3D *v3d, const Base *base)
MultiresModifierData * BKE_sculpt_multires_active(const Scene *scene, Object *ob)
Definition paint.cc:2316
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
Definition paint.cc:2601
void BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph, Main *bmain, Object *ob, MultiresModifierData *mmd)
Definition paint.cc:2610
A BVH for high poly meshes.
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)
void BKE_subdiv_ccg_foreach_visible_grid_vert(const CCGKey &key, const blender::BitGroupVector<> &grid_hidden, const int grid, const Fn &fn)
void BKE_subdiv_ccg_average_grids(SubdivCCG &subdiv_ccg)
BLI_INLINE float BLI_hash_int_01(unsigned int k)
Definition BLI_hash.h:96
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.c:65
@ CD_PROP_FLOAT
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define BM_ELEM_CD_SET_FLOAT(ele, offset, f)
@ BM_ELEM_HIDDEN
#define BM_elem_index_get(ele)
#define BM_elem_flag_test(ele, hflag)
static unsigned long seed
Definition btSoftBody.h:39
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
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]
IndexRange grid_range(const int grid_area, const int grid)
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2846
IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory)
Definition pbvh.cc:2612
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
int vert_face_set_get(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const int vert)
Definition sculpt.cc:232
Span< int > node_visible_verts(const bke::pbvh::MeshNode &node, const Span< bool > hide_vert, Vector< int > &indices)
void ensure_cache(Object &object)
Definition sculpt.cc:6013
int vert_id_get(const SculptSession &ss, const int vert)
Definition sculpt.cc:5880
void write_mask_mesh(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, FunctionRef< void(MutableSpan< float >, Span< int >)> write_fn)
static void init_mask_grids(Main &bmain, Scene &scene, Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, FunctionRef< void(const BitGroupVector<> &, int, MutableSpan< float >)> write_fn)
void SCULPT_OT_mask_init(wmOperatorType *ot)
static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
void push_nodes(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const Type type)
void push_begin(const Scene &scene, Object &ob, const wmOperator *op)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
bool SCULPT_mode_poll(bContext *C)
Definition sculpt.cc:3560
void SCULPT_tag_update_overlays(bContext *C)
Definition sculpt.cc:735
CustomData vdata
int grid_area
Definition BKE_ccg.hh:35
struct SculptSession * sculpt
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::Span< int > grid_to_face_map
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
StructRNA * srna
Definition WM_types.hh:1080
struct PointerRNA * ptr
wmOperatorType * ot
Definition wm_files.cc:4125