Blender  V3.3
sculpt_automasking.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_blenlib.h"
11 #include "BLI_hash.h"
12 #include "BLI_index_range.hh"
13 #include "BLI_math.h"
14 #include "BLI_task.h"
15 
16 #include "DNA_brush_types.h"
17 #include "DNA_mesh_types.h"
18 #include "DNA_meshdata_types.h"
19 
20 #include "BKE_brush.h"
21 #include "BKE_context.h"
22 #include "BKE_mesh.h"
23 #include "BKE_mesh_mapping.h"
24 #include "BKE_object.h"
25 #include "BKE_paint.h"
26 #include "BKE_pbvh.h"
27 #include "BKE_scene.h"
28 
29 #include "DEG_depsgraph.h"
30 
31 #include "WM_api.h"
32 #include "WM_message.h"
33 #include "WM_toolsystem.h"
34 #include "WM_types.h"
35 
36 #include "ED_object.h"
37 #include "ED_screen.h"
38 #include "ED_sculpt.h"
39 #include "paint_intern.h"
40 #include "sculpt_intern.h"
41 
42 #include "RNA_access.h"
43 #include "RNA_define.h"
44 
45 #include "bmesh.h"
46 
47 #include <cmath>
48 #include <cstdlib>
49 
51 
53 {
54  if (ss->cache) {
55  return ss->cache->automasking;
56  }
57  if (ss->filter_cache) {
58  return ss->filter_cache->automasking;
59  }
60  return nullptr;
61 }
62 
64  const Brush *br,
65  const eAutomasking_flag mode)
66 {
67  if (br) {
68  return br->automasking_flags & mode || sd->automasking_flags & mode;
69  }
70  return sd->automasking_flags & mode;
71 }
72 
73 bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, const Brush *br)
74 {
75  if (br && SCULPT_stroke_is_dynamic_topology(ss, br)) {
76  return false;
77  }
79  return true;
80  }
82  return true;
83  }
85  return true;
86  }
88  return true;
89  }
90  return false;
91 }
92 
93 static int sculpt_automasking_mode_effective_bits(const Sculpt *sculpt, const Brush *brush)
94 {
95  if (brush) {
96  return sculpt->automasking_flags | brush->automasking_flags;
97  }
98  return sculpt->automasking_flags;
99 }
100 
101 static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush *brush)
102 {
103 
104  const int automasking_flags = sculpt_automasking_mode_effective_bits(sd, brush);
105  if (automasking_flags & BRUSH_AUTOMASKING_TOPOLOGY) {
106  return true;
107  }
108  if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) {
109  return brush && brush->automasking_boundary_edges_propagation_steps != 1;
110  }
111  if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) {
112  return brush && brush->automasking_boundary_edges_propagation_steps != 1;
113  }
114  return false;
115 }
116 
118 {
119  if (!automasking) {
120  return 1.0f;
121  }
122  /* If the cache is initialized with valid info, use the cache. This is used when the
123  * automasking information can't be computed in real time per vertex and needs to be
124  * initialized for the whole mesh when the stroke starts. */
125  if (automasking->factor) {
126  return automasking->factor[vert];
127  }
128 
129  if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
130  if (!SCULPT_vertex_has_face_set(ss, vert, automasking->settings.initial_face_set)) {
131  return 0.0f;
132  }
133  }
134 
135  if (automasking->settings.flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) {
136  if (SCULPT_vertex_is_boundary(ss, vert)) {
137  return 0.0f;
138  }
139  }
140 
142  if (!SCULPT_vertex_has_unique_face_set(ss, vert)) {
143  return 0.0f;
144  }
145  }
146 
147  return 1.0f;
148 }
149 
151 {
152  if (!automasking) {
153  return;
154  }
155 
156  MEM_SAFE_FREE(automasking->factor);
157  MEM_SAFE_FREE(automasking);
158 }
159 
161 {
162  /* 2D falloff is not constrained by radius. */
164  return false;
165  }
166 
168  return true;
169  }
170  return false;
171 }
172 
175  float radius;
177  float location[3];
178  char symm;
179 };
180 
182  SculptSession *ss, int from_v, int to_v, bool UNUSED(is_duplicate), void *userdata)
183 {
185 
186  data->automask_factor[to_v] = 1.0f;
187  data->automask_factor[from_v] = 1.0f;
188  return (!data->use_radius ||
190  SCULPT_vertex_co_get(ss, to_v), data->location, data->radius, data->symm));
191 }
192 
193 static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *automask_factor)
194 {
195  SculptSession *ss = ob->sculpt;
196  Brush *brush = BKE_paint_brush(&sd->paint);
197 
198  if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
199  BLI_assert_msg(0, "Topology masking: pmap missing");
200  return nullptr;
201  }
202 
203  const int totvert = SCULPT_vertex_count_get(ss);
204  for (int i : IndexRange(totvert)) {
205  automask_factor[i] = 0.0f;
206  }
207 
208  /* Flood fill automask to connected vertices. Limited to vertices inside
209  * the brush radius if the tool requires it. */
210  SculptFloodFill flood;
211  SCULPT_floodfill_init(ss, &flood);
212  const float radius = ss->cache ? ss->cache->radius : FLT_MAX;
213  SCULPT_floodfill_add_active(sd, ob, ss, &flood, radius);
214 
215  AutomaskFloodFillData fdata = {nullptr};
216 
217  fdata.automask_factor = automask_factor;
218  fdata.radius = radius;
221 
223  SCULPT_floodfill_execute(ss, &flood, automask_floodfill_cb, &fdata);
224  SCULPT_floodfill_free(&flood);
225 
226  return automask_factor;
227 }
228 
229 static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *automask_factor)
230 {
231  SculptSession *ss = ob->sculpt;
232  Brush *brush = BKE_paint_brush(&sd->paint);
233 
234  if (!SCULPT_is_automasking_enabled(sd, ss, brush)) {
235  return nullptr;
236  }
237 
238  if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
239  BLI_assert_msg(0, "Face Sets automasking: pmap missing");
240  return nullptr;
241  }
242 
243  int tot_vert = SCULPT_vertex_count_get(ss);
244  int active_face_set = SCULPT_active_face_set_get(ss);
245  for (int i : IndexRange(tot_vert)) {
246  if (!SCULPT_vertex_has_face_set(ss, i, active_face_set)) {
247  automask_factor[i] *= 0.0f;
248  }
249  }
250 
251  return automask_factor;
252 }
253 
254 #define EDGE_DISTANCE_INF -1
255 
258  int propagation_steps,
259  float *automask_factor)
260 {
261  SculptSession *ss = ob->sculpt;
262 
263  if (!ss->pmap) {
264  BLI_assert_msg(0, "Boundary Edges masking: pmap missing");
265  return nullptr;
266  }
267 
268  const int totvert = SCULPT_vertex_count_get(ss);
269  int *edge_distance = (int *)MEM_callocN(sizeof(int) * totvert, "automask_factor");
270 
271  for (int i : IndexRange(totvert)) {
272  edge_distance[i] = EDGE_DISTANCE_INF;
273  switch (mode) {
275  if (SCULPT_vertex_is_boundary(ss, i)) {
276  edge_distance[i] = 0;
277  }
278  break;
280  if (!SCULPT_vertex_has_unique_face_set(ss, i)) {
281  edge_distance[i] = 0;
282  }
283  break;
284  }
285  }
286 
287  for (int propagation_it : IndexRange(propagation_steps)) {
288  for (int i : IndexRange(totvert)) {
289  if (edge_distance[i] != EDGE_DISTANCE_INF) {
290  continue;
291  }
294  if (edge_distance[ni.index] == propagation_it) {
295  edge_distance[i] = propagation_it + 1;
296  }
297  }
299  }
300  }
301 
302  for (int i : IndexRange(totvert)) {
303  if (edge_distance[i] == EDGE_DISTANCE_INF) {
304  continue;
305  }
306  const float p = 1.0f - ((float)edge_distance[i] / (float)propagation_steps);
307  const float edge_boundary_automask = pow2f(p);
308  automask_factor[i] *= (1.0f - edge_boundary_automask);
309  }
310 
311  MEM_SAFE_FREE(edge_distance);
312  return automask_factor;
313 }
314 
316  SculptSession *ss,
317  Sculpt *sd,
318  Brush *brush)
319 {
320  automasking->settings.flags = sculpt_automasking_mode_effective_bits(sd, brush);
322 }
323 
325 {
326  SculptSession *ss = ob->sculpt;
327  const int totvert = SCULPT_vertex_count_get(ss);
328 
329  if (!SCULPT_is_automasking_enabled(sd, ss, brush)) {
330  return nullptr;
331  }
332 
334  "automasking cache");
335  SCULPT_automasking_cache_settings_update(automasking, ss, sd, brush);
337 
338  if (!SCULPT_automasking_needs_factors_cache(sd, brush)) {
339  return automasking;
340  }
341 
342  automasking->factor = (float *)MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor");
343  for (int i : IndexRange(totvert)) {
344  automasking->factor[i] = 1.0f;
345  }
346 
347  const int boundary_propagation_steps = brush ?
349  1;
350 
353  SCULPT_topology_automasking_init(sd, ob, automasking->factor);
354  }
357  sculpt_face_sets_automasking_init(sd, ob, automasking->factor);
358  }
359 
363  ob, AUTOMASK_INIT_BOUNDARY_EDGES, boundary_propagation_steps, automasking->factor);
364  }
368  ob, AUTOMASK_INIT_BOUNDARY_FACE_SETS, boundary_propagation_steps, automasking->factor);
369  }
370 
371  return automasking;
372 }
typedef float(TangentPoint)[2]
General operations, lookup, etc. for blender objects.
struct Brush * BKE_paint_brush(struct Paint *paint)
Definition: paint.c:607
A BVH for high poly meshes.
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1798
@ PBVH_FACES
Definition: BKE_pbvh.h:234
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
MINLINE float pow2f(float x)
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define UNUSED(x)
#define ELEM(...)
eAutomasking_flag
@ BRUSH_AUTOMASKING_BOUNDARY_EDGES
@ BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS
@ BRUSH_AUTOMASKING_FACE_SETS
@ BRUSH_AUTOMASKING_TOPOLOGY
@ SCULPT_TOOL_THUMB
@ SCULPT_TOOL_GRAB
@ SCULPT_TOOL_ROTATE
@ PAINT_FALLOFF_SHAPE_TUBE
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
const float * SCULPT_vertex_co_get(SculptSession *ss, int index)
Definition: sculpt.c:125
int SCULPT_vertex_count_get(SculptSession *ss)
Definition: sculpt.c:111
void SCULPT_boundary_info_ensure(Object *object)
Definition: sculpt.c:5848
void SCULPT_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
Definition: sculpt.c:1072
bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set)
Definition: sculpt.c:533
bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index)
Definition: sculpt.c:662
const float * SCULPT_active_vertex_co_get(SculptSession *ss)
Definition: sculpt.c:279
void SCULPT_vertex_random_access_ensure(SculptSession *ss)
Definition: sculpt.c:103
bool SCULPT_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *brush)
Definition: sculpt.c:1338
bool SCULPT_vertex_is_boundary(const SculptSession *ss, const int index)
Definition: sculpt.c:865
void SCULPT_floodfill_free(SculptFloodFill *flood)
Definition: sculpt.c:1174
char SCULPT_mesh_symmetry_xyz_get(Object *object)
Definition: sculpt.c:317
bool SCULPT_is_vertex_inside_brush_radius_symm(const float vertex[3], const float br_co[3], float radius, char symm)
Definition: sculpt.c:1030
void SCULPT_floodfill_add_active(Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, float radius)
Definition: sculpt.c:1118
int SCULPT_active_face_set_get(SculptSession *ss)
Definition: sculpt.c:325
void SCULPT_floodfill_execute(SculptSession *ss, SculptFloodFill *flood, bool(*func)(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata), void *userdata)
Definition: sculpt.c:1143
static bool sculpt_automasking_is_constrained_by_radius(Brush *br)
float * SCULPT_boundary_automasking_init(Object *ob, eBoundaryAutomaskMode mode, int propagation_steps, float *automask_factor)
static float * sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *automask_factor)
static int sculpt_automasking_mode_effective_bits(const Sculpt *sculpt, const Brush *brush)
static float * SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *automask_factor)
void SCULPT_automasking_cache_free(AutomaskingCache *automasking)
static void SCULPT_automasking_cache_settings_update(AutomaskingCache *automasking, SculptSession *ss, Sculpt *sd, Brush *brush)
float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert)
bool SCULPT_is_automasking_mode_enabled(const Sculpt *sd, const Brush *br, const eAutomasking_flag mode)
#define EDGE_DISTANCE_INF
AutomaskingCache * SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object *ob)
static bool automask_floodfill_cb(SculptSession *ss, int from_v, int to_v, bool UNUSED(is_duplicate), void *userdata)
bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, const Brush *br)
static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush *brush)
AutomaskingCache * SCULPT_automasking_active_cache_get(SculptSession *ss)
#define SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator)
#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator)
eBoundaryAutomaskMode
Definition: sculpt_intern.h:99
@ AUTOMASK_INIT_BOUNDARY_EDGES
@ AUTOMASK_INIT_BOUNDARY_FACE_SETS
AutomaskingSettings settings
int automasking_flags
int automasking_boundary_edges_propagation_steps
char falloff_shape
char sculpt_tool
AutomaskingCache * automasking
struct SculptSession * sculpt
struct MeshElemMap * pmap
Definition: BKE_paint.h:516
struct StrokeCache * cache
Definition: BKE_paint.h:563
struct FilterCache * filter_cache
Definition: BKE_paint.h:564
struct PBVH * pbvh
Definition: BKE_paint.h:550
Paint paint
int automasking_flags
AutomaskingCache * automasking