Blender V5.0
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
8
10#include "BLI_hash.h"
11#include "BLI_time.h"
12
13#include "DNA_object_types.h"
14
15#include "BKE_ccg.hh"
16#include "BKE_context.hh"
17#include "BKE_layer.hh"
18#include "BKE_mesh.hh"
19#include "BKE_multires.hh"
20#include "BKE_paint.hh"
21#include "BKE_paint_bvh.hh"
22#include "BKE_subdiv_ccg.hh"
23
24#include "WM_api.hh"
25#include "WM_types.hh"
26
27#include "RNA_access.hh"
28#include "RNA_define.hh"
29
30#include "paint_intern.hh"
31#include "paint_mask.hh"
32#include "sculpt_face_set.hh"
33#include "sculpt_hide.hh"
34#include "sculpt_intern.hh"
35#include "sculpt_islands.hh"
36#include "sculpt_undo.hh"
37
38#include "bmesh.hh"
39
41
47
48void write_mask_mesh(const Depsgraph &depsgraph,
49 Object &object,
50 const IndexMask &node_mask,
52{
53 Mesh &mesh = *static_cast<Mesh *>(object.data);
54 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
55 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
56
57 undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask);
58
60 ".sculpt_mask", bke::AttrDomain::Point);
61 if (!mask) {
62 return;
63 }
67 node_mask.foreach_index(GrainSize(1), [&](const int i) {
68 Vector<int> &index_data = all_index_data.local();
69 write_fn(mask.span, hide::node_visible_verts(nodes[i], hide_vert, index_data));
71 });
72 pbvh.tag_masks_changed(node_mask);
73 mask.finish();
74}
75
76static void init_mask_grids(
77 Main &bmain,
78 Scene &scene,
79 Depsgraph &depsgraph,
80 Object &object,
81 const IndexMask &node_mask,
82 FunctionRef<void(const BitGroupVector<> &, int, MutableSpan<float>)> write_fn)
83{
85 BKE_sculpt_mask_layers_ensure(&depsgraph, &bmain, &object, mmd);
86
87 SculptSession &ss = *object.sculpt;
90 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
91 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
92 MutableSpan<float> masks = subdiv_ccg.masks;
93 const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
94
95 undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask);
96
97 node_mask.foreach_index(GrainSize(1), [&](const int i) {
98 for (const int grid : nodes[i].grids()) {
99 write_fn(grid_hidden, grid, masks.slice(bke::ccg::grid_range(key, grid)));
100 }
102 });
103 pbvh.tag_masks_changed(node_mask);
105}
106
108{
109 const View3D *v3d = CTX_wm_view3d(C);
110 const Base *base = CTX_data_active_base(C);
111 if (!BKE_base_is_visible(v3d, base)) {
112 return OPERATOR_CANCELLED;
113 }
114 const Scene &scene = *CTX_data_scene(C);
116 SculptSession &ss = *ob.sculpt;
118
120
122 IndexMaskMemory memory;
123 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
124 if (node_mask.is_empty()) {
125 return OPERATOR_CANCELLED;
126 }
127
128 undo::push_begin(scene, ob, op);
129
130 const InitMode mode = InitMode(RNA_enum_get(op->ptr, "mode"));
131 const int seed = BLI_time_now_seconds();
132
133 switch (pbvh.type()) {
135 switch (mode) {
136 case InitMode::Random:
138 for (const int vert : verts) {
139 mask[vert] = BLI_hash_int_01(vert + seed);
140 }
141 });
142 break;
143 case InitMode::FaceSet: {
144 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
145 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
146 const bke::AttributeAccessor attributes = mesh.attributes();
147 const VArraySpan face_sets = *attributes.lookup_or_default<int>(
148 ".sculpt_face_set", bke::AttrDomain::Face, 1);
149
151 for (const int vert : verts) {
152 const int face_set = face_set::vert_face_set_get(vert_to_face_map, face_sets, vert);
154 }
155 });
156 break;
157 }
158 case InitMode::Island:
161 for (const int vert : verts) {
162 const int island = islands::vert_id_get(ss, vert);
163 mask[vert] = BLI_hash_int_01(island + seed);
164 }
165 });
166 break;
167 }
168 break;
169 }
171 Main &bmain = *CTX_data_main(C);
172 Scene &scene = *CTX_data_scene(C);
173 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
174 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
175 switch (mode) {
176 case InitMode::Random: {
177 init_mask_grids(bmain,
178 scene,
179 depsgraph,
180 ob,
181 node_mask,
182 [&](const BitGroupVector<> &grid_hidden,
183 const int grid_index,
184 MutableSpan<float> grid_masks) {
185 const int verts_start = grid_index * key.grid_area;
187 key, grid_hidden, grid_index, [&](const int i) {
188 grid_masks[i] = BLI_hash_int_01(verts_start + i + seed);
189 });
190 });
191 break;
192 }
193 case InitMode::FaceSet: {
194 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
195 const bke::AttributeAccessor attributes = mesh.attributes();
196 const VArraySpan face_sets = *attributes.lookup_or_default<int>(
197 ".sculpt_face_set", bke::AttrDomain::Face, 1);
198 const Span<int> grid_to_face = subdiv_ccg.grid_to_face_map;
200 bmain,
201 scene,
202 depsgraph,
203 ob,
204 node_mask,
205 [&](const BitGroupVector<> &grid_hidden,
206 const int grid_index,
207 MutableSpan<float> grid_masks) {
208 const int face_set = face_sets[grid_to_face[grid_index]];
209 const float value = BLI_hash_int_01(face_set + seed);
211 key, grid_hidden, grid_index, [&](const int i) { grid_masks[i] = value; });
212 });
213 break;
214 }
215 case InitMode::Island: {
217 init_mask_grids(bmain,
218 scene,
219 depsgraph,
220 ob,
221 node_mask,
222 [&](const BitGroupVector<> &grid_hidden,
223 const int grid_index,
224 MutableSpan<float> grid_masks) {
225 const int verts_start = grid_index * key.grid_area;
227 key, grid_hidden, grid_index, [&](const int i) {
228 const int island = islands::vert_id_get(ss, verts_start + i);
229 grid_masks[i] = BLI_hash_int_01(island + seed);
230 });
231 });
232 break;
233 }
234 }
235 break;
236 }
239 const int offset = CustomData_get_offset_named(&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
241 node_mask.foreach_index(GrainSize(1), [&](const int i) {
244 continue;
245 }
246 switch (mode) {
247 case InitMode::Random:
249 break;
250 case InitMode::FaceSet: {
251 BM_ELEM_CD_SET_FLOAT(vert, offset, 0.0f);
252 break;
253 }
254 case InitMode::Island:
256 vert,
257 offset,
259 break;
260 }
261 }
263 });
264 pbvh.tag_masks_changed(node_mask);
265 break;
266 }
267 }
268
269 undo::push_end(ob);
270
272 return OPERATOR_FINISHED;
273}
274
276{
277 ot->name = "Init Mask";
278 ot->description = "Creates a new mask for the entire mesh";
279 ot->idname = "SCULPT_OT_mask_init";
280
282 ot->poll = SCULPT_mode_poll;
283
285
286 static EnumPropertyItem modes[] = {
287 {int(InitMode::Random), "RANDOM_PER_VERTEX", 0, "Random per Vertex", ""},
288 {int(InitMode::FaceSet), "RANDOM_PER_FACE_SET", 0, "Random per Face Set", ""},
289 {int(InitMode::Island), "RANDOM_PER_LOOSE_PART", 0, "Random per Loose Part", ""},
290 {0, nullptr, 0, nullptr, nullptr},
291 };
292 RNA_def_enum(ot->srna, "mode", modes, int(InitMode::Random), "Mode", "");
293}
294
295} // 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:2513
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
Definition paint.cc:2797
void BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph, Main *bmain, Object *ob, MultiresModifierData *mmd)
Definition paint.cc:2806
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:92
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:113
@ CD_PROP_FLOAT
Object is a sort of wrapper for general info.
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
#define C
Definition RandGen.cpp:29
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#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)
BPy_StructRNA * depsgraph
static unsigned long seed
Definition btSoftBody.h:39
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:573
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
GAttributeReader lookup(const StringRef attribute_id) const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
Span< NodeT > nodes() const
void tag_masks_changed(const IndexMask &node_mask)
Definition pbvh.cc:669
void foreach_index(Fn &&fn) const
static float verts[][3]
IndexRange grid_range(const int grid_area, const int grid)
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory)
Definition pbvh.cc:2628
void node_update_mask_bmesh(int mask_offset, BMeshNode &node)
Definition pbvh.cc:1479
void node_update_mask_mesh(Span< float > mask, MeshNode &node)
Definition pbvh.cc:1421
void node_update_mask_grids(const CCGKey &key, Span< float > masks, GridsNode &node)
Definition pbvh.cc:1449
int vert_face_set_get(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const int vert)
Definition sculpt.cc:230
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:6317
int vert_id_get(const SculptSession &ss, const int vert)
Definition sculpt.cc:6184
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 wmOperatorStatus 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:3677
void SCULPT_tag_update_overlays(bContext *C)
Definition sculpt.cc:759
CustomData vdata
int grid_area
Definition BKE_ccg.hh:35
struct SculptSession * sculpt
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
blender::Span< int > grid_to_face_map
struct PointerRNA * ptr
i
Definition text_draw.cc:230
wmOperatorType * ot
Definition wm_files.cc:4237