Blender  V2.93
sculpt_expand.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2021 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "MEM_guardedalloc.h"
25 
26 #include "BLI_blenlib.h"
27 #include "BLI_linklist_stack.h"
28 #include "BLI_math.h"
29 #include "BLI_task.h"
30 
31 #include "BLT_translation.h"
32 
33 #include "DNA_brush_types.h"
34 #include "DNA_mesh_types.h"
35 #include "DNA_meshdata_types.h"
36 #include "DNA_object_types.h"
37 
38 #include "BKE_brush.h"
39 #include "BKE_ccg.h"
40 #include "BKE_colortools.h"
41 #include "BKE_context.h"
42 #include "BKE_image.h"
43 #include "BKE_mesh.h"
44 #include "BKE_mesh_mapping.h"
45 #include "BKE_multires.h"
46 #include "BKE_node.h"
47 #include "BKE_object.h"
48 #include "BKE_paint.h"
49 #include "BKE_pbvh.h"
50 #include "BKE_report.h"
51 #include "BKE_scene.h"
52 #include "BKE_subdiv_ccg.h"
53 
54 #include "DEG_depsgraph.h"
55 
56 #include "WM_api.h"
57 #include "WM_message.h"
58 #include "WM_toolsystem.h"
59 #include "WM_types.h"
60 
61 #include "RNA_access.h"
62 #include "RNA_define.h"
63 
64 #include "ED_object.h"
65 #include "ED_screen.h"
66 #include "ED_sculpt.h"
67 #include "ED_view3d.h"
68 #include "paint_intern.h"
69 #include "sculpt_intern.h"
70 
71 #include "IMB_colormanagement.h"
72 #include "IMB_imbuf.h"
73 
74 #include "bmesh.h"
75 
76 #include <math.h>
77 #include <stdlib.h>
78 
79 /* Sculpt Expand. */
80 /* Operator for creating selections and patterns in Sculpt Mode. Expand can create masks, face sets
81  * and fill vertex colors. */
82 /* The main functionality of the operator
83  * - The operator initializes a value per vertex, called "falloff". There are multiple algorithms
84  * to generate these falloff values which will create different patterns in the result when using
85  * the operator. These falloff values require algorithms that rely on mesh connectivity, so they
86  * are only valid on parts of the mesh that are in the same connected component as the given
87  * initial vertices. If needed, these falloff values are propagated from vertex or grids into the
88  * base mesh faces.
89  *
90  * - On each modal callback, the operator gets the active vertex and face and gets its falloff
91  * value from its precalculated falloff. This is now the active falloff value.
92  * - Using the active falloff value and the settings of the expand operation (which can be modified
93  * during execution using the modal key-map), the operator loops over all elements in the mesh to
94  * check if they are enabled of not.
95  * - Based on each element state after evaluating the settings, the desired mesh data (mask, face
96  * sets, colors...) is updated.
97  */
98 
102 #define SCULPT_EXPAND_VERTEX_NONE -1
103 
105 #define EXPAND_ACTIVE_COMPONENT_NONE -1
110 #define SCULPT_EXPAND_TEXTURE_DISTORTION_STEP 0.01f
111 
117 #define SCULPT_EXPAND_LOOP_THRESHOLD 0.00001f
118 
124 #define SCULPT_EXPAND_NORMALS_FALLOFF_EDGE_SENSITIVITY 300
125 
126 /* Expand Modal Key-map. */
127 enum {
147 };
148 
149 /* Functions for getting the state of mesh elements (vertices and base mesh faces). When the main
150  * functions for getting the state of an element return true it means that data associated to that
151  * element will be modified by expand. */
152 
158  ExpandCache *expand_cache,
159  const int v)
160 {
161  for (int i = 0; i < EXPAND_SYMM_AREAS; i++) {
162  if (ss->vertex_info.connected_component[v] == expand_cache->active_connected_components[i]) {
163  return true;
164  }
165  }
166  return false;
167 }
168 
173  ExpandCache *expand_cache,
174  const int f)
175 {
176  const MLoop *loop = &ss->mloop[ss->mpoly[f].loopstart];
177  return sculpt_expand_is_vert_in_active_component(ss, expand_cache, loop->v);
178 }
179 
185  ExpandCache *expand_cache,
186  const int v)
187 {
188  if (expand_cache->texture_distortion_strength == 0.0f) {
189  return expand_cache->vert_falloff[v];
190  }
191 
192  if (!expand_cache->brush->mtex.tex) {
193  return expand_cache->vert_falloff[v];
194  }
195 
196  float rgba[4];
197  const float *vertex_co = SCULPT_vertex_co_get(ss, v);
198  const float avg = BKE_brush_sample_tex_3d(
199  expand_cache->scene, expand_cache->brush, vertex_co, rgba, 0, ss->tex_pool);
200 
201  const float distortion = (avg - 0.5f) * expand_cache->texture_distortion_strength *
202  expand_cache->max_vert_falloff;
203  return expand_cache->vert_falloff[v] + distortion;
204 }
205 
211 {
212  if (expand_cache->texture_distortion_strength == 0.0f) {
213  return expand_cache->max_vert_falloff;
214  }
215 
216  if (!expand_cache->brush->mtex.tex) {
217  return expand_cache->max_vert_falloff;
218  }
219 
220  return expand_cache->max_vert_falloff +
221  (0.5f * expand_cache->texture_distortion_strength * expand_cache->max_vert_falloff);
222 }
223 
228 static bool sculpt_expand_state_get(SculptSession *ss, ExpandCache *expand_cache, const int v)
229 {
230  if (!SCULPT_vertex_visible_get(ss, v)) {
231  return false;
232  }
233 
234  if (!sculpt_expand_is_vert_in_active_component(ss, expand_cache, v)) {
235  return false;
236  }
237 
238  if (expand_cache->all_enabled) {
239  return true;
240  }
241 
242  bool enabled = false;
243 
244  if (expand_cache->snap) {
245  /* Face Sets are not being modified when using this function, so it is ok to get this directly
246  * from the Sculpt API instead of implementing a custom function to get them from
247  * expand_cache->original_face_sets. */
248  const int face_set = SCULPT_vertex_face_set_get(ss, v);
250  }
251  else {
252  const float max_falloff_factor = sculpt_expand_max_vertex_falloff_get(expand_cache);
253  const float loop_len = (max_falloff_factor / expand_cache->loop_count) +
255 
256  const float vertex_falloff_factor = sculpt_expand_falloff_value_vertex_get(
257  ss, expand_cache, v);
258  const float active_factor = fmod(expand_cache->active_falloff, loop_len);
259  const float falloff_factor = fmod(vertex_falloff_factor, loop_len);
260 
261  enabled = falloff_factor < active_factor;
262  }
263 
264  if (expand_cache->invert) {
265  enabled = !enabled;
266  }
267  return enabled;
268 }
269 
274 static bool sculpt_expand_face_state_get(SculptSession *ss, ExpandCache *expand_cache, const int f)
275 {
276  if (expand_cache->original_face_sets[f] <= 0) {
277  return false;
278  }
279 
280  if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, f)) {
281  return false;
282  }
283 
284  if (expand_cache->all_enabled) {
285  return true;
286  }
287 
288  bool enabled = false;
289 
290  if (expand_cache->snap_enabled_face_sets) {
291  const int face_set = expand_cache->original_face_sets[f];
293  }
294  else {
295  const float loop_len = (expand_cache->max_face_falloff / expand_cache->loop_count) +
297 
298  const float active_factor = fmod(expand_cache->active_falloff, loop_len);
299  const float falloff_factor = fmod(expand_cache->face_falloff[f], loop_len);
300  enabled = falloff_factor < active_factor;
301  }
302 
304  if (ss->face_sets[f] == expand_cache->initial_active_face_set) {
305  enabled = false;
306  }
307  }
308 
309  if (expand_cache->invert) {
310  enabled = !enabled;
311  }
312 
313  return enabled;
314 }
315 
321  ExpandCache *expand_cache,
322  const int v)
323 {
324  if (!expand_cache->falloff_gradient) {
325  return 1.0f;
326  }
327 
328  const float max_falloff_factor = sculpt_expand_max_vertex_falloff_get(expand_cache);
329  const float loop_len = (max_falloff_factor / expand_cache->loop_count) +
331 
332  const float vertex_falloff_factor = sculpt_expand_falloff_value_vertex_get(ss, expand_cache, v);
333  const float active_factor = fmod(expand_cache->active_falloff, loop_len);
334  const float falloff_factor = fmod(vertex_falloff_factor, loop_len);
335 
336  float linear_falloff;
337 
338  if (expand_cache->invert) {
339  /* Active factor is the result of a modulus operation using loop_len, so they will never be
340  * equal and loop_len - active_factor should never be 0. */
341  BLI_assert((loop_len - active_factor) != 0.0f);
342  linear_falloff = (falloff_factor - active_factor) / (loop_len - active_factor);
343  }
344  else {
345  linear_falloff = 1.0f - (falloff_factor / active_factor);
346  }
347 
348  if (!expand_cache->brush_gradient) {
349  return linear_falloff;
350  }
351 
352  return BKE_brush_curve_strength(expand_cache->brush, linear_falloff, 1.0f);
353 }
354 
355 /* Utility functions for getting all vertices state during expand. */
356 
362 {
363  const int totvert = SCULPT_vertex_count_get(ss);
364  BLI_bitmap *enabled_vertices = BLI_BITMAP_NEW(totvert, "enabled vertices");
365  for (int i = 0; i < totvert; i++) {
366  const bool enabled = sculpt_expand_state_get(ss, expand_cache, i);
367  BLI_BITMAP_SET(enabled_vertices, i, enabled);
368  }
369  return enabled_vertices;
370 }
371 
378  const BLI_bitmap *enabled_vertices,
379  const bool use_mesh_boundary)
380 {
381  const int totvert = SCULPT_vertex_count_get(ss);
382  BLI_bitmap *boundary_vertices = BLI_BITMAP_NEW(totvert, "boundary vertices");
383  for (int i = 0; i < totvert; i++) {
384  if (!BLI_BITMAP_TEST(enabled_vertices, i)) {
385  continue;
386  }
387 
388  bool is_expand_boundary = false;
391  if (!BLI_BITMAP_TEST(enabled_vertices, ni.index)) {
392  is_expand_boundary = true;
393  }
394  }
396 
397  if (use_mesh_boundary && SCULPT_vertex_is_boundary(ss, i)) {
398  is_expand_boundary = true;
399  }
400 
401  BLI_BITMAP_SET(boundary_vertices, i, is_expand_boundary);
402  }
403 
404  return boundary_vertices;
405 }
406 
407 /* Functions implementing different algorithms for initializing falloff values. */
408 
414  const char symm_it,
415  const int original_vertex)
416 {
417  SculptSession *ss = ob->sculpt;
418  int symm_vertex = SCULPT_EXPAND_VERTEX_NONE;
419  if (symm_it == 0) {
420  symm_vertex = original_vertex;
421  }
422  else {
423  float location[3];
424  flip_v3_v3(location, SCULPT_vertex_co_get(ss, original_vertex), symm_it);
425  symm_vertex = SCULPT_nearest_vertex_get(NULL, ob, location, FLT_MAX, false);
426  }
427  return symm_vertex;
428 }
429 
434 static float *sculpt_expand_geodesic_falloff_create(Sculpt *sd, Object *ob, const int v)
435 {
436  return SCULPT_geodesic_from_vertex_and_symm(sd, ob, v, FLT_MAX);
437 }
438 
443 typedef struct ExpandFloodFillData {
444  float original_normal[3];
446  float *dists;
447  float *edge_factor;
449 
451  SculptSession *UNUSED(ss), int from_v, int to_v, bool is_duplicate, void *userdata)
452 {
453  ExpandFloodFillData *data = userdata;
454  if (!is_duplicate) {
455  const float to_it = data->dists[from_v] + 1.0f;
456  data->dists[to_v] = to_it;
457  }
458  else {
459  data->dists[to_v] = data->dists[from_v];
460  }
461  return true;
462 }
463 
464 static float *sculpt_expand_topology_falloff_create(Sculpt *sd, Object *ob, const int v)
465 {
466  SculptSession *ss = ob->sculpt;
467  const int totvert = SCULPT_vertex_count_get(ss);
468  float *dists = MEM_calloc_arrayN(sizeof(float), totvert, "topology dist");
469 
470  SculptFloodFill flood;
471  SCULPT_floodfill_init(ss, &flood);
472  SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, v, FLT_MAX);
473 
474  ExpandFloodFillData fdata;
475  fdata.dists = dists;
476 
478  SCULPT_floodfill_free(&flood);
479 
480  return dists;
481 }
482 
489  SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
490 {
491  ExpandFloodFillData *data = userdata;
492  if (!is_duplicate) {
493  float current_normal[3], prev_normal[3];
494  SCULPT_vertex_normal_get(ss, to_v, current_normal);
495  SCULPT_vertex_normal_get(ss, from_v, prev_normal);
496  const float from_edge_factor = data->edge_factor[from_v];
497  data->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) * from_edge_factor;
498  data->dists[to_v] = dot_v3v3(data->original_normal, current_normal) *
499  powf(from_edge_factor, data->edge_sensitivity);
500  CLAMP(data->dists[to_v], 0.0f, 1.0f);
501  }
502  else {
503  /* PBVH_GRIDS duplicate handling. */
504  data->edge_factor[to_v] = data->edge_factor[from_v];
505  data->dists[to_v] = data->dists[from_v];
506  }
507 
508  return true;
509 }
510 
512  Object *ob,
513  const int v,
514  const float edge_sensitivity)
515 {
516  SculptSession *ss = ob->sculpt;
517  const int totvert = SCULPT_vertex_count_get(ss);
518  float *dists = MEM_malloc_arrayN(sizeof(float), totvert, "normal dist");
519  float *edge_factor = MEM_callocN(sizeof(float) * totvert, "mask edge factor");
520  for (int i = 0; i < totvert; i++) {
521  edge_factor[i] = 1.0f;
522  }
523 
524  SculptFloodFill flood;
525  SCULPT_floodfill_init(ss, &flood);
526  SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, v, FLT_MAX);
527 
528  ExpandFloodFillData fdata;
529  fdata.dists = dists;
530  fdata.edge_factor = edge_factor;
531  fdata.edge_sensitivity = edge_sensitivity;
533 
535  SCULPT_floodfill_free(&flood);
536 
537  for (int repeat = 0; repeat < 2; repeat++) {
538  for (int i = 0; i < totvert; i++) {
539  float avg = 0.0f;
542  avg += dists[ni.index];
543  }
545  dists[i] = avg / ni.size;
546  }
547  }
548 
549  MEM_SAFE_FREE(edge_factor);
550 
551  return dists;
552 }
553 
558 static float *sculpt_expand_spherical_falloff_create(Object *ob, const int v)
559 {
560  SculptSession *ss = ob->sculpt;
561  const int totvert = SCULPT_vertex_count_get(ss);
562 
563  float *dists = MEM_malloc_arrayN(sizeof(float), totvert, "spherical dist");
564  for (int i = 0; i < totvert; i++) {
565  dists[i] = FLT_MAX;
566  }
567  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
568 
569  for (char symm_it = 0; symm_it <= symm; symm_it++) {
570  if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
571  continue;
572  }
573  const int symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(ob, symm_it, v);
574  if (symm_vertex != -1) {
575  const float *co = SCULPT_vertex_co_get(ss, symm_vertex);
576  for (int i = 0; i < totvert; i++) {
577  dists[i] = min_ff(dists[i], len_v3v3(co, SCULPT_vertex_co_get(ss, i)));
578  }
579  }
580  }
581 
582  return dists;
583 }
584 
591 {
592  SculptSession *ss = ob->sculpt;
593  const int totvert = SCULPT_vertex_count_get(ss);
594  float *dists = MEM_calloc_arrayN(sizeof(float), totvert, "spherical dist");
595  BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(totvert, "visited vertices");
596  GSQueue *queue = BLI_gsqueue_new(sizeof(int));
597 
598  /* Search and initialize a boundary per symmetry pass, then mark those vertices as visited. */
599  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
600  for (char symm_it = 0; symm_it <= symm; symm_it++) {
601  if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
602  continue;
603  }
604 
605  const int symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(ob, symm_it, v);
606 
607  SculptBoundary *boundary = SCULPT_boundary_data_init(ob, NULL, symm_vertex, FLT_MAX);
608  if (!boundary) {
609  continue;
610  }
611 
612  for (int i = 0; i < boundary->num_vertices; i++) {
613  BLI_gsqueue_push(queue, &boundary->vertices[i]);
614  BLI_BITMAP_ENABLE(visited_vertices, boundary->vertices[i]);
615  }
616  SCULPT_boundary_data_free(boundary);
617  }
618 
619  /* If there are no boundaries, return a falloff with all values set to 0. */
621  return dists;
622  }
623 
624  /* Propagate the values from the boundaries to the rest of the mesh. */
625  while (!BLI_gsqueue_is_empty(queue)) {
626  int v_next;
627  BLI_gsqueue_pop(queue, &v_next);
628 
630  SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, v_next, ni) {
631  if (BLI_BITMAP_TEST(visited_vertices, ni.index)) {
632  continue;
633  }
634  dists[ni.index] = dists[v_next] + 1.0f;
635  BLI_BITMAP_ENABLE(visited_vertices, ni.index);
637  }
639  }
640 
642  MEM_freeN(visited_vertices);
643  return dists;
644 }
645 
651 static float *sculpt_expand_diagonals_falloff_create(Object *ob, const int v)
652 {
653  SculptSession *ss = ob->sculpt;
654  const int totvert = SCULPT_vertex_count_get(ss);
655  float *dists = MEM_calloc_arrayN(sizeof(float), totvert, "spherical dist");
656 
657  /* This algorithm uses mesh data (polys and loops), so this falloff type can't be initialized for
658  * Multires. It also does not make sense to implement it for dyntopo as the result will be the
659  * same as Topology falloff. */
660  if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
661  return dists;
662  }
663 
664  /* Search and mask as visited the initial vertices using the enabled symmetry passes. */
665  BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(totvert, "visited vertices");
666  GSQueue *queue = BLI_gsqueue_new(sizeof(int));
667  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
668  for (char symm_it = 0; symm_it <= symm; symm_it++) {
669  if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
670  continue;
671  }
672 
673  const int symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(ob, symm_it, v);
674 
675  BLI_gsqueue_push(queue, &symm_vertex);
676  BLI_BITMAP_ENABLE(visited_vertices, symm_vertex);
677  }
678 
680  return dists;
681  }
682 
683  /* Propagate the falloff increasing the value by 1 each time a new vertex is visited. */
684  Mesh *mesh = ob->data;
685  while (!BLI_gsqueue_is_empty(queue)) {
686  int v_next;
687  BLI_gsqueue_pop(queue, &v_next);
688  for (int j = 0; j < ss->pmap[v_next].count; j++) {
689  MPoly *p = &ss->mpoly[ss->pmap[v_next].indices[j]];
690  for (int l = 0; l < p->totloop; l++) {
691  const int neighbor_v = mesh->mloop[p->loopstart + l].v;
692  if (BLI_BITMAP_TEST(visited_vertices, neighbor_v)) {
693  continue;
694  }
695  dists[neighbor_v] = dists[v_next] + 1.0f;
696  BLI_BITMAP_ENABLE(visited_vertices, neighbor_v);
697  BLI_gsqueue_push(queue, &neighbor_v);
698  }
699  }
700  }
701 
703  MEM_freeN(visited_vertices);
704  return dists;
705 }
706 
707 /* Functions to update the max_falloff value in the #ExpandCache. These functions are called after
708  * initializing a new falloff to make sure that this value is always updated. */
709 
715  ExpandCache *expand_cache)
716 {
717  const int totvert = SCULPT_vertex_count_get(ss);
718  expand_cache->max_vert_falloff = -FLT_MAX;
719  for (int i = 0; i < totvert; i++) {
720  if (expand_cache->vert_falloff[i] == FLT_MAX) {
721  continue;
722  }
723 
724  if (!sculpt_expand_is_vert_in_active_component(ss, expand_cache, i)) {
725  continue;
726  }
727 
728  expand_cache->max_vert_falloff = max_ff(expand_cache->max_vert_falloff,
729  expand_cache->vert_falloff[i]);
730  }
731 }
732 
738  ExpandCache *expand_cache)
739 {
740  const int totface = ss->totfaces;
741  expand_cache->max_face_falloff = -FLT_MAX;
742  for (int i = 0; i < totface; i++) {
743  if (expand_cache->face_falloff[i] == FLT_MAX) {
744  continue;
745  }
746 
747  if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, i)) {
748  continue;
749  }
750 
751  expand_cache->max_face_falloff = max_ff(expand_cache->max_face_falloff,
752  expand_cache->face_falloff[i]);
753  }
754 }
755 
763  Mesh *mesh,
764  ExpandCache *expand_cache)
765 {
766 
767  const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
768 
769  for (int p = 0; p < mesh->totpoly; p++) {
770  MPoly *poly = &mesh->mpoly[p];
771  float accum = 0.0f;
772  for (int l = 0; l < poly->totloop; l++) {
773  const int grid_loop_index = (poly->loopstart + l) * key->grid_area;
774  for (int g = 0; g < key->grid_area; g++) {
775  accum += expand_cache->vert_falloff[grid_loop_index + g];
776  }
777  }
778  expand_cache->face_falloff[p] = accum / (poly->totloop * key->grid_area);
779  }
780 }
781 
783 {
784  for (int p = 0; p < mesh->totpoly; p++) {
785  MPoly *poly = &mesh->mpoly[p];
786  float accum = 0.0f;
787  for (int l = 0; l < poly->totloop; l++) {
788  MLoop *loop = &mesh->mloop[l + poly->loopstart];
789  accum += expand_cache->vert_falloff[loop->v];
790  }
791  expand_cache->face_falloff[p] = accum / poly->totloop;
792  }
793 }
794 
799  Mesh *mesh,
800  ExpandCache *expand_cache)
801 {
802  BLI_assert(expand_cache->vert_falloff != NULL);
803 
804  if (!expand_cache->face_falloff) {
805  expand_cache->face_falloff = MEM_malloc_arrayN(
806  mesh->totpoly, sizeof(float), "face falloff factors");
807  }
808 
809  if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
811  }
812  else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
813  sculpt_expand_grids_to_faces_falloff(ss, mesh, expand_cache);
814  }
815  else {
816  BLI_assert(false);
817  }
818 }
819 
820 /* Recursions. These functions will generate new falloff values based on the state of the vertices
821  * from the current ExpandCache options and falloff values. */
822 
828  ExpandCache *expand_cache,
829  BLI_bitmap *enabled_vertices)
830 {
831  SculptSession *ss = ob->sculpt;
833 
834  GSet *initial_vertices = BLI_gset_int_new("initial_vertices");
835  BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled(ss, enabled_vertices, false);
836  const int totvert = SCULPT_vertex_count_get(ss);
837  for (int i = 0; i < totvert; i++) {
838  if (!BLI_BITMAP_TEST(boundary_vertices, i)) {
839  continue;
840  }
841  BLI_gset_add(initial_vertices, POINTER_FROM_INT(i));
842  }
843  MEM_freeN(boundary_vertices);
844 
845  MEM_SAFE_FREE(expand_cache->vert_falloff);
846  MEM_SAFE_FREE(expand_cache->face_falloff);
847 
848  expand_cache->vert_falloff = SCULPT_geodesic_distances_create(ob, initial_vertices, FLT_MAX);
849  BLI_gset_free(initial_vertices, NULL);
850 }
851 
857  ExpandCache *expand_cache,
858  BLI_bitmap *enabled_vertices)
859 {
860  MEM_SAFE_FREE(expand_cache->vert_falloff);
861  MEM_SAFE_FREE(expand_cache->face_falloff);
862 
863  SculptSession *ss = ob->sculpt;
864  const int totvert = SCULPT_vertex_count_get(ss);
865 
866  float *dists = MEM_calloc_arrayN(sizeof(float), totvert, "topology dist");
867  BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled(ss, enabled_vertices, false);
868 
869  SculptFloodFill flood;
870  SCULPT_floodfill_init(ss, &flood);
871  for (int i = 0; i < totvert; i++) {
872  if (!BLI_BITMAP_TEST(boundary_vertices, i)) {
873  continue;
874  }
876  }
877  MEM_freeN(boundary_vertices);
878 
879  ExpandFloodFillData fdata;
880  fdata.dists = dists;
882  SCULPT_floodfill_free(&flood);
883 
884  expand_cache->vert_falloff = dists;
885 }
886 
891  ExpandCache *expand_cache,
892  const eSculptExpandRecursionType recursion_type)
893 {
894  SculptSession *ss = ob->sculpt;
895  if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
896  return;
897  }
898 
899  BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache);
900 
901  /* Each time a new recursion step is created, reset the distortion strength. This is the expected
902  * result from the recursion, as otherwise the new falloff will render with undesired distortion
903  * from the beginning. */
904  expand_cache->texture_distortion_strength = 0.0f;
905 
906  switch (recursion_type) {
908  sculpt_expand_geodesics_from_state_boundary(ob, expand_cache, enabled_vertices);
909  break;
911  sculpt_expand_topology_from_state_boundary(ob, expand_cache, enabled_vertices);
912  break;
913  }
914 
916  if (expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS) {
919  }
920 
921  MEM_freeN(enabled_vertices);
922 }
923 
924 /* Face Set Boundary falloff. */
925 
931  ExpandCache *expand_cache,
932  const int active_face_set,
933  const bool internal_falloff)
934 {
935  SculptSession *ss = ob->sculpt;
936  const int totvert = SCULPT_vertex_count_get(ss);
937 
938  BLI_bitmap *enabled_vertices = BLI_BITMAP_NEW(totvert, "enabled vertices");
939  for (int i = 0; i < totvert; i++) {
940  if (!SCULPT_vertex_has_unique_face_set(ss, i)) {
941  continue;
942  }
943  if (!SCULPT_vertex_has_face_set(ss, i, active_face_set)) {
944  continue;
945  }
946  BLI_BITMAP_ENABLE(enabled_vertices, i);
947  }
948 
949  if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
950  sculpt_expand_geodesics_from_state_boundary(ob, expand_cache, enabled_vertices);
951  }
952  else {
953  sculpt_expand_topology_from_state_boundary(ob, expand_cache, enabled_vertices);
954  }
955 
956  MEM_freeN(enabled_vertices);
957 
958  if (internal_falloff) {
959  for (int i = 0; i < totvert; i++) {
960  if (!(SCULPT_vertex_has_face_set(ss, i, active_face_set) &&
962  continue;
963  }
964  expand_cache->vert_falloff[i] *= -1.0f;
965  }
966 
967  float min_factor = FLT_MAX;
968  for (int i = 0; i < totvert; i++) {
969  min_factor = min_ff(expand_cache->vert_falloff[i], min_factor);
970  }
971 
972  const float additional_falloff = fabsf(min_factor);
973  for (int i = 0; i < totvert; i++) {
974  expand_cache->vert_falloff[i] += additional_falloff;
975  }
976  }
977  else {
978  for (int i = 0; i < totvert; i++) {
979  if (!SCULPT_vertex_has_face_set(ss, i, active_face_set)) {
980  continue;
981  }
982  expand_cache->vert_falloff[i] = 0.0f;
983  }
984  }
985 }
986 
992  ExpandCache *expand_cache,
993  Sculpt *sd,
994  Object *ob,
995  const int v,
996  eSculptExpandFalloffType falloff_type)
997 {
998  MEM_SAFE_FREE(expand_cache->vert_falloff);
999  expand_cache->falloff_type = falloff_type;
1000 
1001  SculptSession *ss = ob->sculpt;
1002  const bool has_topology_info = BKE_pbvh_type(ss->pbvh) == PBVH_FACES;
1003 
1004  switch (falloff_type) {
1006  expand_cache->vert_falloff = has_topology_info ?
1009  break;
1011  expand_cache->vert_falloff = sculpt_expand_topology_falloff_create(sd, ob, v);
1012  break;
1014  expand_cache->vert_falloff = has_topology_info ?
1017  break;
1021  break;
1024  break;
1027  break;
1030  ob, expand_cache, expand_cache->initial_active_face_set, true);
1031  break;
1034  ob, expand_cache, expand_cache->initial_active_face_set, false);
1035  break;
1036  }
1037 
1038  /* Update max falloff values and propagate to base mesh faces if needed. */
1040  if (expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS) {
1043  }
1044 }
1045 
1052  ExpandCache *expand_cache)
1053 {
1054  if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
1055  return;
1056  }
1057 
1058  /* Make sure this code runs with snapping and invert disabled. This simplifies the code and
1059  * prevents using this function with snapping already enabled. */
1060  const bool prev_snap_state = expand_cache->snap;
1061  const bool prev_invert_state = expand_cache->invert;
1062  expand_cache->snap = false;
1063  expand_cache->invert = false;
1064 
1065  BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache);
1066 
1067  const int totface = ss->totfaces;
1068  for (int i = 0; i < totface; i++) {
1069  const int face_set = expand_cache->original_face_sets[i];
1070  BLI_gset_add(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(face_set));
1071  }
1072 
1073  for (int p = 0; p < totface; p++) {
1074  MPoly *poly = &ss->mpoly[p];
1075  bool any_disabled = false;
1076  for (int l = 0; l < poly->totloop; l++) {
1077  MLoop *loop = &ss->mloop[l + poly->loopstart];
1078  if (!BLI_BITMAP_TEST(enabled_vertices, loop->v)) {
1079  any_disabled = true;
1080  break;
1081  }
1082  }
1083  if (any_disabled) {
1084  const int face_set = expand_cache->original_face_sets[p];
1085  BLI_gset_remove(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(face_set), NULL);
1086  }
1087  }
1088 
1089  MEM_freeN(enabled_vertices);
1090  expand_cache->snap = prev_snap_state;
1091  expand_cache->invert = prev_invert_state;
1092 }
1093 
1097 static void sculpt_expand_cache_data_free(ExpandCache *expand_cache)
1098 {
1099  if (expand_cache->snap_enabled_face_sets) {
1100  BLI_gset_free(expand_cache->snap_enabled_face_sets, NULL);
1101  }
1102  MEM_SAFE_FREE(expand_cache->nodes);
1103  MEM_SAFE_FREE(expand_cache->vert_falloff);
1104  MEM_SAFE_FREE(expand_cache->face_falloff);
1105  MEM_SAFE_FREE(expand_cache->original_mask);
1106  MEM_SAFE_FREE(expand_cache->original_face_sets);
1107  MEM_SAFE_FREE(expand_cache->initial_face_sets);
1108  MEM_SAFE_FREE(expand_cache->original_colors);
1109  MEM_SAFE_FREE(expand_cache);
1110 }
1111 
1113 {
1115  /* Needs to be set to NULL as the paint cursor relies on checking this pointer detecting if an
1116  * expand operation is running. */
1117  ss->expand_cache = NULL;
1118 }
1119 
1124 {
1125  PBVHNode **nodes;
1126  int totnode;
1127  BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
1128  for (int n = 0; n < totnode; n++) {
1129  PBVHNode *node = nodes[n];
1131  }
1132  MEM_freeN(nodes);
1133  for (int i = 0; i < ss->totfaces; i++) {
1134  ss->face_sets[i] = expand_cache->original_face_sets[i];
1135  }
1136 }
1137 
1139 {
1140  PBVHNode **nodes;
1141  int totnode;
1142  BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
1143  for (int n = 0; n < totnode; n++) {
1144  PBVHNode *node = nodes[n];
1145  PBVHVertexIter vd;
1147  copy_v4_v4(vd.col, expand_cache->original_colors[vd.index]);
1148  }
1151  }
1152  MEM_freeN(nodes);
1153 }
1154 
1156 {
1157  PBVHNode **nodes;
1158  int totnode;
1159  BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
1160  for (int n = 0; n < totnode; n++) {
1161  PBVHNode *node = nodes[n];
1162  PBVHVertexIter vd;
1164  *vd.mask = expand_cache->original_mask[vd.index];
1165  }
1168  }
1169  MEM_freeN(nodes);
1170 }
1171 
1172 /* Main function to restore the original state of the data to how it was before starting the expand
1173  * operation. */
1175  Object *ob,
1176  ExpandCache *expand_cache)
1177 {
1178 
1179  SculptSession *ss = ob->sculpt;
1180  switch (expand_cache->target) {
1182  sculpt_expand_restore_mask_data(ss, expand_cache);
1186  break;
1188  sculpt_expand_restore_face_set_data(ss, expand_cache);
1192  break;
1194  sculpt_expand_restore_color_data(ss, expand_cache);
1197  break;
1198  }
1199 }
1200 
1205 {
1207  SculptSession *ss = ob->sculpt;
1208 
1210 
1213 }
1214 
1215 /* Functions to update the sculpt mesh data. */
1216 
1220 static void sculpt_expand_mask_update_task_cb(void *__restrict userdata,
1221  const int i,
1222  const TaskParallelTLS *__restrict UNUSED(tls))
1223 {
1224  SculptThreadedTaskData *data = userdata;
1225  SculptSession *ss = data->ob->sculpt;
1226  PBVHNode *node = data->nodes[i];
1227  ExpandCache *expand_cache = ss->expand_cache;
1228 
1229  bool any_changed = false;
1230 
1231  PBVHVertexIter vd;
1233  const float initial_mask = *vd.mask;
1234  const bool enabled = sculpt_expand_state_get(ss, expand_cache, vd.index);
1235 
1236  float new_mask;
1237 
1238  if (enabled) {
1239  new_mask = sculpt_expand_gradient_value_get(ss, expand_cache, vd.index);
1240  }
1241  else {
1242  new_mask = 0.0f;
1243  }
1244 
1245  if (expand_cache->preserve) {
1246  new_mask = max_ff(new_mask, expand_cache->original_mask[vd.index]);
1247  }
1248 
1249  if (new_mask == initial_mask) {
1250  continue;
1251  }
1252 
1253  *vd.mask = clamp_f(new_mask, 0.0f, 1.0f);
1254  any_changed = true;
1255  if (vd.mvert) {
1257  }
1258  }
1260  if (any_changed) {
1262  }
1263 }
1264 
1269 {
1270  const int totface = ss->totfaces;
1271  for (int f = 0; f < totface; f++) {
1272  const bool enabled = sculpt_expand_face_state_get(ss, expand_cache, f);
1273  if (!enabled) {
1274  continue;
1275  }
1276  if (expand_cache->preserve) {
1277  ss->face_sets[f] += expand_cache->next_face_set;
1278  }
1279  else {
1280  ss->face_sets[f] = expand_cache->next_face_set;
1281  }
1282  }
1283 
1284  for (int i = 0; i < expand_cache->totnode; i++) {
1286  }
1287 }
1288 
1292 static void sculpt_expand_colors_update_task_cb(void *__restrict userdata,
1293  const int i,
1294  const TaskParallelTLS *__restrict UNUSED(tls))
1295 {
1296  SculptThreadedTaskData *data = userdata;
1297  SculptSession *ss = data->ob->sculpt;
1298  PBVHNode *node = data->nodes[i];
1299  ExpandCache *expand_cache = ss->expand_cache;
1300 
1301  bool any_changed = false;
1302 
1303  PBVHVertexIter vd;
1305  float initial_color[4];
1306  copy_v4_v4(initial_color, vd.col);
1307 
1308  const bool enabled = sculpt_expand_state_get(ss, expand_cache, vd.index);
1309  float fade;
1310 
1311  if (enabled) {
1312  fade = sculpt_expand_gradient_value_get(ss, expand_cache, vd.index);
1313  }
1314  else {
1315  fade = 0.0f;
1316  }
1317 
1318  fade *= 1.0f - *vd.mask;
1319  fade = clamp_f(fade, 0.0f, 1.0f);
1320 
1321  float final_color[4];
1322  float final_fill_color[4];
1323  mul_v4_v4fl(final_fill_color, expand_cache->fill_color, fade);
1324  IMB_blend_color_float(final_color,
1325  expand_cache->original_colors[vd.index],
1326  final_fill_color,
1327  expand_cache->blend_mode);
1328 
1329  if (equals_v4v4(initial_color, final_color)) {
1330  continue;
1331  }
1332 
1333  copy_v4_v4(vd.col, final_color);
1334  any_changed = true;
1335  if (vd.mvert) {
1337  }
1338  }
1340  if (any_changed) {
1342  }
1343 }
1344 
1346 {
1348  SculptSession *ss = ob->sculpt;
1349  switch (ss->expand_cache->target) {
1352  break;
1355  break;
1358  break;
1359  default:
1360  break;
1361  }
1362 }
1363 
1364 /* Store the original mesh data state in the expand cache. */
1366 {
1367  SculptSession *ss = ob->sculpt;
1368  const int totvert = SCULPT_vertex_count_get(ss);
1369  const int totface = ss->totfaces;
1370 
1371  /* Face Sets are always stored as they are needed for snapping. */
1372  expand_cache->initial_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "initial face set");
1373  expand_cache->original_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "original face set");
1374  for (int i = 0; i < totface; i++) {
1375  expand_cache->initial_face_sets[i] = ss->face_sets[i];
1376  expand_cache->original_face_sets[i] = ss->face_sets[i];
1377  }
1378 
1379  if (expand_cache->target == SCULPT_EXPAND_TARGET_MASK) {
1380  expand_cache->original_mask = MEM_malloc_arrayN(totvert, sizeof(float), "initial mask");
1381  for (int i = 0; i < totvert; i++) {
1382  expand_cache->original_mask[i] = SCULPT_vertex_mask_get(ss, i);
1383  }
1384  }
1385 
1386  if (expand_cache->target == SCULPT_EXPAND_TARGET_COLORS) {
1387  expand_cache->original_colors = MEM_malloc_arrayN(totvert, sizeof(float[4]), "initial colors");
1388  for (int i = 0; i < totvert; i++) {
1389  copy_v4_v4(expand_cache->original_colors[i], SCULPT_vertex_color_get(ss, i));
1390  }
1391  }
1392 }
1393 
1398 {
1399  const int totfaces = ss->totfaces;
1400  for (int i = 0; i < totfaces; i++) {
1401  if (expand_cache->original_face_sets[i] <= 0) {
1402  /* Do not modify hidden Face Sets, even when restoring the IDs state. */
1403  continue;
1404  }
1405  if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, i)) {
1406  continue;
1407  }
1408  ss->face_sets[i] = expand_cache->initial_face_sets[i];
1409  }
1410 }
1411 
1412 static void sculpt_expand_update_for_vertex(bContext *C, Object *ob, const int vertex)
1413 {
1414  SculptSession *ss = ob->sculpt;
1416  ExpandCache *expand_cache = ss->expand_cache;
1417 
1418  /* Update the active factor in the cache. */
1419  if (vertex == SCULPT_EXPAND_VERTEX_NONE) {
1420  /* This means that the cursor is not over the mesh, so a valid active falloff can't be
1421  * determined. In this situations, don't evaluate enabled states and default all vertices in
1422  * connected components to enabled. */
1423  expand_cache->active_falloff = expand_cache->max_vert_falloff;
1424  expand_cache->all_enabled = true;
1425  }
1426  else {
1427  expand_cache->active_falloff = expand_cache->vert_falloff[vertex];
1428  expand_cache->all_enabled = false;
1429  }
1430 
1431  if (expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS) {
1432  /* Face sets needs to be restored their initial state on each iteration as the overwrite
1433  * existing data. */
1434  sculpt_expand_face_sets_restore(ss, expand_cache);
1435  }
1436 
1437  /* Update the mesh sculpt data. */
1439  .sd = sd,
1440  .ob = ob,
1441  .nodes = expand_cache->nodes,
1442  };
1443 
1444  TaskParallelSettings settings;
1445  BKE_pbvh_parallel_range_settings(&settings, true, expand_cache->totnode);
1446 
1447  switch (expand_cache->target) {
1450  0, expand_cache->totnode, &data, sculpt_expand_mask_update_task_cb, &settings);
1451  break;
1453  sculpt_expand_face_sets_update(ss, expand_cache);
1454  break;
1457  0, expand_cache->totnode, &data, sculpt_expand_colors_update_task_cb, &settings);
1458  break;
1459  }
1460 
1462 }
1463 
1469  Object *ob,
1470  const float mouse[2])
1471 {
1472  SculptSession *ss = ob->sculpt;
1474  if (SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false)) {
1475  return SCULPT_active_vertex_get(ss);
1476  }
1478 }
1479 
1485 {
1486  SculptSession *ss = ob->sculpt;
1487  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
1488  const int totvert = SCULPT_vertex_count_get(ss);
1489 
1490  const bool initial_invert_state = expand_cache->invert;
1491  expand_cache->invert = false;
1492  BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache);
1493 
1494  /* For boundary topology, position the pivot using only the boundary of the enabled vertices,
1495  * without taking mesh boundary into account. This allows to create deformations like bending the
1496  * mesh from the boundary of the mask that was just created. */
1497  const float use_mesh_boundary = expand_cache->falloff_type !=
1499 
1500  BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled(
1501  ss, enabled_vertices, use_mesh_boundary);
1502 
1503  /* Ignore invert state, as this is the expected behavior in most cases and mask are created in
1504  * inverted state by default. */
1505  expand_cache->invert = initial_invert_state;
1506 
1507  int total = 0;
1508  float avg[3] = {0.0f};
1509 
1510  const float *expand_init_co = SCULPT_vertex_co_get(ss, expand_cache->initial_active_vertex);
1511 
1512  for (int i = 0; i < totvert; i++) {
1513  if (!BLI_BITMAP_TEST(boundary_vertices, i)) {
1514  continue;
1515  }
1516 
1517  if (!sculpt_expand_is_vert_in_active_component(ss, expand_cache, i)) {
1518  continue;
1519  }
1520 
1521  const float *vertex_co = SCULPT_vertex_co_get(ss, i);
1522 
1523  if (!SCULPT_check_vertex_pivot_symmetry(vertex_co, expand_init_co, symm)) {
1524  continue;
1525  }
1526 
1527  add_v3_v3(avg, vertex_co);
1528  total++;
1529  }
1530 
1531  MEM_freeN(enabled_vertices);
1532  MEM_freeN(boundary_vertices);
1533 
1534  if (total > 0) {
1535  mul_v3_v3fl(ss->pivot_pos, avg, 1.0f / total);
1536  }
1537 
1539 }
1540 
1542 {
1544  SculptSession *ss = ob->sculpt;
1546 
1547  /* Tag all nodes to redraw to avoid artifacts after the fast partial updates. */
1548  PBVHNode **nodes;
1549  int totnode;
1550  BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
1551  for (int n = 0; n < totnode; n++) {
1553  }
1554  MEM_freeN(nodes);
1555 
1556  switch (ss->expand_cache->target) {
1559  break;
1562  break;
1565  break;
1566  }
1567 
1570 }
1571 
1577  ExpandCache *expand_cache,
1578  const int initial_vertex)
1579 {
1580  SculptSession *ss = ob->sculpt;
1581  for (int i = 0; i < EXPAND_SYMM_AREAS; i++) {
1583  }
1584 
1585  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
1586  for (char symm_it = 0; symm_it <= symm; symm_it++) {
1587  if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
1588  continue;
1589  }
1590 
1591  const int symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(
1592  ob, symm_it, initial_vertex);
1593 
1594  expand_cache->active_connected_components[(int)symm_it] =
1595  ss->vertex_info.connected_component[symm_vertex];
1596  }
1597 }
1598 
1604  Object *ob,
1605  ExpandCache *expand_cache,
1606  const float mouse[2])
1607 {
1608  SculptSession *ss = ob->sculpt;
1609  int initial_vertex = sculpt_expand_target_vertex_update_and_get(C, ob, mouse);
1610  if (initial_vertex == SCULPT_EXPAND_VERTEX_NONE) {
1611  /* Cursor not over the mesh, for creating valid initial falloffs, fallback to the last active
1612  * vertex in the sculpt session. */
1613  initial_vertex = SCULPT_active_vertex_get(ss);
1614  }
1615  copy_v2_v2(ss->expand_cache->initial_mouse, mouse);
1616  expand_cache->initial_active_vertex = initial_vertex;
1618 
1619  if (expand_cache->next_face_set == SCULPT_FACE_SET_NONE) {
1620  /* Only set the next face set once, otherwise this ID will constantly update to a new one each
1621  * time this function is called for using a new initial vertex from a different cursor
1622  * position. */
1623  if (expand_cache->modify_active_face_set) {
1624  expand_cache->next_face_set = SCULPT_active_face_set_get(ss);
1625  }
1626  else {
1628  }
1629  }
1630 
1631  /* The new mouse position can be over a different connected component, so this needs to be
1632  * updated. */
1633  sculpt_expand_find_active_connected_components_from_vert(ob, expand_cache, initial_vertex);
1634 }
1635 
1641  Object *ob,
1642  const wmEvent *event,
1643  ExpandCache *expand_cache)
1644 {
1646 
1647  const float mouse[2] = {event->mval[0], event->mval[1]};
1648  float move_disp[2];
1649  sub_v2_v2v2(move_disp, mouse, expand_cache->initial_mouse_move);
1650 
1651  float new_mouse[2];
1652  add_v2_v2v2(new_mouse, move_disp, expand_cache->original_mouse_move);
1653 
1654  sculpt_expand_set_initial_components_for_mouse(C, ob, expand_cache, new_mouse);
1656  expand_cache,
1657  sd,
1658  ob,
1659  expand_cache->initial_active_vertex,
1660  expand_cache->move_preview_falloff_type);
1661 }
1662 
1667 {
1668  SculptSession *ss = ob->sculpt;
1672  if (!ss->tex_pool) {
1673  ss->tex_pool = BKE_image_pool_new();
1674  }
1675 }
1676 
1681 {
1682  switch (BKE_pbvh_type(ss->pbvh)) {
1683  case PBVH_FACES:
1684  return expand_cache->original_face_sets[ss->active_face_index];
1685  case PBVH_GRIDS: {
1686  const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg,
1687  ss->active_grid_index);
1688  return expand_cache->original_face_sets[face_index];
1689  }
1690  case PBVH_BMESH: {
1691  /* Dyntopo does not support Face Set functionality. */
1692  BLI_assert(false);
1693  }
1694  }
1695  return SCULPT_FACE_SET_NONE;
1696 }
1697 
1698 static int sculpt_expand_modal(bContext *C, wmOperator *op, const wmEvent *event)
1699 {
1701  SculptSession *ss = ob->sculpt;
1703 
1704  /* Skips INBETWEEN_MOUSEMOVE events and other events that may cause unnecessary updates. */
1705  if (!ELEM(event->type, MOUSEMOVE, EVT_MODAL_MAP)) {
1706  return OPERATOR_RUNNING_MODAL;
1707  }
1708 
1709  /* Update SculptSession data. */
1711  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
1713 
1714  /* Update and get the active vertex (and face) from the cursor. */
1715  const float mouse[2] = {event->mval[0], event->mval[1]};
1716  const int target_expand_vertex = sculpt_expand_target_vertex_update_and_get(C, ob, mouse);
1717 
1718  /* Handle the modal keymap state changes. */
1719  ExpandCache *expand_cache = ss->expand_cache;
1720  if (event->type == EVT_MODAL_MAP) {
1721  switch (event->val) {
1723  sculpt_expand_cancel(C, op);
1724  return OPERATOR_FINISHED;
1725  }
1727  expand_cache->invert = !expand_cache->invert;
1728  break;
1729  }
1731  expand_cache->preserve = !expand_cache->preserve;
1732  break;
1733  }
1735  expand_cache->falloff_gradient = !expand_cache->falloff_gradient;
1736  break;
1737  }
1739  expand_cache->brush_gradient = !expand_cache->brush_gradient;
1740  if (expand_cache->brush_gradient) {
1741  expand_cache->falloff_gradient = true;
1742  }
1743  break;
1744  }
1746  if (expand_cache->snap) {
1747  expand_cache->snap = false;
1748  if (expand_cache->snap_enabled_face_sets) {
1749  BLI_gset_free(expand_cache->snap_enabled_face_sets, NULL);
1750  expand_cache->snap_enabled_face_sets = NULL;
1751  }
1752  }
1753  else {
1754  expand_cache->snap = true;
1755  if (!expand_cache->snap_enabled_face_sets) {
1756  expand_cache->snap_enabled_face_sets = BLI_gset_int_new("snap face sets");
1757  }
1759  }
1760  } break;
1762  if (expand_cache->move) {
1763  expand_cache->move = false;
1765  expand_cache,
1766  sd,
1767  ob,
1768  expand_cache->initial_active_vertex,
1769  expand_cache->move_original_falloff_type);
1770  break;
1771  }
1772  expand_cache->move = true;
1773  expand_cache->move_original_falloff_type = expand_cache->falloff_type;
1774  copy_v2_v2(expand_cache->initial_mouse_move, mouse);
1775  copy_v2_v2(expand_cache->original_mouse_move, expand_cache->initial_mouse);
1776  if (expand_cache->falloff_type == SCULPT_EXPAND_FALLOFF_GEODESIC &&
1777  SCULPT_vertex_count_get(ss) > expand_cache->max_geodesic_move_preview) {
1778  /* Set to spherical falloff for preview in high poly meshes as it is the fastest one.
1779  * In most cases it should match closely the preview from geodesic. */
1781  }
1782  else {
1783  expand_cache->move_preview_falloff_type = expand_cache->falloff_type;
1784  }
1785  break;
1786  }
1789  break;
1790  }
1793  break;
1794  }
1796  sculpt_expand_update_for_vertex(C, ob, target_expand_vertex);
1797 
1798  if (expand_cache->reposition_pivot) {
1799  sculpt_expand_reposition_pivot(C, ob, expand_cache);
1800  }
1801 
1803  return OPERATOR_FINISHED;
1804  }
1807  expand_cache,
1808  sd,
1809  ob,
1810  expand_cache->initial_active_vertex,
1812  break;
1813  }
1816  expand_cache,
1817  sd,
1818  ob,
1819  expand_cache->initial_active_vertex,
1821  break;
1822  }
1825  expand_cache,
1826  sd,
1827  ob,
1828  expand_cache->initial_active_vertex,
1830  break;
1831  }
1834  expand_cache,
1835  sd,
1836  ob,
1837  expand_cache->initial_active_vertex,
1839  break;
1840  }
1842  expand_cache->loop_count += 1;
1843  break;
1844  }
1846  expand_cache->loop_count -= 1;
1847  expand_cache->loop_count = max_ii(expand_cache->loop_count, 1);
1848  break;
1849  }
1851  if (expand_cache->texture_distortion_strength == 0.0f) {
1852  if (expand_cache->brush->mtex.tex == NULL) {
1853  BKE_report(op->reports,
1854  RPT_WARNING,
1855  "Active brush does not contain any texture to distort the expand boundary");
1856  break;
1857  }
1858  if (expand_cache->brush->mtex.brush_map_mode != MTEX_MAP_MODE_3D) {
1859  BKE_report(op->reports,
1860  RPT_WARNING,
1861  "Texture mapping not set to 3D, results may be unpredictable");
1862  }
1863  }
1865  break;
1866  }
1869  expand_cache->texture_distortion_strength = max_ff(
1870  expand_cache->texture_distortion_strength, 0.0f);
1871  break;
1872  }
1873  }
1874  }
1875 
1876  /* Handle expand origin movement if enabled. */
1877  if (expand_cache->move) {
1878  sculpt_expand_move_propagation_origin(C, ob, event, expand_cache);
1879  }
1880 
1881  /* Add new Face Sets IDs to the snapping gset if enabled. */
1882  if (expand_cache->snap) {
1883  const int active_face_set_id = sculpt_expand_active_face_set_id_get(ss, expand_cache);
1884  if (!BLI_gset_haskey(expand_cache->snap_enabled_face_sets,
1885  POINTER_FROM_INT(active_face_set_id))) {
1886  BLI_gset_add(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(active_face_set_id));
1887  }
1888  }
1889 
1890  /* Update the sculpt data with the current state of the #ExpandCache. */
1891  sculpt_expand_update_for_vertex(C, ob, target_expand_vertex);
1892 
1893  return OPERATOR_RUNNING_MODAL;
1894 }
1895 
1902 static void sculpt_expand_delete_face_set_id(int *r_face_sets,
1903  SculptSession *ss,
1904  ExpandCache *expand_cache,
1905  Mesh *mesh,
1906  const int delete_id)
1907 {
1908  const int totface = ss->totfaces;
1909  MeshElemMap *pmap = ss->pmap;
1910 
1911  /* Check that all the face sets IDs in the mesh are not equal to `delete_id`
1912  * before attempting to delete it. */
1913  bool all_same_id = true;
1914  for (int i = 0; i < totface; i++) {
1915  if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, i)) {
1916  continue;
1917  }
1918  if (r_face_sets[i] != delete_id) {
1919  all_same_id = false;
1920  break;
1921  }
1922  }
1923  if (all_same_id) {
1924  return;
1925  }
1926 
1927  BLI_LINKSTACK_DECLARE(queue, void *);
1928  BLI_LINKSTACK_DECLARE(queue_next, void *);
1929 
1931  BLI_LINKSTACK_INIT(queue_next);
1932 
1933  for (int i = 0; i < totface; i++) {
1934  if (r_face_sets[i] == delete_id) {
1936  }
1937  }
1938 
1939  while (BLI_LINKSTACK_SIZE(queue)) {
1940  bool any_updated = false;
1941  while (BLI_LINKSTACK_SIZE(queue)) {
1942  const int f_index = POINTER_AS_INT(BLI_LINKSTACK_POP(queue));
1943  int other_id = delete_id;
1944  const MPoly *c_poly = &mesh->mpoly[f_index];
1945  for (int l = 0; l < c_poly->totloop; l++) {
1946  const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l];
1947  const MeshElemMap *vert_map = &pmap[c_loop->v];
1948  for (int i = 0; i < vert_map->count; i++) {
1949 
1950  const int neighbor_face_index = vert_map->indices[i];
1951  if (expand_cache->original_face_sets[neighbor_face_index] <= 0) {
1952  /* Skip picking IDs from hidden Face Sets. */
1953  continue;
1954  }
1955  if (r_face_sets[neighbor_face_index] != delete_id) {
1956  other_id = r_face_sets[neighbor_face_index];
1957  }
1958  }
1959  }
1960 
1961  if (other_id != delete_id) {
1962  any_updated = true;
1963  r_face_sets[f_index] = other_id;
1964  }
1965  else {
1966  BLI_LINKSTACK_PUSH(queue_next, POINTER_FROM_INT(f_index));
1967  }
1968  }
1969  if (!any_updated) {
1970  /* No Face Sets where updated in this iteration, which means that no more content to keep
1971  * filling the polys of the deleted Face Set was found. Break to avoid entering an infinite
1972  * loop trying to search for those polys again. */
1973  break;
1974  }
1975 
1976  BLI_LINKSTACK_SWAP(queue, queue_next);
1977  }
1978 
1980  BLI_LINKSTACK_FREE(queue_next);
1981 
1982  /* Ensure that the visibility state of the modified Face Sets is the same as the original ones.
1983  */
1984  for (int i = 0; i < totface; i++) {
1985  if (expand_cache->original_face_sets[i] >= 0) {
1986  r_face_sets[i] = abs(r_face_sets[i]);
1987  }
1988  else {
1989  r_face_sets[i] = -abs(r_face_sets[i]);
1990  }
1991  }
1992 }
1993 
1995  wmOperator *op,
1996  ExpandCache *expand_cache)
1997 {
1998  /* RNA properties. */
1999  expand_cache->invert = RNA_boolean_get(op->ptr, "invert");
2000  expand_cache->preserve = RNA_boolean_get(op->ptr, "use_mask_preserve");
2001  expand_cache->falloff_gradient = RNA_boolean_get(op->ptr, "use_falloff_gradient");
2002  expand_cache->target = RNA_enum_get(op->ptr, "target");
2003  expand_cache->modify_active_face_set = RNA_boolean_get(op->ptr, "use_modify_active");
2004  expand_cache->reposition_pivot = RNA_boolean_get(op->ptr, "use_reposition_pivot");
2005  expand_cache->max_geodesic_move_preview = RNA_int_get(op->ptr, "max_geodesic_move_preview");
2006 
2007  /* These can be exposed in RNA if needed. */
2008  expand_cache->loop_count = 1;
2009  expand_cache->brush_gradient = false;
2010 
2011  /* Texture and color data from the active Brush. */
2014  SculptSession *ss = ob->sculpt;
2015  expand_cache->brush = BKE_paint_brush(&sd->paint);
2016  BKE_curvemapping_init(expand_cache->brush->curve);
2017  copy_v4_fl(expand_cache->fill_color, 1.0f);
2018  copy_v3_v3(expand_cache->fill_color, BKE_brush_color_get(ss->scene, expand_cache->brush));
2020 
2021  expand_cache->scene = CTX_data_scene(C);
2022  expand_cache->mtex = &expand_cache->brush->mtex;
2023  expand_cache->texture_distortion_strength = 0.0f;
2024  expand_cache->blend_mode = expand_cache->brush->blend;
2025 }
2026 
2030 static void sculpt_expand_undo_push(Object *ob, ExpandCache *expand_cache)
2031 {
2032  SculptSession *ss = ob->sculpt;
2033  PBVHNode **nodes;
2034  int totnode;
2035  BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
2036 
2037  switch (expand_cache->target) {
2039  for (int i = 0; i < totnode; i++) {
2040  SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
2041  }
2042  break;
2045  break;
2047  for (int i = 0; i < totnode; i++) {
2049  }
2050  break;
2051  }
2052 
2053  MEM_freeN(nodes);
2054 }
2055 
2056 static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2057 {
2060  SculptSession *ss = ob->sculpt;
2062 
2063  /* Create and configure the Expand Cache. */
2064  ss->expand_cache = MEM_callocN(sizeof(ExpandCache), "expand cache");
2066 
2067  /* Update object. */
2068  const bool needs_colors = ss->expand_cache->target == SCULPT_EXPAND_TARGET_COLORS;
2069 
2070  if (needs_colors) {
2071  /* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the updates of
2072  * earlier steps modifying the data. */
2075  }
2076 
2077  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, needs_colors);
2078 
2079  /* Do nothing when the mesh has 0 vertices. */
2080  const int totvert = SCULPT_vertex_count_get(ss);
2081  if (totvert == 0) {
2083  return OPERATOR_CANCELLED;
2084  }
2085 
2086  /* Face Set operations are not supported in dyntopo. */
2088  BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
2090  return OPERATOR_CANCELLED;
2091  }
2092 
2094 
2095  /* Initialize undo. */
2096  SCULPT_undo_push_begin(ob, "expand");
2098 
2099  /* Set the initial element for expand from the event position. */
2100  const float mouse[2] = {event->mval[0], event->mval[1]};
2102 
2103  /* Cache PBVH nodes. */
2105  ss->pbvh, NULL, NULL, &ss->expand_cache->nodes, &ss->expand_cache->totnode);
2106 
2107  /* Store initial state. */
2109 
2112  ss,
2113  ss->expand_cache,
2114  ob->data,
2116  }
2117 
2118  /* Initialize the falloff. */
2119  eSculptExpandFalloffType falloff_type = RNA_enum_get(op->ptr, "falloff_type");
2120 
2121  /* When starting from a boundary vertex, set the initial falloff to boundary. */
2124  }
2125 
2127  ss->expand_cache, sd, ob, ss->expand_cache->initial_active_vertex, falloff_type);
2128 
2129  /* Initial mesh data update, resets all target data in the sculpt mesh. */
2131 
2133  return OPERATOR_RUNNING_MODAL;
2134 }
2135 
2137 {
2138  static const EnumPropertyItem modal_items[] = {
2139  {SCULPT_EXPAND_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
2140  {SCULPT_EXPAND_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
2141  {SCULPT_EXPAND_MODAL_INVERT, "INVERT", 0, "Invert", ""},
2142  {SCULPT_EXPAND_MODAL_PRESERVE_TOGGLE, "PRESERVE", 0, "Toggle Preserve State", ""},
2143  {SCULPT_EXPAND_MODAL_GRADIENT_TOGGLE, "GRADIENT", 0, "Toggle Gradient", ""},
2145  "RECURSION_STEP_GEODESIC",
2146  0,
2147  "Geodesic recursion step",
2148  ""},
2150  "RECURSION_STEP_TOPOLOGY",
2151  0,
2152  "Topology recursion Step",
2153  ""},
2154  {SCULPT_EXPAND_MODAL_MOVE_TOGGLE, "MOVE_TOGGLE", 0, "Move Origin", ""},
2155  {SCULPT_EXPAND_MODAL_FALLOFF_GEODESIC, "FALLOFF_GEODESICS", 0, "Geodesic Falloff", ""},
2156  {SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY, "FALLOFF_TOPOLOGY", 0, "Topology Falloff", ""},
2158  "FALLOFF_TOPOLOGY_DIAGONALS",
2159  0,
2160  "Diagonals Falloff",
2161  ""},
2162  {SCULPT_EXPAND_MODAL_FALLOFF_SPHERICAL, "FALLOFF_SPHERICAL", 0, "Spherical Falloff", ""},
2163  {SCULPT_EXPAND_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap expand to Face Sets", ""},
2165  "LOOP_COUNT_INCREASE",
2166  0,
2167  "Loop Count Increase",
2168  ""},
2170  "LOOP_COUNT_DECREASE",
2171  0,
2172  "Loop Count Decrease",
2173  ""},
2175  "BRUSH_GRADIENT_TOGGLE",
2176  0,
2177  "Toggle Brush Gradient",
2178  ""},
2180  "TEXTURE_DISTORTION_INCREASE",
2181  0,
2182  "Texture Distortion Increase",
2183  ""},
2185  "TEXTURE_DISTORTION_DECREASE",
2186  0,
2187  "Texture Distortion Decrease",
2188  ""},
2189  {0, NULL, 0, NULL, NULL},
2190  };
2191 
2192  static const char *name = "Sculpt Expand Modal";
2193  wmKeyMap *keymap = WM_modalkeymap_find(keyconf, name);
2194 
2195  /* This function is called for each spacetype, only needs to add map once. */
2196  if (keymap && keymap->modal_items) {
2197  return;
2198  }
2199 
2200  keymap = WM_modalkeymap_ensure(keyconf, name, modal_items);
2201  WM_modalkeymap_assign(keymap, "SCULPT_OT_expand");
2202 }
2203 
2205 {
2206  /* Identifiers. */
2207  ot->name = "Expand";
2208  ot->idname = "SCULPT_OT_expand";
2209  ot->description = "Generic sculpt expand operator";
2210 
2211  /* API callbacks. */
2216 
2218 
2219  static EnumPropertyItem prop_sculpt_expand_falloff_type_items[] = {
2220  {SCULPT_EXPAND_FALLOFF_GEODESIC, "GEODESIC", 0, "Geodesic", ""},
2221  {SCULPT_EXPAND_FALLOFF_TOPOLOGY, "TOPOLOGY", 0, "Topology", ""},
2223  "TOPOLOGY_DIAGONALS",
2224  0,
2225  "Topology Diagonals",
2226  ""},
2227  {SCULPT_EXPAND_FALLOFF_NORMALS, "NORMALS", 0, "Normals", ""},
2228  {SCULPT_EXPAND_FALLOFF_SPHERICAL, "SPHERICAL", 0, "Spherical", ""},
2229  {SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY, "BOUNDARY_TOPOLOGY", 0, "Boundary Topology", ""},
2230  {SCULPT_EXPAND_FALLOFF_BOUNDARY_FACE_SET, "BOUNDARY_FACE_SET", 0, "Boundary Face Set", ""},
2231  {SCULPT_EXPAND_FALLOFF_ACTIVE_FACE_SET, "ACTIVE_FACE_SET", 0, "Active Face Set", ""},
2232  {0, NULL, 0, NULL, NULL},
2233  };
2234 
2235  static EnumPropertyItem prop_sculpt_expand_target_type_items[] = {
2236  {SCULPT_EXPAND_TARGET_MASK, "MASK", 0, "Mask", ""},
2237  {SCULPT_EXPAND_TARGET_FACE_SETS, "FACE_SETS", 0, "Face Sets", ""},
2238  {SCULPT_EXPAND_TARGET_COLORS, "COLOR", 0, "Color", ""},
2239  {0, NULL, 0, NULL, NULL},
2240  };
2241 
2242  RNA_def_enum(ot->srna,
2243  "target",
2244  prop_sculpt_expand_target_type_items,
2246  "Data Target",
2247  "Data that is going to be modified in the expand operation");
2248 
2249  RNA_def_enum(ot->srna,
2250  "falloff_type",
2251  prop_sculpt_expand_falloff_type_items,
2253  "Falloff Type",
2254  "Initial falloff of the expand operation");
2255 
2256  ot->prop = RNA_def_boolean(
2257  ot->srna, "invert", false, "Invert", "Invert the expand active elements");
2259  "use_mask_preserve",
2260  false,
2261  "Preserve Previous",
2262  "Preserve the previous state of the target data");
2264  "use_falloff_gradient",
2265  false,
2266  "Falloff Gradient",
2267  "Expand Using a linear falloff");
2268 
2270  "use_modify_active",
2271  false,
2272  "Modify Active",
2273  "Modify the active Face Set instead of creating a new one");
2274 
2275  ot->prop = RNA_def_boolean(
2276  ot->srna,
2277  "use_reposition_pivot",
2278  true,
2279  "Reposition Pivot",
2280  "Reposition the sculpt transform pivot to the boundary of the expand active area");
2281 
2282  ot->prop = RNA_def_int(ot->srna,
2283  "max_geodesic_move_preview",
2284  10000,
2285  0,
2286  INT_MAX,
2287  "Max Vertex Count for Geodesic Move Preview",
2288  "Maximum number of vertices in the mesh for using geodesic falloff when "
2289  "moving the origin of expand. If the total number of vertices is greater "
2290  "than this value, the falloff will be set to spherical when moving",
2291  0,
2292  1000000);
2293 }
const float * BKE_brush_color_get(const struct Scene *scene, const struct Brush *brush)
Definition: brush.c:2210
float BKE_brush_curve_strength(const struct Brush *br, float p, const float len)
float BKE_brush_sample_tex_3d(const struct Scene *scene, const struct Brush *br, const float point[3], float rgba[4], const int thread, struct ImagePool *pool)
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1200
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1401
struct ToolSettings * CTX_data_tool_settings(const bContext *C)
Definition: context.c:1208
struct ImagePool * BKE_image_pool_new(void)
Definition: image.c:5173
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 need_colors)
Definition: paint.c:1817
struct Brush * BKE_paint_brush(struct Paint *paint)
Definition: paint.c:604
#define SCULPT_FACE_SET_NONE
Definition: BKE_paint.h:230
void BKE_sculpt_color_layer_create_if_needed(struct Object *object)
Definition: paint.c:1800
A BVH for high poly meshes.
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode)
Definition: BKE_pbvh.h:384
#define PBVH_ITER_ALL
Definition: BKE_pbvh.h:334
void BKE_pbvh_node_mark_update_color(PBVHNode *node)
Definition: pbvh.c:1743
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1661
#define BKE_pbvh_vertex_iter_end
Definition: BKE_pbvh.h:457
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:335
const struct CCGKey * BKE_pbvh_get_grid_key(const PBVH *pbvh)
Definition: pbvh.c:1694
@ PBVH_GRIDS
Definition: BKE_pbvh.h:211
@ PBVH_BMESH
Definition: BKE_pbvh.h:212
@ PBVH_FACES
Definition: BKE_pbvh.h:210
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode)
Definition: pbvh.c:3042
void BKE_pbvh_node_mark_update_mask(PBVHNode *node)
Definition: pbvh.c:1738
void BKE_pbvh_node_mark_redraw(PBVHNode *node)
Definition: pbvh.c:1759
void BKE_pbvh_search_gather(PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot)
Definition: pbvh.c:843
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int grid_index)
Definition: subdiv_ccg.c:1832
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:63
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
#define BLI_BITMAP_SET(_bitmap, _index, _set)
Definition: BLI_bitmap.h:93
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
struct GSet GSet
Definition: BLI_ghash.h:189
GSet * BLI_gset_int_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
bool BLI_gset_haskey(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1216
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1253
bool BLI_gset_add(GSet *gs, void *key)
Definition: BLI_ghash.c:1160
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1211
void BLI_gsqueue_free(GSQueue *queue)
Definition: gsqueue.c:107
void BLI_gsqueue_push(GSQueue *queue, const void *item)
Definition: gsqueue.c:122
GSQueue * BLI_gsqueue_new(const size_t elem_size)
Definition: gsqueue.c:83
void BLI_gsqueue_pop(GSQueue *queue, void *r_item)
Definition: gsqueue.c:162
bool BLI_gsqueue_is_empty(const GSQueue *queue)
Definition: gsqueue.c:193
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 void mul_v4_v4fl(float r[3], const float a[4], float f)
MINLINE void copy_v4_v4(float r[4], const float a[4])
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 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(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
#define POINTER_FROM_INT(i)
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
@ ME_VERT_PBVH_UPDATE
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:840
int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh)
void IMB_colormanagement_srgb_to_scene_linear_v3(float pixel[3])
void IMB_blend_color_float(float dst[4], const float src1[4], const float src2[4], IMB_BlendMode mode)
Definition: rectop.c:129
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Group RGB to Bright Vector Camera CLAMP
#define C
Definition: RandGen.cpp:39
#define NC_GEOM
Definition: WM_types.h:294
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_SELECT
Definition: WM_types.h:407
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
OperationNode * node
const Depsgraph * depsgraph
bool enabled
#define powf(x, y)
#define fabsf(x)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:46
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
ThreadQueue * queue
all scheduled work for the cpu
void flip_v3_v3(float out[3], const float in[3], const enum ePaintSymmetryFlags symm)
Definition: paint_utils.c:407
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
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:3585
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:3771
const float * SCULPT_vertex_co_get(SculptSession *ss, int index)
Definition: sculpt.c:134
int SCULPT_vertex_count_get(SculptSession *ss)
Definition: sculpt.c:120
void SCULPT_floodfill_add_and_skip_initial(SculptFloodFill *flood, int index)
Definition: sculpt.c:1099
void SCULPT_floodfill_add_initial_with_symmetry(Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, int index, float radius)
Definition: sculpt.c:1105
void SCULPT_boundary_info_ensure(Object *object)
Definition: sculpt.c:9039
int SCULPT_active_vertex_get(SculptSession *ss)
Definition: sculpt.c:277
int SCULPT_nearest_vertex_get(Sculpt *sd, Object *ob, const float co[3], float max_distance, bool use_original)
Definition: sculpt.c:1000
bool SCULPT_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mouse[2], bool use_sampled_normal)
Definition: sculpt.c:7452
void SCULPT_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
Definition: sculpt.c:1085
bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set)
Definition: sculpt.c:539
bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index)
Definition: sculpt.c:669
bool SCULPT_is_symmetry_iteration_valid(char i, char symm)
Definition: sculpt.c:1042
void SCULPT_connected_components_ensure(Object *ob)
Definition: sculpt.c:9007
void SCULPT_vertex_random_access_ensure(SculptSession *ss)
Definition: sculpt.c:112
void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags)
Definition: sculpt.c:7819
bool SCULPT_vertex_visible_get(SculptSession *ss, int index)
Definition: sculpt.c:362
void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
Definition: sculpt.c:7759
void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
Definition: sculpt.c:172
bool SCULPT_vertex_is_boundary(const SculptSession *ss, const int index)
Definition: sculpt.c:868
void SCULPT_floodfill_free(SculptFloodFill *flood)
Definition: sculpt.c:1188
bool SCULPT_mode_poll(bContext *C)
Definition: sculpt.c:6601
const float * SCULPT_vertex_color_get(SculptSession *ss, int index)
Definition: sculpt.c:157
int SCULPT_vertex_face_set_get(SculptSession *ss, int index)
Definition: sculpt.c:514
float SCULPT_vertex_mask_get(SculptSession *ss, int index)
Definition: sculpt.c:254
char SCULPT_mesh_symmetry_xyz_get(Object *object)
Definition: sculpt.c:323
bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm)
Definition: sculpt.c:940
int SCULPT_active_face_set_get(SculptSession *ss)
Definition: sculpt.c:331
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:1157
void SCULPT_tag_update_overlays(bContext *C)
Definition: sculpt.c:1066
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
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
static void sculpt_expand_update_max_face_falloff_factor(SculptSession *ss, ExpandCache *expand_cache)
static void sculpt_expand_cache_free(SculptSession *ss)
static int sculpt_expand_target_vertex_update_and_get(bContext *C, Object *ob, const float mouse[2])
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)
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_set_initial_components_for_mouse(bContext *C, Object *ob, ExpandCache *expand_cache, const float mouse[2])
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)
#define EXPAND_ACTIVE_COMPONENT_NONE
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)
@ 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_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)
#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:1383
#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:61
@ SCULPT_UPDATE_MASK
Definition: sculpt_intern.h:59
#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator)
void SCULPT_undo_push_end(void)
Definition: sculpt_undo.c:1400
SculptUndoNode * SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type)
Definition: sculpt_undo.c:1292
#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:48
int grid_area
Definition: BKE_ccg.h:58
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
float texture_distortion_strength
int initial_active_face_set
bool reposition_pivot
eSculptExpandTargetType target
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
struct MVert * mvert
Definition: BKE_pbvh.h:372
float * col
Definition: BKE_pbvh.h:378
float * mask
Definition: BKE_pbvh.h:377
int * vertices
Definition: BKE_paint.h:380
struct SubdivCCG * subdiv_ccg
Definition: BKE_paint.h:501
struct ImagePool * tex_pool
Definition: BKE_paint.h:516
SculptVertexInfo vertex_info
Definition: BKE_paint.h:563
int * face_sets
Definition: BKE_paint.h:490
float pivot_pos[3]
Definition: BKE_paint.h:567
int active_face_index
Definition: BKE_paint.h:525
struct Scene * scene
Definition: BKE_paint.h:546
struct MeshElemMap * pmap
Definition: BKE_paint.h:474
struct MLoop * mloop
Definition: BKE_paint.h:463
struct MPoly * mpoly
Definition: BKE_paint.h:462
struct ExpandCache * expand_cache
Definition: BKE_paint.h:520
int active_grid_index
Definition: BKE_paint.h:526
struct PBVH * pbvh
Definition: BKE_paint.h:504
int * connected_component
Definition: BKE_paint.h:355
Paint paint
short val
Definition: WM_types.h:579
short type
Definition: WM_types.h:577
const void * modal_items
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: svm_noise.h:37
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
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:3156
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