Blender  V3.3
sculpt_expand.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_blenlib.h"
11 #include "BLI_linklist_stack.h"
12 #include "BLI_math.h"
13 #include "BLI_task.h"
14 
15 #include "BLT_translation.h"
16 
17 #include "DNA_brush_types.h"
18 #include "DNA_mesh_types.h"
19 #include "DNA_meshdata_types.h"
20 #include "DNA_object_types.h"
21 
22 #include "BKE_brush.h"
23 #include "BKE_ccg.h"
24 #include "BKE_colortools.h"
25 #include "BKE_context.h"
26 #include "BKE_image.h"
27 #include "BKE_mesh.h"
28 #include "BKE_mesh_mapping.h"
29 #include "BKE_multires.h"
30 #include "BKE_node.h"
31 #include "BKE_object.h"
32 #include "BKE_paint.h"
33 #include "BKE_pbvh.h"
34 #include "BKE_report.h"
35 #include "BKE_scene.h"
36 #include "BKE_subdiv_ccg.h"
37 
38 #include "DEG_depsgraph.h"
39 
40 #include "WM_api.h"
41 #include "WM_message.h"
42 #include "WM_toolsystem.h"
43 #include "WM_types.h"
44 
45 #include "RNA_access.h"
46 #include "RNA_define.h"
47 
48 #include "ED_object.h"
49 #include "ED_screen.h"
50 #include "ED_sculpt.h"
51 #include "ED_view3d.h"
52 #include "paint_intern.h"
53 #include "sculpt_intern.h"
54 
55 #include "IMB_colormanagement.h"
56 #include "IMB_imbuf.h"
57 
58 #include "bmesh.h"
59 
60 #include <math.h>
61 #include <stdlib.h>
62 
63 /* Sculpt Expand. */
64 /* Operator for creating selections and patterns in Sculpt Mode. Expand can create masks, face sets
65  * and fill vertex colors. */
66 /* The main functionality of the operator
67  * - The operator initializes a value per vertex, called "falloff". There are multiple algorithms
68  * to generate these falloff values which will create different patterns in the result when using
69  * the operator. These falloff values require algorithms that rely on mesh connectivity, so they
70  * are only valid on parts of the mesh that are in the same connected component as the given
71  * initial vertices. If needed, these falloff values are propagated from vertex or grids into the
72  * base mesh faces.
73  *
74  * - On each modal callback, the operator gets the active vertex and face and gets its falloff
75  * value from its precalculated falloff. This is now the active falloff value.
76  * - Using the active falloff value and the settings of the expand operation (which can be modified
77  * during execution using the modal key-map), the operator loops over all elements in the mesh to
78  * check if they are enabled of not.
79  * - Based on each element state after evaluating the settings, the desired mesh data (mask, face
80  * sets, colors...) is updated.
81  */
82 
86 #define SCULPT_EXPAND_VERTEX_NONE -1
87 
89 #define EXPAND_ACTIVE_COMPONENT_NONE -1
94 #define SCULPT_EXPAND_TEXTURE_DISTORTION_STEP 0.01f
95 
101 #define SCULPT_EXPAND_LOOP_THRESHOLD 0.00001f
102 
108 #define SCULPT_EXPAND_NORMALS_FALLOFF_EDGE_SENSITIVITY 300
109 
110 /* Expand Modal Key-map. */
111 enum {
131 };
132 
133 /* Functions for getting the state of mesh elements (vertices and base mesh faces). When the main
134  * functions for getting the state of an element return true it means that data associated to that
135  * element will be modified by expand. */
136 
142  ExpandCache *expand_cache,
143  const int v)
144 {
145  for (int i = 0; i < EXPAND_SYMM_AREAS; i++) {
146  if (ss->vertex_info.connected_component[v] == expand_cache->active_connected_components[i]) {
147  return true;
148  }
149  }
150  return false;
151 }
152 
157  ExpandCache *expand_cache,
158  const int f)
159 {
160  const MLoop *loop = &ss->mloop[ss->mpoly[f].loopstart];
161  return sculpt_expand_is_vert_in_active_component(ss, expand_cache, loop->v);
162 }
163 
169  ExpandCache *expand_cache,
170  const int v)
171 {
172  if (expand_cache->texture_distortion_strength == 0.0f) {
173  return expand_cache->vert_falloff[v];
174  }
175 
176  if (!expand_cache->brush->mtex.tex) {
177  return expand_cache->vert_falloff[v];
178  }
179 
180  float rgba[4];
181  const float *vertex_co = SCULPT_vertex_co_get(ss, v);
182  const float avg = BKE_brush_sample_tex_3d(
183  expand_cache->scene, expand_cache->brush, vertex_co, rgba, 0, ss->tex_pool);
184 
185  const float distortion = (avg - 0.5f) * expand_cache->texture_distortion_strength *
186  expand_cache->max_vert_falloff;
187  return expand_cache->vert_falloff[v] + distortion;
188 }
189 
195 {
196  if (expand_cache->texture_distortion_strength == 0.0f) {
197  return expand_cache->max_vert_falloff;
198  }
199 
200  if (!expand_cache->brush->mtex.tex) {
201  return expand_cache->max_vert_falloff;
202  }
203 
204  return expand_cache->max_vert_falloff +
205  (0.5f * expand_cache->texture_distortion_strength * expand_cache->max_vert_falloff);
206 }
207 
212 static bool sculpt_expand_state_get(SculptSession *ss, ExpandCache *expand_cache, const int v)
213 {
214  if (!SCULPT_vertex_visible_get(ss, v)) {
215  return false;
216  }
217 
218  if (!sculpt_expand_is_vert_in_active_component(ss, expand_cache, v)) {
219  return false;
220  }
221 
222  if (expand_cache->all_enabled) {
223  return true;
224  }
225 
226  bool enabled = false;
227 
228  if (expand_cache->snap) {
229  /* Face Sets are not being modified when using this function, so it is ok to get this directly
230  * from the Sculpt API instead of implementing a custom function to get them from
231  * expand_cache->original_face_sets. */
232  const int face_set = SCULPT_vertex_face_set_get(ss, v);
234  }
235  else {
236  const float max_falloff_factor = sculpt_expand_max_vertex_falloff_get(expand_cache);
237  const float loop_len = (max_falloff_factor / expand_cache->loop_count) +
239 
240  const float vertex_falloff_factor = sculpt_expand_falloff_value_vertex_get(
241  ss, expand_cache, v);
242  const float active_factor = fmod(expand_cache->active_falloff, loop_len);
243  const float falloff_factor = fmod(vertex_falloff_factor, loop_len);
244 
245  enabled = falloff_factor < active_factor;
246  }
247 
248  if (expand_cache->invert) {
249  enabled = !enabled;
250  }
251  return enabled;
252 }
253 
258 static bool sculpt_expand_face_state_get(SculptSession *ss, ExpandCache *expand_cache, const int f)
259 {
260  if (expand_cache->original_face_sets[f] <= 0) {
261  return false;
262  }
263 
264  if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, f)) {
265  return false;
266  }
267 
268  if (expand_cache->all_enabled) {
269  return true;
270  }
271 
272  bool enabled = false;
273 
274  if (expand_cache->snap_enabled_face_sets) {
275  const int face_set = expand_cache->original_face_sets[f];
277  }
278  else {
279  const float loop_len = (expand_cache->max_face_falloff / expand_cache->loop_count) +
281 
282  const float active_factor = fmod(expand_cache->active_falloff, loop_len);
283  const float falloff_factor = fmod(expand_cache->face_falloff[f], loop_len);
284  enabled = falloff_factor < active_factor;
285  }
286 
288  if (ss->face_sets[f] == expand_cache->initial_active_face_set) {
289  enabled = false;
290  }
291  }
292 
293  if (expand_cache->invert) {
294  enabled = !enabled;
295  }
296 
297  return enabled;
298 }
299 
305  ExpandCache *expand_cache,
306  const int v)
307 {
308  if (!expand_cache->falloff_gradient) {
309  return 1.0f;
310  }
311 
312  const float max_falloff_factor = sculpt_expand_max_vertex_falloff_get(expand_cache);
313  const float loop_len = (max_falloff_factor / expand_cache->loop_count) +
315 
316  const float vertex_falloff_factor = sculpt_expand_falloff_value_vertex_get(ss, expand_cache, v);
317  const float active_factor = fmod(expand_cache->active_falloff, loop_len);
318  const float falloff_factor = fmod(vertex_falloff_factor, loop_len);
319 
320  float linear_falloff;
321 
322  if (expand_cache->invert) {
323  /* Active factor is the result of a modulus operation using loop_len, so they will never be
324  * equal and loop_len - active_factor should never be 0. */
325  BLI_assert((loop_len - active_factor) != 0.0f);
326  linear_falloff = (falloff_factor - active_factor) / (loop_len - active_factor);
327  }
328  else {
329  linear_falloff = 1.0f - (falloff_factor / active_factor);
330  }
331 
332  if (!expand_cache->brush_gradient) {
333  return linear_falloff;
334  }
335 
336  return BKE_brush_curve_strength(expand_cache->brush, linear_falloff, 1.0f);
337 }
338 
339 /* Utility functions for getting all vertices state during expand. */
340 
346 {
347  const int totvert = SCULPT_vertex_count_get(ss);
348  BLI_bitmap *enabled_vertices = BLI_BITMAP_NEW(totvert, "enabled vertices");
349  for (int i = 0; i < totvert; i++) {
350  const bool enabled = sculpt_expand_state_get(ss, expand_cache, i);
351  BLI_BITMAP_SET(enabled_vertices, i, enabled);
352  }
353  return enabled_vertices;
354 }
355 
362  const BLI_bitmap *enabled_vertices,
363  const bool use_mesh_boundary)
364 {
365  const int totvert = SCULPT_vertex_count_get(ss);
366  BLI_bitmap *boundary_vertices = BLI_BITMAP_NEW(totvert, "boundary vertices");
367  for (int i = 0; i < totvert; i++) {
368  if (!BLI_BITMAP_TEST(enabled_vertices, i)) {
369  continue;
370  }
371 
372  bool is_expand_boundary = false;
375  if (!BLI_BITMAP_TEST(enabled_vertices, ni.index)) {
376  is_expand_boundary = true;
377  }
378  }
380 
381  if (use_mesh_boundary && SCULPT_vertex_is_boundary(ss, i)) {
382  is_expand_boundary = true;
383  }
384 
385  BLI_BITMAP_SET(boundary_vertices, i, is_expand_boundary);
386  }
387 
388  return boundary_vertices;
389 }
390 
391 /* Functions implementing different algorithms for initializing falloff values. */
392 
398  const char symm_it,
399  const int original_vertex)
400 {
401  SculptSession *ss = ob->sculpt;
402  int symm_vertex = SCULPT_EXPAND_VERTEX_NONE;
403  if (symm_it == 0) {
404  symm_vertex = original_vertex;
405  }
406  else {
407  float location[3];
408  flip_v3_v3(location, SCULPT_vertex_co_get(ss, original_vertex), symm_it);
409  symm_vertex = SCULPT_nearest_vertex_get(NULL, ob, location, FLT_MAX, false);
410  }
411  return symm_vertex;
412 }
413 
418 static float *sculpt_expand_geodesic_falloff_create(Sculpt *sd, Object *ob, const int v)
419 {
420  return SCULPT_geodesic_from_vertex_and_symm(sd, ob, v, FLT_MAX);
421 }
422 
427 typedef struct ExpandFloodFillData {
428  float original_normal[3];
430  float *dists;
431  float *edge_factor;
433 
435  SculptSession *UNUSED(ss), int from_v, int to_v, bool is_duplicate, void *userdata)
436 {
437  ExpandFloodFillData *data = userdata;
438  if (!is_duplicate) {
439  const float to_it = data->dists[from_v] + 1.0f;
440  data->dists[to_v] = to_it;
441  }
442  else {
443  data->dists[to_v] = data->dists[from_v];
444  }
445  return true;
446 }
447 
448 static float *sculpt_expand_topology_falloff_create(Sculpt *sd, Object *ob, const int v)
449 {
450  SculptSession *ss = ob->sculpt;
451  const int totvert = SCULPT_vertex_count_get(ss);
452  float *dists = MEM_calloc_arrayN(totvert, sizeof(float), "topology dist");
453 
454  SculptFloodFill flood;
455  SCULPT_floodfill_init(ss, &flood);
456  SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, v, FLT_MAX);
457 
458  ExpandFloodFillData fdata;
459  fdata.dists = dists;
460 
462  SCULPT_floodfill_free(&flood);
463 
464  return dists;
465 }
466 
473  SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
474 {
475  ExpandFloodFillData *data = userdata;
476  if (!is_duplicate) {
477  float current_normal[3], prev_normal[3];
478  SCULPT_vertex_normal_get(ss, to_v, current_normal);
479  SCULPT_vertex_normal_get(ss, from_v, prev_normal);
480  const float from_edge_factor = data->edge_factor[from_v];
481  data->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) * from_edge_factor;
482  data->dists[to_v] = dot_v3v3(data->original_normal, current_normal) *
483  powf(from_edge_factor, data->edge_sensitivity);
484  CLAMP(data->dists[to_v], 0.0f, 1.0f);
485  }
486  else {
487  /* PBVH_GRIDS duplicate handling. */
488  data->edge_factor[to_v] = data->edge_factor[from_v];
489  data->dists[to_v] = data->dists[from_v];
490  }
491 
492  return true;
493 }
494 
496  Object *ob,
497  const int v,
498  const float edge_sensitivity)
499 {
500  SculptSession *ss = ob->sculpt;
501  const int totvert = SCULPT_vertex_count_get(ss);
502  float *dists = MEM_malloc_arrayN(totvert, sizeof(float), "normal dist");
503  float *edge_factor = MEM_callocN(sizeof(float) * totvert, "mask edge factor");
504  for (int i = 0; i < totvert; i++) {
505  edge_factor[i] = 1.0f;
506  }
507 
508  SculptFloodFill flood;
509  SCULPT_floodfill_init(ss, &flood);
510  SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, v, FLT_MAX);
511 
512  ExpandFloodFillData fdata;
513  fdata.dists = dists;
514  fdata.edge_factor = edge_factor;
515  fdata.edge_sensitivity = edge_sensitivity;
517 
519  SCULPT_floodfill_free(&flood);
520 
521  for (int repeat = 0; repeat < 2; repeat++) {
522  for (int i = 0; i < totvert; i++) {
523  float avg = 0.0f;
526  avg += dists[ni.index];
527  }
529  dists[i] = avg / ni.size;
530  }
531  }
532 
533  MEM_SAFE_FREE(edge_factor);
534 
535  return dists;
536 }
537 
542 static float *sculpt_expand_spherical_falloff_create(Object *ob, const int v)
543 {
544  SculptSession *ss = ob->sculpt;
545  const int totvert = SCULPT_vertex_count_get(ss);
546 
547  float *dists = MEM_malloc_arrayN(totvert, sizeof(float), "spherical dist");
548  for (int i = 0; i < totvert; i++) {
549  dists[i] = FLT_MAX;
550  }
551  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
552 
553  for (char symm_it = 0; symm_it <= symm; symm_it++) {
554  if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
555  continue;
556  }
557  const int symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(ob, symm_it, v);
558  if (symm_vertex != -1) {
559  const float *co = SCULPT_vertex_co_get(ss, symm_vertex);
560  for (int i = 0; i < totvert; i++) {
561  dists[i] = min_ff(dists[i], len_v3v3(co, SCULPT_vertex_co_get(ss, i)));
562  }
563  }
564  }
565 
566  return dists;
567 }
568 
575 {
576  SculptSession *ss = ob->sculpt;
577  const int totvert = SCULPT_vertex_count_get(ss);
578  float *dists = MEM_calloc_arrayN(totvert, sizeof(float), "spherical dist");
579  BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(totvert, "visited vertices");
580  GSQueue *queue = BLI_gsqueue_new(sizeof(int));
581 
582  /* Search and initialize a boundary per symmetry pass, then mark those vertices as visited. */
583  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
584  for (char symm_it = 0; symm_it <= symm; symm_it++) {
585  if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
586  continue;
587  }
588 
589  const int symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(ob, symm_it, v);
590 
591  SculptBoundary *boundary = SCULPT_boundary_data_init(ob, NULL, symm_vertex, FLT_MAX);
592  if (!boundary) {
593  continue;
594  }
595 
596  for (int i = 0; i < boundary->num_vertices; i++) {
597  BLI_gsqueue_push(queue, &boundary->vertices[i]);
598  BLI_BITMAP_ENABLE(visited_vertices, boundary->vertices[i]);
599  }
600  SCULPT_boundary_data_free(boundary);
601  }
602 
603  /* If there are no boundaries, return a falloff with all values set to 0. */
605  return dists;
606  }
607 
608  /* Propagate the values from the boundaries to the rest of the mesh. */
609  while (!BLI_gsqueue_is_empty(queue)) {
610  int v_next;
611  BLI_gsqueue_pop(queue, &v_next);
612 
614  SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, v_next, ni) {
615  if (BLI_BITMAP_TEST(visited_vertices, ni.index)) {
616  continue;
617  }
618  dists[ni.index] = dists[v_next] + 1.0f;
619  BLI_BITMAP_ENABLE(visited_vertices, ni.index);
621  }
623  }
624 
626  MEM_freeN(visited_vertices);
627  return dists;
628 }
629 
635 static float *sculpt_expand_diagonals_falloff_create(Object *ob, const int v)
636 {
637  SculptSession *ss = ob->sculpt;
638  const int totvert = SCULPT_vertex_count_get(ss);
639  float *dists = MEM_calloc_arrayN(totvert, sizeof(float), "spherical dist");
640 
641  /* This algorithm uses mesh data (polys and loops), so this falloff type can't be initialized for
642  * Multires. It also does not make sense to implement it for dyntopo as the result will be the
643  * same as Topology falloff. */
644  if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
645  return dists;
646  }
647 
648  /* Search and mask as visited the initial vertices using the enabled symmetry passes. */
649  BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(totvert, "visited vertices");
650  GSQueue *queue = BLI_gsqueue_new(sizeof(int));
651  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
652  for (char symm_it = 0; symm_it <= symm; symm_it++) {
653  if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
654  continue;
655  }
656 
657  const int symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(ob, symm_it, v);
658 
659  BLI_gsqueue_push(queue, &symm_vertex);
660  BLI_BITMAP_ENABLE(visited_vertices, symm_vertex);
661  }
662 
664  return dists;
665  }
666 
667  /* Propagate the falloff increasing the value by 1 each time a new vertex is visited. */
668  Mesh *mesh = ob->data;
669  while (!BLI_gsqueue_is_empty(queue)) {
670  int v_next;
671  BLI_gsqueue_pop(queue, &v_next);
672  for (int j = 0; j < ss->pmap[v_next].count; j++) {
673  MPoly *p = &ss->mpoly[ss->pmap[v_next].indices[j]];
674  for (int l = 0; l < p->totloop; l++) {
675  const int neighbor_v = mesh->mloop[p->loopstart + l].v;
676  if (BLI_BITMAP_TEST(visited_vertices, neighbor_v)) {
677  continue;
678  }
679  dists[neighbor_v] = dists[v_next] + 1.0f;
680  BLI_BITMAP_ENABLE(visited_vertices, neighbor_v);
681  BLI_gsqueue_push(queue, &neighbor_v);
682  }
683  }
684  }
685 
687  MEM_freeN(visited_vertices);
688  return dists;
689 }
690 
691 /* Functions to update the max_falloff value in the #ExpandCache. These functions are called after
692  * initializing a new falloff to make sure that this value is always updated. */
693 
699  ExpandCache *expand_cache)
700 {
701  const int totvert = SCULPT_vertex_count_get(ss);
702  expand_cache->max_vert_falloff = -FLT_MAX;
703  for (int i = 0; i < totvert; i++) {
704  if (expand_cache->vert_falloff[i] == FLT_MAX) {
705  continue;
706  }
707 
708  if (!sculpt_expand_is_vert_in_active_component(ss, expand_cache, i)) {
709  continue;
710  }
711 
712  expand_cache->max_vert_falloff = max_ff(expand_cache->max_vert_falloff,
713  expand_cache->vert_falloff[i]);
714  }
715 }
716 
722  ExpandCache *expand_cache)
723 {
724  const int totface = ss->totfaces;
725  expand_cache->max_face_falloff = -FLT_MAX;
726  for (int i = 0; i < totface; i++) {
727  if (expand_cache->face_falloff[i] == FLT_MAX) {
728  continue;
729  }
730 
731  if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, i)) {
732  continue;
733  }
734 
735  expand_cache->max_face_falloff = max_ff(expand_cache->max_face_falloff,
736  expand_cache->face_falloff[i]);
737  }
738 }
739 
747  Mesh *mesh,
748  ExpandCache *expand_cache)
749 {
750 
751  const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
752 
753  for (int p = 0; p < mesh->totpoly; p++) {
754  MPoly *poly = &mesh->mpoly[p];
755  float accum = 0.0f;
756  for (int l = 0; l < poly->totloop; l++) {
757  const int grid_loop_index = (poly->loopstart + l) * key->grid_area;
758  for (int g = 0; g < key->grid_area; g++) {
759  accum += expand_cache->vert_falloff[grid_loop_index + g];
760  }
761  }
762  expand_cache->face_falloff[p] = accum / (poly->totloop * key->grid_area);
763  }
764 }
765 
767 {
768  for (int p = 0; p < mesh->totpoly; p++) {
769  MPoly *poly = &mesh->mpoly[p];
770  float accum = 0.0f;
771  for (int l = 0; l < poly->totloop; l++) {
772  MLoop *loop = &mesh->mloop[l + poly->loopstart];
773  accum += expand_cache->vert_falloff[loop->v];
774  }
775  expand_cache->face_falloff[p] = accum / poly->totloop;
776  }
777 }
778 
783  Mesh *mesh,
784  ExpandCache *expand_cache)
785 {
786  BLI_assert(expand_cache->vert_falloff != NULL);
787 
788  if (!expand_cache->face_falloff) {
789  expand_cache->face_falloff = MEM_malloc_arrayN(
790  mesh->totpoly, sizeof(float), "face falloff factors");
791  }
792 
793  if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
795  }
796  else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
797  sculpt_expand_grids_to_faces_falloff(ss, mesh, expand_cache);
798  }
799  else {
800  BLI_assert(false);
801  }
802 }
803 
804 /* Recursions. These functions will generate new falloff values based on the state of the vertices
805  * from the current ExpandCache options and falloff values. */
806 
812  ExpandCache *expand_cache,
813  BLI_bitmap *enabled_vertices)
814 {
815  SculptSession *ss = ob->sculpt;
817 
818  GSet *initial_vertices = BLI_gset_int_new("initial_vertices");
819  BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled(ss, enabled_vertices, false);
820  const int totvert = SCULPT_vertex_count_get(ss);
821  for (int i = 0; i < totvert; i++) {
822  if (!BLI_BITMAP_TEST(boundary_vertices, i)) {
823  continue;
824  }
825  BLI_gset_add(initial_vertices, POINTER_FROM_INT(i));
826  }
827  MEM_freeN(boundary_vertices);
828 
829  MEM_SAFE_FREE(expand_cache->vert_falloff);
830  MEM_SAFE_FREE(expand_cache->face_falloff);
831 
832  expand_cache->vert_falloff = SCULPT_geodesic_distances_create(ob, initial_vertices, FLT_MAX);
833  BLI_gset_free(initial_vertices, NULL);
834 }
835 
841  ExpandCache *expand_cache,
842  BLI_bitmap *enabled_vertices)
843 {
844  MEM_SAFE_FREE(expand_cache->vert_falloff);
845  MEM_SAFE_FREE(expand_cache->face_falloff);
846 
847  SculptSession *ss = ob->sculpt;
848  const int totvert = SCULPT_vertex_count_get(ss);
849 
850  float *dists = MEM_calloc_arrayN(totvert, sizeof(float), "topology dist");
851  BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled(ss, enabled_vertices, false);
852 
853  SculptFloodFill flood;
854  SCULPT_floodfill_init(ss, &flood);
855  for (int i = 0; i < totvert; i++) {
856  if (!BLI_BITMAP_TEST(boundary_vertices, i)) {
857  continue;
858  }
860  }
861  MEM_freeN(boundary_vertices);
862 
863  ExpandFloodFillData fdata;
864  fdata.dists = dists;
866  SCULPT_floodfill_free(&flood);
867 
868  expand_cache->vert_falloff = dists;
869 }
870 
875  ExpandCache *expand_cache,
876  const eSculptExpandRecursionType recursion_type)
877 {
878  SculptSession *ss = ob->sculpt;
879  if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
880  return;
881  }
882 
883  BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache);
884 
885  /* Each time a new recursion step is created, reset the distortion strength. This is the expected
886  * result from the recursion, as otherwise the new falloff will render with undesired distortion
887  * from the beginning. */
888  expand_cache->texture_distortion_strength = 0.0f;
889 
890  switch (recursion_type) {
892  sculpt_expand_geodesics_from_state_boundary(ob, expand_cache, enabled_vertices);
893  break;
895  sculpt_expand_topology_from_state_boundary(ob, expand_cache, enabled_vertices);
896  break;
897  }
898 
900  if (expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS) {
903  }
904 
905  MEM_freeN(enabled_vertices);
906 }
907 
908 /* Face Set Boundary falloff. */
909 
915  ExpandCache *expand_cache,
916  const int active_face_set,
917  const bool internal_falloff)
918 {
919  SculptSession *ss = ob->sculpt;
920  const int totvert = SCULPT_vertex_count_get(ss);
921 
922  BLI_bitmap *enabled_vertices = BLI_BITMAP_NEW(totvert, "enabled vertices");
923  for (int i = 0; i < totvert; i++) {
924  if (!SCULPT_vertex_has_unique_face_set(ss, i)) {
925  continue;
926  }
927  if (!SCULPT_vertex_has_face_set(ss, i, active_face_set)) {
928  continue;
929  }
930  BLI_BITMAP_ENABLE(enabled_vertices, i);
931  }
932 
933  if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
934  sculpt_expand_geodesics_from_state_boundary(ob, expand_cache, enabled_vertices);
935  }
936  else {
937  sculpt_expand_topology_from_state_boundary(ob, expand_cache, enabled_vertices);
938  }
939 
940  MEM_freeN(enabled_vertices);
941 
942  if (internal_falloff) {
943  for (int i = 0; i < totvert; i++) {
944  if (!(SCULPT_vertex_has_face_set(ss, i, active_face_set) &&
946  continue;
947  }
948  expand_cache->vert_falloff[i] *= -1.0f;
949  }
950 
951  float min_factor = FLT_MAX;
952  for (int i = 0; i < totvert; i++) {
953  min_factor = min_ff(expand_cache->vert_falloff[i], min_factor);
954  }
955 
956  const float additional_falloff = fabsf(min_factor);
957  for (int i = 0; i < totvert; i++) {
958  expand_cache->vert_falloff[i] += additional_falloff;
959  }
960  }
961  else {
962  for (int i = 0; i < totvert; i++) {
963  if (!SCULPT_vertex_has_face_set(ss, i, active_face_set)) {
964  continue;
965  }
966  expand_cache->vert_falloff[i] = 0.0f;
967  }
968  }
969 }
970 
976  ExpandCache *expand_cache,
977  Sculpt *sd,
978  Object *ob,
979  const int v,
980  eSculptExpandFalloffType falloff_type)
981 {
982  MEM_SAFE_FREE(expand_cache->vert_falloff);
983  expand_cache->falloff_type = falloff_type;
984 
985  SculptSession *ss = ob->sculpt;
986  const bool has_topology_info = BKE_pbvh_type(ss->pbvh) == PBVH_FACES;
987 
988  switch (falloff_type) {
990  expand_cache->vert_falloff = has_topology_info ?
993  break;
995  expand_cache->vert_falloff = sculpt_expand_topology_falloff_create(sd, ob, v);
996  break;
998  expand_cache->vert_falloff = has_topology_info ?
1001  break;
1005  break;
1008  break;
1011  break;
1014  ob, expand_cache, expand_cache->initial_active_face_set, true);
1015  break;
1018  ob, expand_cache, expand_cache->initial_active_face_set, false);
1019  break;
1020  }
1021 
1022  /* Update max falloff values and propagate to base mesh faces if needed. */
1024  if (expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS) {
1027  }
1028 }
1029 
1036  ExpandCache *expand_cache)
1037 {
1038  if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
1039  return;
1040  }
1041 
1042  /* Make sure this code runs with snapping and invert disabled. This simplifies the code and
1043  * prevents using this function with snapping already enabled. */
1044  const bool prev_snap_state = expand_cache->snap;
1045  const bool prev_invert_state = expand_cache->invert;
1046  expand_cache->snap = false;
1047  expand_cache->invert = false;
1048 
1049  BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache);
1050 
1051  const int totface = ss->totfaces;
1052  for (int i = 0; i < totface; i++) {
1053  const int face_set = expand_cache->original_face_sets[i];
1054  BLI_gset_add(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(face_set));
1055  }
1056 
1057  for (int p = 0; p < totface; p++) {
1058  MPoly *poly = &ss->mpoly[p];
1059  bool any_disabled = false;
1060  for (int l = 0; l < poly->totloop; l++) {
1061  MLoop *loop = &ss->mloop[l + poly->loopstart];
1062  if (!BLI_BITMAP_TEST(enabled_vertices, loop->v)) {
1063  any_disabled = true;
1064  break;
1065  }
1066  }
1067  if (any_disabled) {
1068  const int face_set = expand_cache->original_face_sets[p];
1069  BLI_gset_remove(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(face_set), NULL);
1070  }
1071  }
1072 
1073  MEM_freeN(enabled_vertices);
1074  expand_cache->snap = prev_snap_state;
1075  expand_cache->invert = prev_invert_state;
1076 }
1077 
1081 static void sculpt_expand_cache_data_free(ExpandCache *expand_cache)
1082 {
1083  if (expand_cache->snap_enabled_face_sets) {
1084  BLI_gset_free(expand_cache->snap_enabled_face_sets, NULL);
1085  }
1086  MEM_SAFE_FREE(expand_cache->nodes);
1087  MEM_SAFE_FREE(expand_cache->vert_falloff);
1088  MEM_SAFE_FREE(expand_cache->face_falloff);
1089  MEM_SAFE_FREE(expand_cache->original_mask);
1090  MEM_SAFE_FREE(expand_cache->original_face_sets);
1091  MEM_SAFE_FREE(expand_cache->initial_face_sets);
1092  MEM_SAFE_FREE(expand_cache->original_colors);
1093  MEM_SAFE_FREE(expand_cache);
1094 }
1095 
1097 {
1099  /* Needs to be set to NULL as the paint cursor relies on checking this pointer detecting if an
1100  * expand operation is running. */
1101  ss->expand_cache = NULL;
1102 }
1103 
1108 {
1109  PBVHNode **nodes;
1110  int totnode;
1111  BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
1112  for (int n = 0; n < totnode; n++) {
1113  PBVHNode *node = nodes[n];
1115  }
1116  MEM_freeN(nodes);
1117  for (int i = 0; i < ss->totfaces; i++) {
1118  ss->face_sets[i] = expand_cache->original_face_sets[i];
1119  }
1120 }
1121 
1123 {
1124  PBVHNode **nodes;
1125  int totnode;
1126  BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
1127  for (int n = 0; n < totnode; n++) {
1128  PBVHNode *node = nodes[n];
1129  PBVHVertexIter vd;
1131  SCULPT_vertex_color_set(ss, vd.index, expand_cache->original_colors[vd.index]);
1132  }
1135  }
1136  MEM_freeN(nodes);
1137 }
1138 
1140 {
1141  PBVHNode **nodes;
1142  int totnode;
1143  BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
1144  for (int n = 0; n < totnode; n++) {
1145  PBVHNode *node = nodes[n];
1146  PBVHVertexIter vd;
1148  *vd.mask = expand_cache->original_mask[vd.index];
1149  }
1152  }
1153  MEM_freeN(nodes);
1154 }
1155 
1156 /* Main function to restore the original state of the data to how it was before starting the expand
1157  * operation. */
1159  Object *ob,
1160  ExpandCache *expand_cache)
1161 {
1162 
1163  SculptSession *ss = ob->sculpt;
1164  switch (expand_cache->target) {
1166  sculpt_expand_restore_mask_data(ss, expand_cache);
1170  break;
1172  sculpt_expand_restore_face_set_data(ss, expand_cache);
1176  break;
1178  sculpt_expand_restore_color_data(ss, expand_cache);
1181  break;
1182  }
1183 }
1184 
1189 {
1191  SculptSession *ss = ob->sculpt;
1192 
1194 
1197 }
1198 
1199 /* Functions to update the sculpt mesh data. */
1200 
1204 static void sculpt_expand_mask_update_task_cb(void *__restrict userdata,
1205  const int i,
1206  const TaskParallelTLS *__restrict UNUSED(tls))
1207 {
1208  SculptThreadedTaskData *data = userdata;
1209  SculptSession *ss = data->ob->sculpt;
1210  PBVHNode *node = data->nodes[i];
1211  ExpandCache *expand_cache = ss->expand_cache;
1212 
1213  bool any_changed = false;
1214 
1215  PBVHVertexIter vd;
1217  const float initial_mask = *vd.mask;
1218  const bool enabled = sculpt_expand_state_get(ss, expand_cache, vd.index);
1219 
1220  float new_mask;
1221 
1222  if (enabled) {
1223  new_mask = sculpt_expand_gradient_value_get(ss, expand_cache, vd.index);
1224  }
1225  else {
1226  new_mask = 0.0f;
1227  }
1228 
1229  if (expand_cache->preserve) {
1230  new_mask = max_ff(new_mask, expand_cache->original_mask[vd.index]);
1231  }
1232 
1233  if (new_mask == initial_mask) {
1234  continue;
1235  }
1236 
1237  *vd.mask = clamp_f(new_mask, 0.0f, 1.0f);
1238  any_changed = true;
1239  }
1241  if (any_changed) {
1243  }
1244 }
1245 
1250 {
1251  const int totface = ss->totfaces;
1252  for (int f = 0; f < totface; f++) {
1253  const bool enabled = sculpt_expand_face_state_get(ss, expand_cache, f);
1254  if (!enabled) {
1255  continue;
1256  }
1257  if (expand_cache->preserve) {
1258  ss->face_sets[f] += expand_cache->next_face_set;
1259  }
1260  else {
1261  ss->face_sets[f] = expand_cache->next_face_set;
1262  }
1263  }
1264 
1265  for (int i = 0; i < expand_cache->totnode; i++) {
1267  }
1268 }
1269 
1273 static void sculpt_expand_colors_update_task_cb(void *__restrict userdata,
1274  const int i,
1275  const TaskParallelTLS *__restrict UNUSED(tls))
1276 {
1277  SculptThreadedTaskData *data = userdata;
1278  SculptSession *ss = data->ob->sculpt;
1279  PBVHNode *node = data->nodes[i];
1280  ExpandCache *expand_cache = ss->expand_cache;
1281 
1282  bool any_changed = false;
1283 
1284  PBVHVertexIter vd;
1286  float initial_color[4];
1287  SCULPT_vertex_color_get(ss, vd.index, initial_color);
1288 
1289  const bool enabled = sculpt_expand_state_get(ss, expand_cache, vd.index);
1290  float fade;
1291 
1292  if (enabled) {
1293  fade = sculpt_expand_gradient_value_get(ss, expand_cache, vd.index);
1294  }
1295  else {
1296  fade = 0.0f;
1297  }
1298 
1299  fade *= 1.0f - *vd.mask;
1300  fade = clamp_f(fade, 0.0f, 1.0f);
1301 
1302  float final_color[4];
1303  float final_fill_color[4];
1304  mul_v4_v4fl(final_fill_color, expand_cache->fill_color, fade);
1305  IMB_blend_color_float(final_color,
1306  expand_cache->original_colors[vd.index],
1307  final_fill_color,
1308  expand_cache->blend_mode);
1309 
1310  if (equals_v4v4(initial_color, final_color)) {
1311  continue;
1312  }
1313 
1314  SCULPT_vertex_color_set(ss, vd.index, final_color);
1315 
1316  any_changed = true;
1317  }
1319  if (any_changed) {
1321  }
1322 }
1323 
1325 {
1327  SculptSession *ss = ob->sculpt;
1328  switch (ss->expand_cache->target) {
1331  break;
1334  break;
1337  break;
1338  default:
1339  break;
1340  }
1341 }
1342 
1343 /* Store the original mesh data state in the expand cache. */
1345 {
1346  SculptSession *ss = ob->sculpt;
1347  const int totvert = SCULPT_vertex_count_get(ss);
1348  const int totface = ss->totfaces;
1349 
1350  /* Face Sets are always stored as they are needed for snapping. */
1351  expand_cache->initial_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "initial face set");
1352  expand_cache->original_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "original face set");
1353  for (int i = 0; i < totface; i++) {
1354  expand_cache->initial_face_sets[i] = ss->face_sets[i];
1355  expand_cache->original_face_sets[i] = ss->face_sets[i];
1356  }
1357 
1358  if (expand_cache->target == SCULPT_EXPAND_TARGET_MASK) {
1359  expand_cache->original_mask = MEM_malloc_arrayN(totvert, sizeof(float), "initial mask");
1360  for (int i = 0; i < totvert; i++) {
1361  expand_cache->original_mask[i] = SCULPT_vertex_mask_get(ss, i);
1362  }
1363  }
1364 
1365  if (expand_cache->target == SCULPT_EXPAND_TARGET_COLORS) {
1366  expand_cache->original_colors = MEM_malloc_arrayN(totvert, sizeof(float[4]), "initial colors");
1367  for (int i = 0; i < totvert; i++) {
1368  SCULPT_vertex_color_get(ss, i, expand_cache->original_colors[i]);
1369  }
1370  }
1371 }
1372 
1377 {
1378  const int totfaces = ss->totfaces;
1379  for (int i = 0; i < totfaces; i++) {
1380  if (expand_cache->original_face_sets[i] <= 0) {
1381  /* Do not modify hidden Face Sets, even when restoring the IDs state. */
1382  continue;
1383  }
1384  if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, i)) {
1385  continue;
1386  }
1387  ss->face_sets[i] = expand_cache->initial_face_sets[i];
1388  }
1389 }
1390 
1391 static void sculpt_expand_update_for_vertex(bContext *C, Object *ob, const int vertex)
1392 {
1393  SculptSession *ss = ob->sculpt;
1395  ExpandCache *expand_cache = ss->expand_cache;
1396 
1397  /* Update the active factor in the cache. */
1398  if (vertex == SCULPT_EXPAND_VERTEX_NONE) {
1399  /* This means that the cursor is not over the mesh, so a valid active falloff can't be
1400  * determined. In this situations, don't evaluate enabled states and default all vertices in
1401  * connected components to enabled. */
1402  expand_cache->active_falloff = expand_cache->max_vert_falloff;
1403  expand_cache->all_enabled = true;
1404  }
1405  else {
1406  expand_cache->active_falloff = expand_cache->vert_falloff[vertex];
1407  expand_cache->all_enabled = false;
1408  }
1409 
1410  if (expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS) {
1411  /* Face sets needs to be restored their initial state on each iteration as the overwrite
1412  * existing data. */
1413  sculpt_expand_face_sets_restore(ss, expand_cache);
1414  }
1415 
1416  /* Update the mesh sculpt data. */
1418  .sd = sd,
1419  .ob = ob,
1420  .nodes = expand_cache->nodes,
1421  };
1422 
1423  TaskParallelSettings settings;
1424  BKE_pbvh_parallel_range_settings(&settings, true, expand_cache->totnode);
1425 
1426  switch (expand_cache->target) {
1429  0, expand_cache->totnode, &data, sculpt_expand_mask_update_task_cb, &settings);
1430  break;
1432  sculpt_expand_face_sets_update(ss, expand_cache);
1433  break;
1436  0, expand_cache->totnode, &data, sculpt_expand_colors_update_task_cb, &settings);
1437  break;
1438  }
1439 
1441 }
1442 
1447 static int sculpt_expand_target_vertex_update_and_get(bContext *C, Object *ob, const float mval[2])
1448 {
1449  SculptSession *ss = ob->sculpt;
1451  if (SCULPT_cursor_geometry_info_update(C, &sgi, mval, false)) {
1452  return SCULPT_active_vertex_get(ss);
1453  }
1455 }
1456 
1462 {
1463  SculptSession *ss = ob->sculpt;
1464  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
1465  const int totvert = SCULPT_vertex_count_get(ss);
1466 
1467  const bool initial_invert_state = expand_cache->invert;
1468  expand_cache->invert = false;
1469  BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache);
1470 
1471  /* For boundary topology, position the pivot using only the boundary of the enabled vertices,
1472  * without taking mesh boundary into account. This allows to create deformations like bending the
1473  * mesh from the boundary of the mask that was just created. */
1474  const float use_mesh_boundary = expand_cache->falloff_type !=
1476 
1477  BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled(
1478  ss, enabled_vertices, use_mesh_boundary);
1479 
1480  /* Ignore invert state, as this is the expected behavior in most cases and mask are created in
1481  * inverted state by default. */
1482  expand_cache->invert = initial_invert_state;
1483 
1484  int total = 0;
1485  float avg[3] = {0.0f};
1486 
1487  const float *expand_init_co = SCULPT_vertex_co_get(ss, expand_cache->initial_active_vertex);
1488 
1489  for (int i = 0; i < totvert; i++) {
1490  if (!BLI_BITMAP_TEST(boundary_vertices, i)) {
1491  continue;
1492  }
1493 
1494  if (!sculpt_expand_is_vert_in_active_component(ss, expand_cache, i)) {
1495  continue;
1496  }
1497 
1498  const float *vertex_co = SCULPT_vertex_co_get(ss, i);
1499 
1500  if (!SCULPT_check_vertex_pivot_symmetry(vertex_co, expand_init_co, symm)) {
1501  continue;
1502  }
1503 
1504  add_v3_v3(avg, vertex_co);
1505  total++;
1506  }
1507 
1508  MEM_freeN(enabled_vertices);
1509  MEM_freeN(boundary_vertices);
1510 
1511  if (total > 0) {
1512  mul_v3_v3fl(ss->pivot_pos, avg, 1.0f / total);
1513  }
1514 
1516 }
1517 
1519 {
1521  SculptSession *ss = ob->sculpt;
1523 
1524  /* Tag all nodes to redraw to avoid artifacts after the fast partial updates. */
1525  PBVHNode **nodes;
1526  int totnode;
1527  BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
1528  for (int n = 0; n < totnode; n++) {
1530  }
1531  MEM_freeN(nodes);
1532 
1533  switch (ss->expand_cache->target) {
1536  break;
1539  break;
1542  break;
1543  }
1544 
1547 }
1548 
1554  ExpandCache *expand_cache,
1555  const int initial_vertex)
1556 {
1557  SculptSession *ss = ob->sculpt;
1558  for (int i = 0; i < EXPAND_SYMM_AREAS; i++) {
1560  }
1561 
1562  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
1563  for (char symm_it = 0; symm_it <= symm; symm_it++) {
1564  if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
1565  continue;
1566  }
1567 
1568  const int symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(
1569  ob, symm_it, initial_vertex);
1570 
1571  expand_cache->active_connected_components[(int)symm_it] =
1572  ss->vertex_info.connected_component[symm_vertex];
1573  }
1574 }
1575 
1581  Object *ob,
1582  ExpandCache *expand_cache,
1583  const float mval[2])
1584 {
1585  SculptSession *ss = ob->sculpt;
1586  int initial_vertex = sculpt_expand_target_vertex_update_and_get(C, ob, mval);
1587  if (initial_vertex == SCULPT_EXPAND_VERTEX_NONE) {
1588  /* Cursor not over the mesh, for creating valid initial falloffs, fallback to the last active
1589  * vertex in the sculpt session. */
1590  initial_vertex = SCULPT_active_vertex_get(ss);
1591  }
1593  expand_cache->initial_active_vertex = initial_vertex;
1595 
1596  if (expand_cache->next_face_set == SCULPT_FACE_SET_NONE) {
1597  /* Only set the next face set once, otherwise this ID will constantly update to a new one each
1598  * time this function is called for using a new initial vertex from a different cursor
1599  * position. */
1600  if (expand_cache->modify_active_face_set) {
1601  expand_cache->next_face_set = SCULPT_active_face_set_get(ss);
1602  }
1603  else {
1605  }
1606  }
1607 
1608  /* The new mouse position can be over a different connected component, so this needs to be
1609  * updated. */
1610  sculpt_expand_find_active_connected_components_from_vert(ob, expand_cache, initial_vertex);
1611 }
1612 
1618  Object *ob,
1619  const wmEvent *event,
1620  ExpandCache *expand_cache)
1621 {
1623 
1624  const float mval_fl[2] = {UNPACK2(event->mval)};
1625  float move_disp[2];
1626  sub_v2_v2v2(move_disp, mval_fl, expand_cache->initial_mouse_move);
1627 
1628  float new_mval[2];
1629  add_v2_v2v2(new_mval, move_disp, expand_cache->original_mouse_move);
1630 
1631  sculpt_expand_set_initial_components_for_mouse(C, ob, expand_cache, new_mval);
1633  expand_cache,
1634  sd,
1635  ob,
1636  expand_cache->initial_active_vertex,
1637  expand_cache->move_preview_falloff_type);
1638 }
1639 
1644 {
1645  SculptSession *ss = ob->sculpt;
1649  if (!ss->tex_pool) {
1650  ss->tex_pool = BKE_image_pool_new();
1651  }
1652 }
1653 
1658 {
1659  switch (BKE_pbvh_type(ss->pbvh)) {
1660  case PBVH_FACES:
1661  return expand_cache->original_face_sets[ss->active_face_index];
1662  case PBVH_GRIDS: {
1663  const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg,
1664  ss->active_grid_index);
1665  return expand_cache->original_face_sets[face_index];
1666  }
1667  case PBVH_BMESH: {
1668  /* Dyntopo does not support Face Set functionality. */
1669  BLI_assert(false);
1670  }
1671  }
1672  return SCULPT_FACE_SET_NONE;
1673 }
1674 
1675 static int sculpt_expand_modal(bContext *C, wmOperator *op, const wmEvent *event)
1676 {
1678  SculptSession *ss = ob->sculpt;
1680 
1681  /* Skips INBETWEEN_MOUSEMOVE events and other events that may cause unnecessary updates. */
1682  if (!ELEM(event->type, MOUSEMOVE, EVT_MODAL_MAP)) {
1683  return OPERATOR_RUNNING_MODAL;
1684  }
1685 
1686  /* Update SculptSession data. */
1688  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
1690 
1691  /* Update and get the active vertex (and face) from the cursor. */
1692  const float mval_fl[2] = {UNPACK2(event->mval)};
1693  const int target_expand_vertex = sculpt_expand_target_vertex_update_and_get(C, ob, mval_fl);
1694 
1695  /* Handle the modal keymap state changes. */
1696  ExpandCache *expand_cache = ss->expand_cache;
1697  if (event->type == EVT_MODAL_MAP) {
1698  switch (event->val) {
1700  sculpt_expand_cancel(C, op);
1701  return OPERATOR_FINISHED;
1702  }
1704  expand_cache->invert = !expand_cache->invert;
1705  break;
1706  }
1708  expand_cache->preserve = !expand_cache->preserve;
1709  break;
1710  }
1712  expand_cache->falloff_gradient = !expand_cache->falloff_gradient;
1713  break;
1714  }
1716  expand_cache->brush_gradient = !expand_cache->brush_gradient;
1717  if (expand_cache->brush_gradient) {
1718  expand_cache->falloff_gradient = true;
1719  }
1720  break;
1721  }
1723  if (expand_cache->snap) {
1724  expand_cache->snap = false;
1725  if (expand_cache->snap_enabled_face_sets) {
1726  BLI_gset_free(expand_cache->snap_enabled_face_sets, NULL);
1727  expand_cache->snap_enabled_face_sets = NULL;
1728  }
1729  }
1730  else {
1731  expand_cache->snap = true;
1732  if (!expand_cache->snap_enabled_face_sets) {
1733  expand_cache->snap_enabled_face_sets = BLI_gset_int_new("snap face sets");
1734  }
1736  }
1737  } break;
1739  if (expand_cache->move) {
1740  expand_cache->move = false;
1742  expand_cache,
1743  sd,
1744  ob,
1745  expand_cache->initial_active_vertex,
1746  expand_cache->move_original_falloff_type);
1747  break;
1748  }
1749  expand_cache->move = true;
1750  expand_cache->move_original_falloff_type = expand_cache->falloff_type;
1751  copy_v2_v2(expand_cache->initial_mouse_move, mval_fl);
1752  copy_v2_v2(expand_cache->original_mouse_move, expand_cache->initial_mouse);
1753  if (expand_cache->falloff_type == SCULPT_EXPAND_FALLOFF_GEODESIC &&
1754  SCULPT_vertex_count_get(ss) > expand_cache->max_geodesic_move_preview) {
1755  /* Set to spherical falloff for preview in high poly meshes as it is the fastest one.
1756  * In most cases it should match closely the preview from geodesic. */
1758  }
1759  else {
1760  expand_cache->move_preview_falloff_type = expand_cache->falloff_type;
1761  }
1762  break;
1763  }
1766  break;
1767  }
1770  break;
1771  }
1773  sculpt_expand_update_for_vertex(C, ob, target_expand_vertex);
1774 
1775  if (expand_cache->reposition_pivot) {
1776  sculpt_expand_reposition_pivot(C, ob, expand_cache);
1777  }
1778 
1780  return OPERATOR_FINISHED;
1781  }
1784  expand_cache,
1785  sd,
1786  ob,
1787  expand_cache->initial_active_vertex,
1789  break;
1790  }
1793  expand_cache,
1794  sd,
1795  ob,
1796  expand_cache->initial_active_vertex,
1798  break;
1799  }
1802  expand_cache,
1803  sd,
1804  ob,
1805  expand_cache->initial_active_vertex,
1807  break;
1808  }
1811  expand_cache,
1812  sd,
1813  ob,
1814  expand_cache->initial_active_vertex,
1816  break;
1817  }
1819  expand_cache->loop_count += 1;
1820  break;
1821  }
1823  expand_cache->loop_count -= 1;
1824  expand_cache->loop_count = max_ii(expand_cache->loop_count, 1);
1825  break;
1826  }
1828  if (expand_cache->texture_distortion_strength == 0.0f) {
1829  if (expand_cache->brush->mtex.tex == NULL) {
1830  BKE_report(op->reports,
1831  RPT_WARNING,
1832  "Active brush does not contain any texture to distort the expand boundary");
1833  break;
1834  }
1835  if (expand_cache->brush->mtex.brush_map_mode != MTEX_MAP_MODE_3D) {
1836  BKE_report(op->reports,
1837  RPT_WARNING,
1838  "Texture mapping not set to 3D, results may be unpredictable");
1839  }
1840  }
1842  break;
1843  }
1846  expand_cache->texture_distortion_strength = max_ff(
1847  expand_cache->texture_distortion_strength, 0.0f);
1848  break;
1849  }
1850  }
1851  }
1852 
1853  /* Handle expand origin movement if enabled. */
1854  if (expand_cache->move) {
1855  sculpt_expand_move_propagation_origin(C, ob, event, expand_cache);
1856  }
1857 
1858  /* Add new Face Sets IDs to the snapping gset if enabled. */
1859  if (expand_cache->snap) {
1860  const int active_face_set_id = sculpt_expand_active_face_set_id_get(ss, expand_cache);
1861  /* The key may exist, in that case this does nothing. */
1862  BLI_gset_add(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(active_face_set_id));
1863  }
1864 
1865  /* Update the sculpt data with the current state of the #ExpandCache. */
1866  sculpt_expand_update_for_vertex(C, ob, target_expand_vertex);
1867 
1868  return OPERATOR_RUNNING_MODAL;
1869 }
1870 
1877 static void sculpt_expand_delete_face_set_id(int *r_face_sets,
1878  SculptSession *ss,
1879  ExpandCache *expand_cache,
1880  Mesh *mesh,
1881  const int delete_id)
1882 {
1883  const int totface = ss->totfaces;
1884  MeshElemMap *pmap = ss->pmap;
1885 
1886  /* Check that all the face sets IDs in the mesh are not equal to `delete_id`
1887  * before attempting to delete it. */
1888  bool all_same_id = true;
1889  for (int i = 0; i < totface; i++) {
1890  if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, i)) {
1891  continue;
1892  }
1893  if (r_face_sets[i] != delete_id) {
1894  all_same_id = false;
1895  break;
1896  }
1897  }
1898  if (all_same_id) {
1899  return;
1900  }
1901 
1902  BLI_LINKSTACK_DECLARE(queue, void *);
1903  BLI_LINKSTACK_DECLARE(queue_next, void *);
1904 
1906  BLI_LINKSTACK_INIT(queue_next);
1907 
1908  for (int i = 0; i < totface; i++) {
1909  if (r_face_sets[i] == delete_id) {
1911  }
1912  }
1913 
1914  while (BLI_LINKSTACK_SIZE(queue)) {
1915  bool any_updated = false;
1916  while (BLI_LINKSTACK_SIZE(queue)) {
1917  const int f_index = POINTER_AS_INT(BLI_LINKSTACK_POP(queue));
1918  int other_id = delete_id;
1919  const MPoly *c_poly = &mesh->mpoly[f_index];
1920  for (int l = 0; l < c_poly->totloop; l++) {
1921  const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l];
1922  const MeshElemMap *vert_map = &pmap[c_loop->v];
1923  for (int i = 0; i < vert_map->count; i++) {
1924 
1925  const int neighbor_face_index = vert_map->indices[i];
1926  if (expand_cache->original_face_sets[neighbor_face_index] <= 0) {
1927  /* Skip picking IDs from hidden Face Sets. */
1928  continue;
1929  }
1930  if (r_face_sets[neighbor_face_index] != delete_id) {
1931  other_id = r_face_sets[neighbor_face_index];
1932  }
1933  }
1934  }
1935 
1936  if (other_id != delete_id) {
1937  any_updated = true;
1938  r_face_sets[f_index] = other_id;
1939  }
1940  else {
1941  BLI_LINKSTACK_PUSH(queue_next, POINTER_FROM_INT(f_index));
1942  }
1943  }
1944  if (!any_updated) {
1945  /* No Face Sets where updated in this iteration, which means that no more content to keep
1946  * filling the polys of the deleted Face Set was found. Break to avoid entering an infinite
1947  * loop trying to search for those polys again. */
1948  break;
1949  }
1950 
1951  BLI_LINKSTACK_SWAP(queue, queue_next);
1952  }
1953 
1955  BLI_LINKSTACK_FREE(queue_next);
1956 
1957  /* Ensure that the visibility state of the modified Face Sets is the same as the original ones.
1958  */
1959  for (int i = 0; i < totface; i++) {
1960  if (expand_cache->original_face_sets[i] >= 0) {
1961  r_face_sets[i] = abs(r_face_sets[i]);
1962  }
1963  else {
1964  r_face_sets[i] = -abs(r_face_sets[i]);
1965  }
1966  }
1967 }
1968 
1970  wmOperator *op,
1971  ExpandCache *expand_cache)
1972 {
1973  /* RNA properties. */
1974  expand_cache->invert = RNA_boolean_get(op->ptr, "invert");
1975  expand_cache->preserve = RNA_boolean_get(op->ptr, "use_mask_preserve");
1976  expand_cache->falloff_gradient = RNA_boolean_get(op->ptr, "use_falloff_gradient");
1977  expand_cache->target = RNA_enum_get(op->ptr, "target");
1978  expand_cache->modify_active_face_set = RNA_boolean_get(op->ptr, "use_modify_active");
1979  expand_cache->reposition_pivot = RNA_boolean_get(op->ptr, "use_reposition_pivot");
1980  expand_cache->max_geodesic_move_preview = RNA_int_get(op->ptr, "max_geodesic_move_preview");
1981 
1982  /* These can be exposed in RNA if needed. */
1983  expand_cache->loop_count = 1;
1984  expand_cache->brush_gradient = false;
1985 
1986  /* Texture and color data from the active Brush. */
1989  SculptSession *ss = ob->sculpt;
1990  expand_cache->brush = BKE_paint_brush(&sd->paint);
1991  BKE_curvemapping_init(expand_cache->brush->curve);
1992  copy_v4_fl(expand_cache->fill_color, 1.0f);
1993  copy_v3_v3(expand_cache->fill_color, BKE_brush_color_get(ss->scene, expand_cache->brush));
1995 
1996  expand_cache->scene = CTX_data_scene(C);
1997  expand_cache->mtex = &expand_cache->brush->mtex;
1998  expand_cache->texture_distortion_strength = 0.0f;
1999  expand_cache->blend_mode = expand_cache->brush->blend;
2000 }
2001 
2005 static void sculpt_expand_undo_push(Object *ob, ExpandCache *expand_cache)
2006 {
2007  SculptSession *ss = ob->sculpt;
2008  PBVHNode **nodes;
2009  int totnode;
2010  BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
2011 
2012  switch (expand_cache->target) {
2014  for (int i = 0; i < totnode; i++) {
2015  SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
2016  }
2017  break;
2020  break;
2022  for (int i = 0; i < totnode; i++) {
2024  }
2025  break;
2026  }
2027 
2028  MEM_freeN(nodes);
2029 }
2030 
2031 static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2032 {
2035  SculptSession *ss = ob->sculpt;
2037 
2038  /* Create and configure the Expand Cache. */
2039  ss->expand_cache = MEM_callocN(sizeof(ExpandCache), "expand cache");
2041 
2042  /* Update object. */
2043  const bool needs_colors = ss->expand_cache->target == SCULPT_EXPAND_TARGET_COLORS;
2044 
2045  if (needs_colors) {
2046  /* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the updates of
2047  * earlier steps modifying the data. */
2050  }
2051 
2052  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, needs_colors);
2053 
2054  /* Do nothing when the mesh has 0 vertices. */
2055  const int totvert = SCULPT_vertex_count_get(ss);
2056  if (totvert == 0) {
2058  return OPERATOR_CANCELLED;
2059  }
2060 
2061  /* Face Set operations are not supported in dyntopo. */
2063  BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
2065  return OPERATOR_CANCELLED;
2066  }
2067 
2069 
2070  /* Initialize undo. */
2071  SCULPT_undo_push_begin(ob, "expand");
2073 
2074  /* Set the initial element for expand from the event position. */
2075  const float mouse[2] = {event->mval[0], event->mval[1]};
2077 
2078  /* Cache PBVH nodes. */
2080  ss->pbvh, NULL, NULL, &ss->expand_cache->nodes, &ss->expand_cache->totnode);
2081 
2082  /* Store initial state. */
2084 
2087  ss,
2088  ss->expand_cache,
2089  ob->data,
2091  }
2092 
2093  /* Initialize the falloff. */
2094  eSculptExpandFalloffType falloff_type = RNA_enum_get(op->ptr, "falloff_type");
2095 
2096  /* When starting from a boundary vertex, set the initial falloff to boundary. */
2099  }
2100 
2102  ss->expand_cache, sd, ob, ss->expand_cache->initial_active_vertex, falloff_type);
2103 
2104  /* Initial mesh data update, resets all target data in the sculpt mesh. */
2106 
2108  return OPERATOR_RUNNING_MODAL;
2109 }
2110 
2112 {
2113  static const EnumPropertyItem modal_items[] = {
2114  {SCULPT_EXPAND_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
2115  {SCULPT_EXPAND_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
2116  {SCULPT_EXPAND_MODAL_INVERT, "INVERT", 0, "Invert", ""},
2117  {SCULPT_EXPAND_MODAL_PRESERVE_TOGGLE, "PRESERVE", 0, "Toggle Preserve State", ""},
2118  {SCULPT_EXPAND_MODAL_GRADIENT_TOGGLE, "GRADIENT", 0, "Toggle Gradient", ""},
2120  "RECURSION_STEP_GEODESIC",
2121  0,
2122  "Geodesic recursion step",
2123  ""},
2125  "RECURSION_STEP_TOPOLOGY",
2126  0,
2127  "Topology recursion Step",
2128  ""},
2129  {SCULPT_EXPAND_MODAL_MOVE_TOGGLE, "MOVE_TOGGLE", 0, "Move Origin", ""},
2130  {SCULPT_EXPAND_MODAL_FALLOFF_GEODESIC, "FALLOFF_GEODESICS", 0, "Geodesic Falloff", ""},
2131  {SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY, "FALLOFF_TOPOLOGY", 0, "Topology Falloff", ""},
2133  "FALLOFF_TOPOLOGY_DIAGONALS",
2134  0,
2135  "Diagonals Falloff",
2136  ""},
2137  {SCULPT_EXPAND_MODAL_FALLOFF_SPHERICAL, "FALLOFF_SPHERICAL", 0, "Spherical Falloff", ""},
2138  {SCULPT_EXPAND_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap expand to Face Sets", ""},
2140  "LOOP_COUNT_INCREASE",
2141  0,
2142  "Loop Count Increase",
2143  ""},
2145  "LOOP_COUNT_DECREASE",
2146  0,
2147  "Loop Count Decrease",
2148  ""},
2150  "BRUSH_GRADIENT_TOGGLE",
2151  0,
2152  "Toggle Brush Gradient",
2153  ""},
2155  "TEXTURE_DISTORTION_INCREASE",
2156  0,
2157  "Texture Distortion Increase",
2158  ""},
2160  "TEXTURE_DISTORTION_DECREASE",
2161  0,
2162  "Texture Distortion Decrease",
2163  ""},
2164  {0, NULL, 0, NULL, NULL},
2165  };
2166 
2167  static const char *name = "Sculpt Expand Modal";
2168  wmKeyMap *keymap = WM_modalkeymap_find(keyconf, name);
2169 
2170  /* This function is called for each spacetype, only needs to add map once. */
2171  if (keymap && keymap->modal_items) {
2172  return;
2173  }
2174 
2175  keymap = WM_modalkeymap_ensure(keyconf, name, modal_items);
2176  WM_modalkeymap_assign(keymap, "SCULPT_OT_expand");
2177 }
2178 
2180 {
2181  /* Identifiers. */
2182  ot->name = "Expand";
2183  ot->idname = "SCULPT_OT_expand";
2184  ot->description = "Generic sculpt expand operator";
2185 
2186  /* API callbacks. */
2191 
2193 
2194  static EnumPropertyItem prop_sculpt_expand_falloff_type_items[] = {
2195  {SCULPT_EXPAND_FALLOFF_GEODESIC, "GEODESIC", 0, "Geodesic", ""},
2196  {SCULPT_EXPAND_FALLOFF_TOPOLOGY, "TOPOLOGY", 0, "Topology", ""},
2198  "TOPOLOGY_DIAGONALS",
2199  0,
2200  "Topology Diagonals",
2201  ""},
2202  {SCULPT_EXPAND_FALLOFF_NORMALS, "NORMALS", 0, "Normals", ""},
2203  {SCULPT_EXPAND_FALLOFF_SPHERICAL, "SPHERICAL", 0, "Spherical", ""},
2204  {SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY, "BOUNDARY_TOPOLOGY", 0, "Boundary Topology", ""},
2205  {SCULPT_EXPAND_FALLOFF_BOUNDARY_FACE_SET, "BOUNDARY_FACE_SET", 0, "Boundary Face Set", ""},
2206  {SCULPT_EXPAND_FALLOFF_ACTIVE_FACE_SET, "ACTIVE_FACE_SET", 0, "Active Face Set", ""},
2207  {0, NULL, 0, NULL, NULL},
2208  };
2209 
2210  static EnumPropertyItem prop_sculpt_expand_target_type_items[] = {
2211  {SCULPT_EXPAND_TARGET_MASK, "MASK", 0, "Mask", ""},
2212  {SCULPT_EXPAND_TARGET_FACE_SETS, "FACE_SETS", 0, "Face Sets", ""},
2213  {SCULPT_EXPAND_TARGET_COLORS, "COLOR", 0, "Color", ""},
2214  {0, NULL, 0, NULL, NULL},
2215  };
2216 
2217  RNA_def_enum(ot->srna,
2218  "target",
2219  prop_sculpt_expand_target_type_items,
2221  "Data Target",
2222  "Data that is going to be modified in the expand operation");
2223 
2224  RNA_def_enum(ot->srna,
2225  "falloff_type",
2226  prop_sculpt_expand_falloff_type_items,
2228  "Falloff Type",
2229  "Initial falloff of the expand operation");
2230 
2231  ot->prop = RNA_def_boolean(
2232  ot->srna, "invert", false, "Invert", "Invert the expand active elements");
2234  "use_mask_preserve",
2235  false,
2236  "Preserve Previous",
2237  "Preserve the previous state of the target data");
2239  "use_falloff_gradient",
2240  false,
2241  "Falloff Gradient",
2242  "Expand Using a linear falloff");
2243 
2245  "use_modify_active",
2246  false,
2247  "Modify Active",
2248  "Modify the active Face Set instead of creating a new one");
2249 
2250  ot->prop = RNA_def_boolean(
2251  ot->srna,
2252  "use_reposition_pivot",
2253  true,
2254  "Reposition Pivot",
2255  "Reposition the sculpt transform pivot to the boundary of the expand active area");
2256 
2257  ot->prop = RNA_def_int(ot->srna,
2258  "max_geodesic_move_preview",
2259  10000,
2260  0,
2261  INT_MAX,
2262  "Max Vertex Count for Geodesic Move Preview",
2263  "Maximum number of vertices in the mesh for using geodesic falloff when "
2264  "moving the origin of expand. If the total number of vertices is greater "
2265  "than this value, the falloff will be set to spherical when moving",
2266  0,
2267  1000000);
2268 }
float BKE_brush_curve_strength(const struct Brush *br, float p, float len)
float BKE_brush_sample_tex_3d(const struct Scene *scene, const struct Brush *br, const float point[3], float rgba[4], int thread, struct ImagePool *pool)
const float * BKE_brush_color_get(const struct Scene *scene, const struct Brush *brush)
Definition: brush.cc:2210
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1235
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct ToolSettings * CTX_data_tool_settings(const bContext *C)
Definition: context.c:1282
struct ImagePool * BKE_image_pool_new(void)
General operations, lookup, etc. for blender objects.
void BKE_sculpt_update_object_for_edit(struct Depsgraph *depsgraph, struct Object *ob_orig, bool need_pmap, bool need_mask, bool is_paint_tool)
Definition: paint.c:1914
struct Brush * BKE_paint_brush(struct Paint *paint)
Definition: paint.c:607
#define SCULPT_FACE_SET_NONE
Definition: BKE_paint.h:267
void BKE_sculpt_color_layer_create_if_needed(struct Object *object)
Definition: paint.c:1880
A BVH for high poly meshes.
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode)
Definition: BKE_pbvh.h:439
#define PBVH_ITER_ALL
Definition: BKE_pbvh.h:390
void BKE_pbvh_node_mark_update_color(PBVHNode *node)
Definition: pbvh.c:1880
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1798
#define BKE_pbvh_vertex_iter_end
Definition: BKE_pbvh.h:509
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:391
const struct CCGKey * BKE_pbvh_get_grid_key(const PBVH *pbvh)
Definition: pbvh.c:1831
@ PBVH_GRIDS
Definition: BKE_pbvh.h:235
@ PBVH_BMESH
Definition: BKE_pbvh.h:236
@ PBVH_FACES
Definition: BKE_pbvh.h:234
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode)
Definition: pbvh.c:3211
void BKE_pbvh_node_mark_update_mask(PBVHNode *node)
Definition: pbvh.c:1875
void BKE_pbvh_node_mark_redraw(PBVHNode *node)
Definition: pbvh.c:1906
void BKE_pbvh_search_gather(PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot)
Definition: pbvh.c:838
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, int grid_index)
Definition: subdiv_ccg.c:1940
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition: BLI_bitmap.h:40
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:64
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:81
#define BLI_BITMAP_SET(_bitmap, _index, _set)
Definition: BLI_bitmap.h:102
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:16
struct GSet GSet
Definition: BLI_ghash.h:340
GSet * BLI_gset_int_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
bool BLI_gset_haskey(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1007
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1037
bool BLI_gset_add(GSet *gs, void *key)
Definition: BLI_ghash.c:969
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1002
void BLI_gsqueue_free(GSQueue *queue)
Definition: gsqueue.c:90
GSQueue * BLI_gsqueue_new(size_t elem_size)
Definition: gsqueue.c:69
void BLI_gsqueue_push(GSQueue *queue, const void *item)
Definition: gsqueue.c:97
void BLI_gsqueue_pop(GSQueue *queue, void *r_item)
Definition: gsqueue.c:131
bool BLI_gsqueue_is_empty(const GSQueue *queue)
Definition: gsqueue.c:159
MINLINE float max_ff(float a, float b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v4_v4fl(float r[4], const float a[4], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE void copy_v4_fl(float r[4], float f)
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
#define UNPACK2(a)
#define POINTER_FROM_INT(i)
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
Object is a sort of wrapper for general info.
#define MTEX_MAP_MODE_3D
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
void ED_workspace_status_text(struct bContext *C, const char *str)
Definition: area.c:816
int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh)
BLI_INLINE void IMB_colormanagement_srgb_to_scene_linear_v3(float scene_linear[3], const float srgb[3])
void IMB_blend_color_float(float dst[4], const float src1[4], const float src2[4], IMB_BlendMode mode)
Definition: rectop.c:112
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define C
Definition: RandGen.cpp:25
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_GEOM
Definition: WM_types.h:343
#define ND_SELECT
Definition: WM_types.h:455
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define powf(x, y)
Definition: cuda/compat.h:103
OperationNode * node
const Depsgraph * depsgraph
SyclQueue * queue
bool enabled
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define fabsf(x)
Definition: metal/compat.h:219
T abs(const T &a)
static const pxr::TfToken rgba("rgba", pxr::TfToken::Immortal)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: noise.h:15
BLI_INLINE void flip_v3_v3(float out[3], const float in[3], const ePaintSymmetryFlags symm)
Definition: paint_intern.h:392
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3597
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
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_floodfill_add_and_skip_initial(SculptFloodFill *flood, int index)
Definition: sculpt.c:1086
void SCULPT_floodfill_add_initial_with_symmetry(Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, int index, float radius)
Definition: sculpt.c:1092
void SCULPT_boundary_info_ensure(Object *object)
Definition: sculpt.c:5848
int SCULPT_active_vertex_get(SculptSession *ss)
Definition: sculpt.c:271
bool SCULPT_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mval[2], bool use_sampled_normal)
Definition: sculpt.c:4835
int SCULPT_nearest_vertex_get(Sculpt *sd, Object *ob, const float co[3], float max_distance, bool use_original)
Definition: sculpt.c:983
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
bool SCULPT_is_symmetry_iteration_valid(char i, char symm)
Definition: sculpt.c:1025
void SCULPT_connected_components_ensure(Object *ob)
Definition: sculpt.c:5815
void SCULPT_vertex_random_access_ensure(SculptSession *ss)
Definition: sculpt.c:103
void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags)
Definition: sculpt.c:5212
bool SCULPT_vertex_visible_get(SculptSession *ss, int index)
Definition: sculpt.c:356
void SCULPT_vertex_color_set(SculptSession *ss, int index, const float color[4])
Definition: sculpt.c:166
void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
Definition: sculpt.c:5144
void SCULPT_vertex_color_get(const SculptSession *ss, int index, float r_color[4])
Definition: sculpt.c:161
void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
Definition: sculpt.c:171
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
bool SCULPT_mode_poll(bContext *C)
Definition: sculpt.c:3957
int SCULPT_vertex_face_set_get(SculptSession *ss, int index)
Definition: sculpt.c:508
float SCULPT_vertex_mask_get(SculptSession *ss, int index)
Definition: sculpt.c:248
char SCULPT_mesh_symmetry_xyz_get(Object *object)
Definition: sculpt.c:317
bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm)
Definition: sculpt.c:923
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
void SCULPT_tag_update_overlays(bContext *C)
Definition: sculpt.c:1048
void SCULPT_boundary_data_free(SculptBoundary *boundary)
SculptBoundary * SCULPT_boundary_data_init(Object *object, Brush *brush, const int initial_vertex, const float radius)
static void sculpt_expand_cache_data_free(ExpandCache *expand_cache)
#define SCULPT_EXPAND_LOOP_THRESHOLD
static bool mask_expand_normal_floodfill_cb(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
static bool sculpt_expand_is_face_in_active_component(SculptSession *ss, ExpandCache *expand_cache, const int f)
#define SCULPT_EXPAND_TEXTURE_DISTORTION_STEP
Definition: sculpt_expand.c:94
static int sculpt_expand_get_vertex_index_for_symmetry_pass(Object *ob, const char symm_it, const int original_vertex)
static void sculpt_expand_vertex_to_faces_falloff(Mesh *mesh, ExpandCache *expand_cache)
static int sculpt_expand_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void sculpt_expand_update_max_vert_falloff_value(SculptSession *ss, ExpandCache *expand_cache)
static float sculpt_expand_gradient_value_get(SculptSession *ss, ExpandCache *expand_cache, const int v)
#define SCULPT_EXPAND_VERTEX_NONE
Definition: sculpt_expand.c:86
static void sculpt_expand_update_max_face_falloff_factor(SculptSession *ss, ExpandCache *expand_cache)
static void sculpt_expand_cache_free(SculptSession *ss)
static void sculpt_expand_cancel(bContext *C, wmOperator *UNUSED(op))
static BLI_bitmap * sculpt_expand_bitmap_from_enabled(SculptSession *ss, ExpandCache *expand_cache)
static void sculpt_expand_face_sets_restore(SculptSession *ss, ExpandCache *expand_cache)
static float * sculpt_expand_geodesic_falloff_create(Sculpt *sd, Object *ob, const int v)
static void sculpt_expand_finish(bContext *C)
static void sculpt_expand_restore_mask_data(SculptSession *ss, ExpandCache *expand_cache)
static void sculpt_expand_grids_to_faces_falloff(SculptSession *ss, Mesh *mesh, ExpandCache *expand_cache)
static void sculpt_expand_undo_push(Object *ob, ExpandCache *expand_cache)
void SCULPT_OT_expand(wmOperatorType *ot)
static bool sculpt_expand_face_state_get(SculptSession *ss, ExpandCache *expand_cache, const int f)
static float * sculpt_expand_normal_falloff_create(Sculpt *sd, Object *ob, const int v, const float edge_sensitivity)
static void sculpt_expand_mesh_face_falloff_from_vertex_falloff(SculptSession *ss, Mesh *mesh, ExpandCache *expand_cache)
static float * sculpt_expand_diagonals_falloff_create(Object *ob, const int v)
struct ExpandFloodFillData ExpandFloodFillData
static void sculpt_expand_restore_color_data(SculptSession *ss, ExpandCache *expand_cache)
static bool sculpt_expand_state_get(SculptSession *ss, ExpandCache *expand_cache, const int v)
static void sculpt_expand_snap_initialize_from_enabled(SculptSession *ss, ExpandCache *expand_cache)
static void sculpt_expand_flush_updates(bContext *C)
static BLI_bitmap * sculpt_expand_boundary_from_enabled(SculptSession *ss, const BLI_bitmap *enabled_vertices, const bool use_mesh_boundary)
static void sculpt_expand_falloff_factors_from_vertex_and_symm_create(ExpandCache *expand_cache, Sculpt *sd, Object *ob, const int v, eSculptExpandFalloffType falloff_type)
@ SCULPT_EXPAND_MODAL_TEXTURE_DISTORTION_INCREASE
@ SCULPT_EXPAND_MODAL_PRESERVE_TOGGLE
@ SCULPT_EXPAND_MODAL_RECURSION_STEP_TOPOLOGY
@ SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY_DIAGONALS
@ SCULPT_EXPAND_MODAL_INVERT
@ SCULPT_EXPAND_MODAL_LOOP_COUNT_DECREASE
@ SCULPT_EXPAND_MODAL_GRADIENT_TOGGLE
@ SCULPT_EXPAND_MODAL_LOOP_COUNT_INCREASE
@ SCULPT_EXPAND_MODAL_MOVE_TOGGLE
@ SCULPT_EXPAND_MODAL_BRUSH_GRADIENT_TOGGLE
@ SCULPT_EXPAND_MODAL_TEXTURE_DISTORTION_DECREASE
@ SCULPT_EXPAND_MODAL_FALLOFF_CYCLE
@ SCULPT_EXPAND_MODAL_FALLOFF_GEODESIC
@ SCULPT_EXPAND_MODAL_CANCEL
@ SCULPT_EXPAND_MODAL_FALLOFF_SPHERICAL
@ SCULPT_EXPAND_MODAL_SNAP_TOGGLE
@ SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY
@ SCULPT_EXPAND_MODAL_RECURSION_STEP_GEODESIC
@ SCULPT_EXPAND_MODAL_CONFIRM
static void sculpt_expand_update_for_vertex(bContext *C, Object *ob, const int vertex)
static bool expand_topology_floodfill_cb(SculptSession *UNUSED(ss), int from_v, int to_v, bool is_duplicate, void *userdata)
static void sculpt_expand_restore_face_set_data(SculptSession *ss, ExpandCache *expand_cache)
void sculpt_expand_modal_keymap(wmKeyConfig *keyconf)
static float * sculpt_expand_spherical_falloff_create(Object *ob, const int v)
static void sculpt_expand_reposition_pivot(bContext *C, Object *ob, ExpandCache *expand_cache)
static void sculpt_expand_cache_initial_config_set(bContext *C, wmOperator *op, ExpandCache *expand_cache)
static void sculpt_expand_find_active_connected_components_from_vert(Object *ob, ExpandCache *expand_cache, const int initial_vertex)
static float * sculpt_expand_topology_falloff_create(Sculpt *sd, Object *ob, const int v)
static float sculpt_expand_max_vertex_falloff_get(ExpandCache *expand_cache)
static void sculpt_expand_colors_update_task_cb(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
static void sculpt_expand_original_state_store(Object *ob, ExpandCache *expand_cache)
static float * sculpt_expand_boundary_topology_falloff_create(Object *ob, const int v)
static int sculpt_expand_target_vertex_update_and_get(bContext *C, Object *ob, const float mval[2])
#define EXPAND_ACTIVE_COMPONENT_NONE
Definition: sculpt_expand.c:89
static void sculpt_expand_initialize_from_face_set_boundary(Object *ob, ExpandCache *expand_cache, const int active_face_set, const bool internal_falloff)
static int sculpt_expand_active_face_set_id_get(SculptSession *ss, ExpandCache *expand_cache)
static void sculpt_expand_face_sets_update(SculptSession *ss, ExpandCache *expand_cache)
static void sculpt_expand_delete_face_set_id(int *r_face_sets, SculptSession *ss, ExpandCache *expand_cache, Mesh *mesh, const int delete_id)
static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void sculpt_expand_topology_from_state_boundary(Object *ob, ExpandCache *expand_cache, BLI_bitmap *enabled_vertices)
static void sculpt_expand_resursion_step_add(Object *ob, ExpandCache *expand_cache, const eSculptExpandRecursionType recursion_type)
static void sculpt_expand_mask_update_task_cb(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
static float sculpt_expand_falloff_value_vertex_get(SculptSession *ss, ExpandCache *expand_cache, const int v)
static void sculpt_expand_set_initial_components_for_mouse(bContext *C, Object *ob, ExpandCache *expand_cache, const float mval[2])
#define SCULPT_EXPAND_NORMALS_FALLOFF_EDGE_SENSITIVITY
static bool sculpt_expand_is_vert_in_active_component(SculptSession *ss, ExpandCache *expand_cache, const int v)
static void sculpt_expand_restore_original_state(bContext *C, Object *ob, ExpandCache *expand_cache)
static void sculpt_expand_geodesics_from_state_boundary(Object *ob, ExpandCache *expand_cache, BLI_bitmap *enabled_vertices)
static void sculpt_expand_ensure_sculptsession_data(Object *ob)
static void sculpt_expand_move_propagation_origin(bContext *C, Object *ob, const wmEvent *event, ExpandCache *expand_cache)
float * SCULPT_geodesic_from_vertex_and_symm(Sculpt *sd, Object *ob, const int vertex, const float limit_radius)
float * SCULPT_geodesic_distances_create(Object *ob, GSet *initial_vertices, const float limit_radius)
eSculptExpandFalloffType
@ SCULPT_EXPAND_FALLOFF_BOUNDARY_FACE_SET
@ SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY
@ SCULPT_EXPAND_FALLOFF_NORMALS
@ SCULPT_EXPAND_FALLOFF_SPHERICAL
@ SCULPT_EXPAND_FALLOFF_GEODESIC
@ SCULPT_EXPAND_FALLOFF_TOPOLOGY
@ SCULPT_EXPAND_FALLOFF_TOPOLOGY_DIAGONALS
@ SCULPT_EXPAND_FALLOFF_ACTIVE_FACE_SET
void SCULPT_undo_push_begin(struct Object *ob, const char *name)
Definition: sculpt_undo.c:1545
void SCULPT_undo_push_end(struct Object *ob)
Definition: sculpt_undo.c:1575
#define SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator)
eSculptExpandRecursionType
@ SCULPT_EXPAND_RECURSION_GEODESICS
@ SCULPT_EXPAND_RECURSION_TOPOLOGY
@ SCULPT_UPDATE_COLOR
Definition: sculpt_intern.h:48
@ SCULPT_UPDATE_MASK
Definition: sculpt_intern.h:46
#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator)
SculptUndoNode * SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type)
Definition: sculpt_undo.c:1419
#define EXPAND_SYMM_AREAS
@ SCULPT_EXPAND_TARGET_COLORS
@ SCULPT_EXPAND_TARGET_FACE_SETS
@ SCULPT_EXPAND_TARGET_MASK
@ SCULPT_UNDO_FACE_SETS
@ SCULPT_UNDO_COLOR
@ SCULPT_UNDO_MASK
struct MTex mtex
struct CurveMapping * curve
short blend
Definition: BKE_ccg.h:32
int grid_area
Definition: BKE_ccg.h:42
bool brush_gradient
eSculptExpandFalloffType falloff_type
float active_falloff
int * initial_face_sets
int * original_face_sets
float * vert_falloff
eSculptExpandFalloffType move_original_falloff_type
int max_geodesic_move_preview
float initial_mouse[2]
int initial_active_vertex
Brush * brush
float texture_distortion_strength
int initial_active_face_set
bool reposition_pivot
eSculptExpandTargetType target
short blend_mode
float max_vert_falloff
GSet * snap_enabled_face_sets
float * face_falloff
float * original_mask
bool falloff_gradient
float initial_mouse_move[2]
eSculptExpandFalloffType move_preview_falloff_type
bool modify_active_face_set
struct Scene * scene
float(* original_colors)[4]
struct MTex * mtex
int active_connected_components[EXPAND_SYMM_AREAS]
float max_face_falloff
float fill_color[4]
PBVHNode ** nodes
float original_mouse_move[2]
unsigned int v
char brush_map_mode
struct Tex * tex
struct MLoop * mloop
int totpoly
struct MPoly * mpoly
struct SculptSession * sculpt
void * data
float * mask
Definition: BKE_pbvh.h:433
int * vertices
Definition: BKE_paint.h:417
struct SubdivCCG * subdiv_ccg
Definition: BKE_paint.h:547
struct ImagePool * tex_pool
Definition: BKE_paint.h:561
SculptVertexInfo vertex_info
Definition: BKE_paint.h:608
int * face_sets
Definition: BKE_paint.h:536
float pivot_pos[3]
Definition: BKE_paint.h:612
int active_face_index
Definition: BKE_paint.h:570
struct Scene * scene
Definition: BKE_paint.h:591
struct MeshElemMap * pmap
Definition: BKE_paint.h:516
struct MLoop * mloop
Definition: BKE_paint.h:500
struct MPoly * mpoly
Definition: BKE_paint.h:499
struct ExpandCache * expand_cache
Definition: BKE_paint.h:565
int active_grid_index
Definition: BKE_paint.h:571
struct PBVH * pbvh
Definition: BKE_paint.h:550
int * connected_component
Definition: BKE_paint.h:392
Paint paint
short val
Definition: WM_types.h:680
int mval[2]
Definition: WM_types.h:684
short type
Definition: WM_types.h:678
const void * modal_items
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct PointerRNA * ptr
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ EVT_MODAL_MAP
@ MOUSEMOVE
wmOperatorType * ot
Definition: wm_files.c:3479
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition: wm_keymap.c:914
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
Definition: wm_keymap.c:985
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition: wm_keymap.c:888