Blender  V3.3
sculpt_face_set.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_blenlib.h"
11 #include "BLI_hash.h"
12 #include "BLI_math.h"
13 #include "BLI_task.h"
14 
15 #include "DNA_brush_types.h"
16 #include "DNA_customdata_types.h"
17 #include "DNA_mesh_types.h"
18 #include "DNA_meshdata_types.h"
19 #include "DNA_object_types.h"
20 #include "DNA_scene_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_customdata.h"
27 #include "BKE_mesh.h"
28 #include "BKE_mesh_fair.h"
29 #include "BKE_mesh_mapping.h"
30 #include "BKE_multires.h"
31 #include "BKE_node.h"
32 #include "BKE_object.h"
33 #include "BKE_paint.h"
34 #include "BKE_pbvh.h"
35 #include "BKE_scene.h"
36 
37 #include "DEG_depsgraph.h"
38 
39 #include "WM_api.h"
40 #include "WM_message.h"
41 #include "WM_toolsystem.h"
42 #include "WM_types.h"
43 
44 #include "ED_object.h"
45 #include "ED_screen.h"
46 #include "ED_sculpt.h"
47 #include "ED_view3d.h"
48 #include "paint_intern.h"
49 #include "sculpt_intern.h"
50 
51 #include "RNA_access.h"
52 #include "RNA_define.h"
53 
54 #include "bmesh.h"
55 
56 #include <math.h>
57 #include <stdlib.h>
58 
59 /* Utils. */
60 
62 {
63  const int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
64  if (!face_sets) {
65  return SCULPT_FACE_SET_NONE;
66  }
67 
68  int next_face_set_id = 0;
69  for (int i = 0; i < mesh->totpoly; i++) {
70  next_face_set_id = max_ii(next_face_set_id, abs(face_sets[i]));
71  }
72  next_face_set_id++;
73 
74  return next_face_set_id;
75 }
76 
77 void ED_sculpt_face_sets_initialize_none_to_id(struct Mesh *mesh, const int new_id)
78 {
80  if (!face_sets) {
81  return;
82  }
83 
84  for (int i = 0; i < mesh->totpoly; i++) {
85  if (face_sets[i] == SCULPT_FACE_SET_NONE) {
86  face_sets[i] = new_id;
87  }
88  }
89 }
90 
92 {
93  SculptSession *ss = ob->sculpt;
94  if (!ss) {
95  return SCULPT_FACE_SET_NONE;
96  }
97 
99  if (!SCULPT_cursor_geometry_info_update(C, &gi, mval, false)) {
100  return SCULPT_FACE_SET_NONE;
101  }
102 
103  return SCULPT_active_face_set_get(ss);
104 }
105 
106 /* Draw Face Sets Brush. */
107 
108 static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
109  const int n,
110  const TaskParallelTLS *__restrict tls)
111 {
112  SculptThreadedTaskData *data = userdata;
113  SculptSession *ss = data->ob->sculpt;
114  const Brush *brush = data->brush;
115  const float bstrength = ss->cache->bstrength;
116 
117  PBVHVertexIter vd;
118 
119  SculptBrushTest test;
121  ss, &test, data->brush->falloff_shape);
122  const int thread_id = BLI_task_parallel_thread_id(tls);
123 
125 
126  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
127  if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
128  MeshElemMap *vert_map = &ss->pmap[vd.index];
129  for (int j = 0; j < ss->pmap[vd.index].count; j++) {
130  const MPoly *p = &ss->mpoly[vert_map->indices[j]];
131 
132  float poly_center[3];
133  BKE_mesh_calc_poly_center(p, &ss->mloop[p->loopstart], mvert, poly_center);
134 
135  if (!sculpt_brush_test_sq_fn(&test, poly_center)) {
136  continue;
137  }
138  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
139  brush,
140  vd.co,
141  sqrtf(test.dist),
142  vd.no,
143  vd.fno,
144  vd.mask ? *vd.mask : 0.0f,
145  vd.index,
146  thread_id);
147 
148  if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) {
149  ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set);
150  }
151  }
152  }
153  else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
154  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
155  continue;
156  }
157  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
158  brush,
159  vd.co,
160  sqrtf(test.dist),
161  vd.no,
162  vd.fno,
163  vd.mask ? *vd.mask : 0.0f,
164  vd.index,
165  thread_id);
166 
167  if (fade > 0.05f) {
169  }
170  }
171  }
173 }
174 
175 static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
176  const int n,
177  const TaskParallelTLS *__restrict tls)
178 {
179  SculptThreadedTaskData *data = userdata;
180  SculptSession *ss = data->ob->sculpt;
181  const Brush *brush = data->brush;
182  float bstrength = ss->cache->bstrength;
183 
184  PBVHVertexIter vd;
185 
186  SculptBrushTest test;
188  ss, &test, data->brush->falloff_shape);
189 
190  const bool relax_face_sets = !(ss->cache->iteration_count % 3 == 0);
191  /* This operations needs a strength tweak as the relax deformation is too weak by default. */
192  if (relax_face_sets) {
193  bstrength *= 2.0f;
194  }
195 
196  const int thread_id = BLI_task_parallel_thread_id(tls);
197 
198  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
199  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
200  continue;
201  }
202  if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
203  continue;
204  }
205 
206  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
207  brush,
208  vd.co,
209  sqrtf(test.dist),
210  vd.no,
211  vd.fno,
212  vd.mask ? *vd.mask : 0.0f,
213  vd.index,
214  thread_id);
215 
216  SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co);
217  if (vd.mvert) {
219  }
220  }
222 }
223 
224 void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
225 {
226  SculptSession *ss = ob->sculpt;
227  Brush *brush = BKE_paint_brush(&sd->paint);
228 
230 
231  /* Threaded loop over nodes. */
233  .sd = sd,
234  .ob = ob,
235  .brush = brush,
236  .nodes = nodes,
237  };
238 
239  TaskParallelSettings settings;
240  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
241  if (ss->cache->alt_smooth) {
243  for (int i = 0; i < 4; i++) {
245  }
246  }
247  else {
249  }
250 }
251 
252 /* Face Sets Operators */
253 
260 
262  {
264  "MASKED",
265  0,
266  "Face Set from Masked",
267  "Create a new Face Set from the masked faces",
268  },
269  {
271  "VISIBLE",
272  0,
273  "Face Set from Visible",
274  "Create a new Face Set from the visible vertices",
275  },
276  {
278  "ALL",
279  0,
280  "Face Set Full Mesh",
281  "Create an unique Face Set with all faces in the sculpt",
282  },
283  {
285  "SELECTION",
286  0,
287  "Face Set from Edit Mode Selection",
288  "Create an Face Set corresponding to the Edit Mode face selection",
289  },
290  {0, NULL, 0, NULL, NULL},
291 };
292 
294 {
296  SculptSession *ss = ob->sculpt;
298 
299  const int mode = RNA_enum_get(op->ptr, "mode");
300 
301  /* Dyntopo not supported. */
302  if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
303  return OPERATOR_CANCELLED;
304  }
305 
307 
308  const int tot_vert = SCULPT_vertex_count_get(ss);
309  float threshold = 0.5f;
310 
311  PBVH *pbvh = ob->sculpt->pbvh;
312  PBVHNode **nodes;
313  int totnode;
314  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
315 
316  if (!nodes) {
317  return OPERATOR_CANCELLED;
318  }
319 
320  SCULPT_undo_push_begin(ob, "face set change");
322 
323  const int next_face_set = SCULPT_face_set_next_available_get(ss);
324 
325  if (mode == SCULPT_FACE_SET_MASKED) {
326  for (int i = 0; i < tot_vert; i++) {
328  SCULPT_vertex_face_set_set(ss, i, next_face_set);
329  }
330  }
331  }
332 
333  if (mode == SCULPT_FACE_SET_VISIBLE) {
334 
335  /* If all vertices in the sculpt are visible, create the new face set and update the default
336  * color. This way the new face set will be white, which is a quick way of disabling all face
337  * sets and the performance hit of rendering the overlay. */
338  bool all_visible = true;
339  for (int i = 0; i < tot_vert; i++) {
340  if (!SCULPT_vertex_visible_get(ss, i)) {
341  all_visible = false;
342  break;
343  }
344  }
345 
346  if (all_visible) {
347  Mesh *mesh = ob->data;
348  mesh->face_sets_color_default = next_face_set;
351  }
352 
353  for (int i = 0; i < tot_vert; i++) {
354  if (SCULPT_vertex_visible_get(ss, i)) {
355  SCULPT_vertex_face_set_set(ss, i, next_face_set);
356  }
357  }
358  }
359 
360  if (mode == SCULPT_FACE_SET_ALL) {
361  for (int i = 0; i < tot_vert; i++) {
362  SCULPT_vertex_face_set_set(ss, i, next_face_set);
363  }
364  }
365 
366  if (mode == SCULPT_FACE_SET_SELECTION) {
367  Mesh *mesh = ob->data;
368  BMesh *bm;
369  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
370  bm = BM_mesh_create(&allocsize,
371  &((struct BMeshCreateParams){
372  .use_toolflags = true,
373  }));
374 
376  mesh,
377  (&(struct BMeshFromMeshParams){
378  .calc_face_normal = true,
379  .calc_vert_normal = true,
380  }));
381 
382  BMIter iter;
383  BMFace *f;
384  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
386  ss->face_sets[BM_elem_index_get(f)] = next_face_set;
387  }
388  }
389  BM_mesh_free(bm);
390  }
391 
392  for (int i = 0; i < totnode; i++) {
393  BKE_pbvh_node_mark_redraw(nodes[i]);
394  }
395 
396  MEM_SAFE_FREE(nodes);
397 
399 
401 
402  return OPERATOR_FINISHED;
403 }
404 
406 {
407  /* identifiers */
408  ot->name = "Create Face Set";
409  ot->idname = "SCULPT_OT_face_sets_create";
410  ot->description = "Create a new Face Set";
411 
412  /* api callbacks */
415 
417 
418  RNA_def_enum(
420 }
421 
433 
435  {
437  "LOOSE_PARTS",
438  0,
439  "Face Sets from Loose Parts",
440  "Create a Face Set per loose part in the mesh",
441  },
442  {
444  "MATERIALS",
445  0,
446  "Face Sets from Material Slots",
447  "Create a Face Set per Material Slot",
448  },
449  {
451  "NORMALS",
452  0,
453  "Face Sets from Mesh Normals",
454  "Create Face Sets for Faces that have similar normal",
455  },
456  {
458  "UV_SEAMS",
459  0,
460  "Face Sets from UV Seams",
461  "Create Face Sets using UV Seams as boundaries",
462  },
463  {
465  "CREASES",
466  0,
467  "Face Sets from Edge Creases",
468  "Create Face Sets using Edge Creases as boundaries",
469  },
470  {
472  "BEVEL_WEIGHT",
473  0,
474  "Face Sets from Bevel Weight",
475  "Create Face Sets using Bevel Weights as boundaries",
476  },
477  {
479  "SHARP_EDGES",
480  0,
481  "Face Sets from Sharp Edges",
482  "Create Face Sets using Sharp Edges as boundaries",
483  },
484  {
486  "FACE_MAPS",
487  0,
488  "Face Sets from Face Maps",
489  "Create a Face Set per Face Map",
490  },
491  {
493  "FACE_SET_BOUNDARIES",
494  0,
495  "Face Sets from Face Set Boundaries",
496  "Create a Face Set per isolated Face Set",
497  },
498 
499  {0, NULL, 0, NULL, NULL},
500 };
501 
503  BMesh *bm, BMFace *from_f, BMEdge *from_e, BMFace *to_f, const float threshold);
504 
506  BMFace *UNUSED(from_f),
507  BMEdge *UNUSED(from_e),
508  BMFace *UNUSED(to_f),
509  const float UNUSED(threshold))
510 {
511  return true;
512 }
513 
515  BMesh *UNUSED(bm), BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float threshold)
516 {
517  return fabsf(dot_v3v3(from_f->no, to_f->no)) > threshold;
518 }
519 
521  BMFace *UNUSED(from_f),
522  BMEdge *from_e,
523  BMFace *UNUSED(to_f),
524  const float UNUSED(threshold))
525 {
526  return !BM_elem_flag_test(from_e, BM_ELEM_SEAM);
527 }
528 
530  BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
531 {
532  return BM_elem_float_data_get(&bm->edata, from_e, CD_CREASE) < threshold;
533 }
534 
536  BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
537 {
538  return BM_elem_float_data_get(&bm->edata, from_e, CD_BWEIGHT) < threshold;
539 }
540 
542  BMFace *UNUSED(from_f),
543  BMEdge *from_e,
544  BMFace *UNUSED(to_f),
545  const float UNUSED(threshold))
546 {
547  return BM_elem_flag_test(from_e, BM_ELEM_SMOOTH);
548 }
549 
551  BMesh *bm, BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float UNUSED(threshold))
552 {
553  const int cd_face_sets_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
554  return BM_ELEM_CD_GET_INT(from_f, cd_face_sets_offset) ==
555  BM_ELEM_CD_GET_INT(to_f, cd_face_sets_offset);
556 }
557 
560  const float threshold)
561 {
562  SculptSession *ss = ob->sculpt;
563  Mesh *mesh = ob->data;
564  BMesh *bm;
565  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
566  bm = BM_mesh_create(&allocsize,
567  &((struct BMeshCreateParams){
568  .use_toolflags = true,
569  }));
570 
572  mesh,
573  (&(struct BMeshFromMeshParams){
574  .calc_face_normal = true,
575  .calc_vert_normal = true,
576  }));
577 
578  BLI_bitmap *visited_faces = BLI_BITMAP_NEW(mesh->totpoly, "visited faces");
579  const int totfaces = mesh->totpoly;
580 
581  int *face_sets = ss->face_sets;
582 
585 
586  int next_face_set = 1;
587 
588  for (int i = 0; i < totfaces; i++) {
589  if (BLI_BITMAP_TEST(visited_faces, i)) {
590  continue;
591  }
592  GSQueue *queue;
593  queue = BLI_gsqueue_new(sizeof(int));
594 
595  face_sets[i] = next_face_set;
596  BLI_BITMAP_ENABLE(visited_faces, i);
597  BLI_gsqueue_push(queue, &i);
598 
599  while (!BLI_gsqueue_is_empty(queue)) {
600  int from_f;
601  BLI_gsqueue_pop(queue, &from_f);
602 
603  BMFace *f, *f_neighbor;
604  BMEdge *ed;
605  BMIter iter_a, iter_b;
606 
607  f = BM_face_at_index(bm, from_f);
608 
609  BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) {
610  BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) {
611  if (f_neighbor == f) {
612  continue;
613  }
614  int neighbor_face_index = BM_elem_index_get(f_neighbor);
615  if (BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) {
616  continue;
617  }
618  if (!test(bm, f, ed, f_neighbor, threshold)) {
619  continue;
620  }
621 
622  face_sets[neighbor_face_index] = next_face_set;
623  BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index);
624  BLI_gsqueue_push(queue, &neighbor_face_index);
625  }
626  }
627  }
628 
629  next_face_set += 1;
630 
632  }
633 
634  MEM_SAFE_FREE(visited_faces);
635 
636  BM_mesh_free(bm);
637 }
638 
639 static void sculpt_face_sets_init_loop(Object *ob, const int mode)
640 {
641  Mesh *mesh = ob->data;
642  SculptSession *ss = ob->sculpt;
643  BMesh *bm;
644  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
645  bm = BM_mesh_create(&allocsize,
646  &((struct BMeshCreateParams){
647  .use_toolflags = true,
648  }));
649 
651  mesh,
652  (&(struct BMeshFromMeshParams){
653  .calc_face_normal = true,
654  .calc_vert_normal = true,
655  }));
656  BMIter iter;
657  BMFace *f;
658 
659  const int cd_fmaps_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
660 
661  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
662  if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) {
663  ss->face_sets[BM_elem_index_get(f)] = (int)(f->mat_nr + 1);
664  }
665  else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) {
666  if (cd_fmaps_offset != -1) {
667  ss->face_sets[BM_elem_index_get(f)] = BM_ELEM_CD_GET_INT(f, cd_fmaps_offset) + 2;
668  }
669  else {
670  ss->face_sets[BM_elem_index_get(f)] = 1;
671  }
672  }
673  }
674  BM_mesh_free(bm);
675 }
676 
678 {
680  SculptSession *ss = ob->sculpt;
682 
683  const int mode = RNA_enum_get(op->ptr, "mode");
684 
685  /* Dyntopo not supported. */
686  if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
687  return OPERATOR_CANCELLED;
688  }
689 
690  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
691 
692  PBVH *pbvh = ob->sculpt->pbvh;
693  PBVHNode **nodes;
694  int totnode;
695  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
696 
697  if (!nodes) {
698  return OPERATOR_CANCELLED;
699  }
700 
701  SCULPT_undo_push_begin(ob, "face set change");
703 
704  const float threshold = RNA_float_get(op->ptr, "threshold");
705 
706  switch (mode) {
709  break;
712  break;
715  break;
718  break;
721  break;
724  break;
727  break;
731  break;
734  break;
735  }
736 
738 
739  /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
741 
742  for (int i = 0; i < totnode; i++) {
744  }
745 
747 
748  MEM_SAFE_FREE(nodes);
749 
750  if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
752  }
753 
755 
756  return OPERATOR_FINISHED;
757 }
758 
760 {
761  /* identifiers */
762  ot->name = "Init Face Sets";
763  ot->idname = "SCULPT_OT_face_sets_init";
764  ot->description = "Initializes all Face Sets in the mesh";
765 
766  /* api callbacks */
769 
771 
772  RNA_def_enum(
775  ot->srna,
776  "threshold",
777  0.5f,
778  0.0f,
779  1.0f,
780  "Threshold",
781  "Minimum value to consider a certain attribute a boundary when creating the Face Sets",
782  0.0f,
783  1.0f);
784 }
785 
793 
795  {
797  "TOGGLE",
798  0,
799  "Toggle Visibility",
800  "Hide all Face Sets except for the active one",
801  },
802  {
804  "SHOW_ACTIVE",
805  0,
806  "Show Active Face Set",
807  "Show Active Face Set",
808  },
809  {
811  "HIDE_ACTIVE",
812  0,
813  "Hide Active Face Sets",
814  "Hide Active Face Sets",
815  },
816  {
818  "INVERT",
819  0,
820  "Invert Face Set Visibility",
821  "Invert Face Set Visibility",
822  },
823  {
825  "SHOW_ALL",
826  0,
827  "Show All Face Sets",
828  "Show All Face Sets",
829  },
830  {0, NULL, 0, NULL, NULL},
831 };
832 
834 {
836  SculptSession *ss = ob->sculpt;
838 
839  /* Dyntopo not supported. */
840  if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
841  return OPERATOR_CANCELLED;
842  }
843 
844  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
845 
846  const int tot_vert = SCULPT_vertex_count_get(ss);
847  const int mode = RNA_enum_get(op->ptr, "mode");
848  const int active_face_set = SCULPT_active_face_set_get(ss);
849 
850  SCULPT_undo_push_begin(ob, "Hide area");
851 
852  PBVH *pbvh = ob->sculpt->pbvh;
853  PBVHNode **nodes;
854  int totnode;
855 
856  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
857 
858  if (totnode == 0) {
859  MEM_SAFE_FREE(nodes);
860  return OPERATOR_CANCELLED;
861  }
862 
864 
865  if (mode == SCULPT_FACE_SET_VISIBILITY_TOGGLE) {
866  bool hidden_vertex = false;
867 
868  /* This can fail with regular meshes with non-manifold geometry as the visibility state can't
869  * be synced from face sets to non-manifold vertices. */
870  if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
871  for (int i = 0; i < tot_vert; i++) {
872  if (!SCULPT_vertex_visible_get(ss, i)) {
873  hidden_vertex = true;
874  break;
875  }
876  }
877  }
878 
879  for (int i = 0; i < ss->totfaces; i++) {
880  if (ss->face_sets[i] <= 0) {
881  hidden_vertex = true;
882  break;
883  }
884  }
885 
886  if (hidden_vertex) {
888  }
889  else {
891  SCULPT_face_set_visibility_set(ss, active_face_set, true);
892  }
893  }
894 
897  }
898 
901  SCULPT_face_set_visibility_set(ss, active_face_set, true);
902  }
903 
905  SCULPT_face_set_visibility_set(ss, active_face_set, false);
906  }
907 
908  if (mode == SCULPT_FACE_SET_VISIBILITY_INVERT) {
910  }
911 
912  /* For modes that use the cursor active vertex, update the rotation origin for viewport
913  * navigation. */
916  float location[3];
918  mul_m4_v3(ob->obmat, location);
919  copy_v3_v3(ups->average_stroke_accum, location);
920  ups->average_stroke_counter = 1;
921  ups->last_stroke_valid = true;
922  }
923 
924  /* Sync face sets visibility and vertex visibility. */
926 
928 
929  for (int i = 0; i < totnode; i++) {
931  }
932 
934 
935  MEM_SAFE_FREE(nodes);
936 
938 
939  return OPERATOR_FINISHED;
940 }
941 
943  wmOperator *op,
944  const wmEvent *event)
945 {
947  SculptSession *ss = ob->sculpt;
948 
949  /* Update the active vertex and Face Set using the cursor position to avoid relying on the paint
950  * cursor updates. */
952  const float mval_fl[2] = {UNPACK2(event->mval)};
954  SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
955 
957 }
958 
960 {
961  /* Identifiers. */
962  ot->name = "Face Sets Visibility";
963  ot->idname = "SCULPT_OT_face_set_change_visibility";
964  ot->description = "Change the visibility of the Face Sets of the sculpt";
965 
966  /* Api callbacks. */
970 
972 
974  "mode",
977  "Mode",
978  "");
979 }
980 
982 {
983 
985  SculptSession *ss = ob->sculpt;
986 
987  /* Dyntopo not supported. */
988  if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
989  return OPERATOR_CANCELLED;
990  }
991 
992  PBVH *pbvh = ob->sculpt->pbvh;
993  PBVHNode **nodes;
994  int totnode;
995  Mesh *mesh = ob->data;
996 
998  if (ss->face_sets) {
999  const int random_index = clamp_i(ss->totfaces * BLI_hash_int_01(mesh->face_sets_color_seed),
1000  0,
1001  max_ii(0, ss->totfaces - 1));
1002  mesh->face_sets_color_default = ss->face_sets[random_index];
1003  }
1005 
1006  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
1007  for (int i = 0; i < totnode; i++) {
1008  BKE_pbvh_node_mark_redraw(nodes[i]);
1009  }
1010 
1011  MEM_SAFE_FREE(nodes);
1012 
1014 
1015  return OPERATOR_FINISHED;
1016 }
1017 
1019 {
1020  /* Identifiers. */
1021  ot->name = "Randomize Face Sets Colors";
1022  ot->idname = "SCULPT_OT_face_sets_randomize_colors";
1023  ot->description = "Generates a new set of random colors to render the Face Sets in the viewport";
1024 
1025  /* Api callbacks. */
1028 
1030 }
1031 
1039 
1041  {
1043  "GROW",
1044  0,
1045  "Grow Face Set",
1046  "Grows the Face Sets boundary by one face based on mesh topology",
1047  },
1048  {
1050  "SHRINK",
1051  0,
1052  "Shrink Face Set",
1053  "Shrinks the Face Sets boundary by one face based on mesh topology",
1054  },
1055  {
1057  "DELETE_GEOMETRY",
1058  0,
1059  "Delete Geometry",
1060  "Deletes the faces that are assigned to the Face Set",
1061  },
1062  {
1064  "FAIR_POSITIONS",
1065  0,
1066  "Fair Positions",
1067  "Creates a smooth as possible geometry patch from the Face Set minimizing changes in "
1068  "vertex positions",
1069  },
1070  {
1072  "FAIR_TANGENCY",
1073  0,
1074  "Fair Tangency",
1075  "Creates a smooth as possible geometry patch from the Face Set minimizing changes in "
1076  "vertex tangents",
1077  },
1078  {0, NULL, 0, NULL, NULL},
1079 };
1080 
1082  SculptSession *ss,
1083  const int *prev_face_sets,
1084  const int active_face_set_id,
1085  const bool modify_hidden)
1086 {
1088  for (int p = 0; p < mesh->totpoly; p++) {
1089  if (!modify_hidden && prev_face_sets[p] <= 0) {
1090  continue;
1091  }
1092  const MPoly *c_poly = &mesh->mpoly[p];
1093  for (int l = 0; l < c_poly->totloop; l++) {
1094  const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l];
1095  const MeshElemMap *vert_map = &ss->pmap[c_loop->v];
1096  for (int i = 0; i < vert_map->count; i++) {
1097  const int neighbor_face_index = vert_map->indices[i];
1098  if (neighbor_face_index == p) {
1099  continue;
1100  }
1101  if (abs(prev_face_sets[neighbor_face_index]) == active_face_set_id) {
1102  ss->face_sets[p] = active_face_set_id;
1103  }
1104  }
1105  }
1106  }
1107 }
1108 
1110  SculptSession *ss,
1111  const int *prev_face_sets,
1112  const int active_face_set_id,
1113  const bool modify_hidden)
1114 {
1116  for (int p = 0; p < mesh->totpoly; p++) {
1117  if (!modify_hidden && prev_face_sets[p] <= 0) {
1118  continue;
1119  }
1120  if (abs(prev_face_sets[p]) == active_face_set_id) {
1121  const MPoly *c_poly = &mesh->mpoly[p];
1122  for (int l = 0; l < c_poly->totloop; l++) {
1123  const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l];
1124  const MeshElemMap *vert_map = &ss->pmap[c_loop->v];
1125  for (int i = 0; i < vert_map->count; i++) {
1126  const int neighbor_face_index = vert_map->indices[i];
1127  if (neighbor_face_index == p) {
1128  continue;
1129  }
1130  if (abs(prev_face_sets[neighbor_face_index]) != active_face_set_id) {
1131  ss->face_sets[p] = prev_face_sets[neighbor_face_index];
1132  }
1133  }
1134  }
1135  }
1136  }
1137 }
1138 
1139 static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool check_visible_only)
1140 {
1141 
1142  int first_face_set = SCULPT_FACE_SET_NONE;
1143  if (check_visible_only) {
1144  for (int f = 0; f < ss->totfaces; f++) {
1145  if (face_sets[f] > 0) {
1146  first_face_set = face_sets[f];
1147  break;
1148  }
1149  }
1150  }
1151  else {
1152  first_face_set = abs(face_sets[0]);
1153  }
1154 
1155  if (first_face_set == SCULPT_FACE_SET_NONE) {
1156  return true;
1157  }
1158 
1159  for (int f = 0; f < ss->totfaces; f++) {
1160  const int face_set_id = check_visible_only ? face_sets[f] : abs(face_sets[f]);
1161  if (face_set_id != first_face_set) {
1162  return false;
1163  }
1164  }
1165  return true;
1166 }
1167 
1169  SculptSession *ss,
1170  const int active_face_set_id,
1171  const bool modify_hidden)
1172 {
1173 
1174  Mesh *mesh = ob->data;
1175  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
1176  BMesh *bm = BM_mesh_create(&allocsize,
1177  &((struct BMeshCreateParams){
1178  .use_toolflags = true,
1179  }));
1180 
1182  mesh,
1183  (&(struct BMeshFromMeshParams){
1184  .calc_face_normal = true,
1185  .calc_vert_normal = true,
1186  }));
1187 
1191  BMIter iter;
1192  BMFace *f;
1193  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
1194  const int face_index = BM_elem_index_get(f);
1195  const int face_set_id = modify_hidden ? abs(ss->face_sets[face_index]) :
1196  ss->face_sets[face_index];
1197  BM_elem_flag_set(f, BM_ELEM_TAG, face_set_id == active_face_set_id);
1198  }
1201 
1203  bm,
1204  ob->data,
1205  (&(struct BMeshToMeshParams){
1206  .calc_object_remap = false,
1207  }));
1208 
1209  BM_mesh_free(bm);
1210 }
1211 
1213  const int active_face_set_id,
1214  const int fair_order)
1215 {
1216  SculptSession *ss = ob->sculpt;
1217  const int totvert = SCULPT_vertex_count_get(ss);
1218 
1219  Mesh *mesh = ob->data;
1220  bool *fair_vertices = MEM_malloc_arrayN(totvert, sizeof(bool), "fair vertices");
1221 
1223 
1224  for (int i = 0; i < totvert; i++) {
1225  fair_vertices[i] = !SCULPT_vertex_is_boundary(ss, i) &&
1226  SCULPT_vertex_has_face_set(ss, i, active_face_set_id) &&
1228  }
1229 
1231  BKE_mesh_prefair_and_fair_vertices(mesh, mvert, fair_vertices, fair_order);
1232  MEM_freeN(fair_vertices);
1233 }
1234 
1236  const int active_face_set_id,
1237  const int mode,
1238  const bool modify_hidden)
1239 {
1240  SculptSession *ss = ob->sculpt;
1241 
1242  switch (mode) {
1244  int *prev_face_sets = MEM_dupallocN(ss->face_sets);
1245  sculpt_face_set_grow(ob, ss, prev_face_sets, active_face_set_id, modify_hidden);
1246  MEM_SAFE_FREE(prev_face_sets);
1247  break;
1248  }
1250  int *prev_face_sets = MEM_dupallocN(ss->face_sets);
1251  sculpt_face_set_shrink(ob, ss, prev_face_sets, active_face_set_id, modify_hidden);
1252  MEM_SAFE_FREE(prev_face_sets);
1253  break;
1254  }
1256  sculpt_face_set_delete_geometry(ob, ss, active_face_set_id, modify_hidden);
1257  break;
1260  break;
1263  break;
1264  }
1265 }
1266 
1268  const eSculptFaceSetEditMode mode,
1269  const bool modify_hidden)
1270 {
1271  if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
1272  /* Dyntopo is not supported. */
1273  return false;
1274  }
1275 
1277  if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
1278  /* Modification of base mesh geometry requires special remapping of multires displacement,
1279  * which does not happen here.
1280  * Disable delete operation. It can be supported in the future by doing similar displacement
1281  * data remapping as what happens in the mesh edit mode. */
1282  return false;
1283  }
1284  if (check_single_face_set(ss, ss->face_sets, !modify_hidden)) {
1285  /* Cancel the operator if the mesh only contains one Face Set to avoid deleting the
1286  * entire object. */
1287  return false;
1288  }
1289  }
1290 
1292  if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
1293  /* TODO: Multires topology representation using grids and duplicates can't be used directly
1294  * by the fair algorithm. Multires topology needs to be exposed in a different way or
1295  * converted to a mesh for this operation. */
1296  return false;
1297  }
1298  }
1299 
1300  return true;
1301 }
1302 
1304  Object *ob,
1305  const int active_face_set,
1306  const eSculptFaceSetEditMode mode,
1307  const bool modify_hidden)
1308 {
1309  ED_sculpt_undo_geometry_begin(ob, "edit face set delete geometry");
1310  sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden);
1315 }
1316 
1317 static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **nodes, int totnode)
1318 {
1319  SculptSession *ss = ob->sculpt;
1320  PBVH *pbvh = ss->pbvh;
1321 
1322  /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
1324 
1325  for (int i = 0; i < totnode; i++) {
1327  }
1328 
1330 
1331  if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
1333  }
1334 }
1335 
1337  const int active_face_set,
1338  const eSculptFaceSetEditMode mode,
1339  const bool modify_hidden)
1340 {
1341  PBVH *pbvh = ob->sculpt->pbvh;
1342  PBVHNode **nodes;
1343  int totnode;
1344  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
1345 
1346  if (!nodes) {
1347  return;
1348  }
1349  SCULPT_undo_push_begin(ob, "face set edit");
1351  sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden);
1353  face_set_edit_do_post_visibility_updates(ob, nodes, totnode);
1354  MEM_freeN(nodes);
1355 }
1356 
1358  Object *ob,
1359  const int active_face_set,
1360  const eSculptFaceSetEditMode mode)
1361 {
1363  SculptSession *ss = ob->sculpt;
1364  PBVH *pbvh = ss->pbvh;
1365  PBVHNode **nodes;
1366  int totnode;
1367  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
1368  SCULPT_undo_push_begin(ob, "face set edit");
1369  for (int i = 0; i < totnode; i++) {
1370  BKE_pbvh_node_mark_update(nodes[i]);
1372  }
1373  sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, false);
1374 
1375  if (ss->deform_modifiers_active || ss->shapekey_active) {
1376  SCULPT_flush_stroke_deform(sd, ob, true);
1377  }
1381  MEM_freeN(nodes);
1382 }
1383 
1385 {
1387  SculptSession *ss = ob->sculpt;
1389 
1390  const int mode = RNA_enum_get(op->ptr, "mode");
1391  const bool modify_hidden = RNA_boolean_get(op->ptr, "modify_hidden");
1392 
1393  if (!sculpt_face_set_edit_is_operation_valid(ss, mode, modify_hidden)) {
1394  return OPERATOR_CANCELLED;
1395  }
1396 
1397  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
1398 
1399  /* Update the current active Face Set and Vertex as the operator can be used directly from the
1400  * tool without brush cursor. */
1402  const float mval_fl[2] = {UNPACK2(event->mval)};
1403  if (!SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false)) {
1404  /* The cursor is not over the mesh. Cancel to avoid editing the last updated Face Set ID. */
1405  return OPERATOR_CANCELLED;
1406  }
1407  const int active_face_set = SCULPT_active_face_set_get(ss);
1408 
1409  switch (mode) {
1411  sculpt_face_set_edit_modify_geometry(C, ob, active_face_set, mode, modify_hidden);
1412  break;
1415  sculpt_face_set_edit_modify_face_sets(ob, active_face_set, mode, modify_hidden);
1416  break;
1419  sculpt_face_set_edit_modify_coordinates(C, ob, active_face_set, mode);
1420  break;
1421  }
1422 
1424 
1425  return OPERATOR_FINISHED;
1426 }
1427 
1429 {
1430  /* Identifiers. */
1431  ot->name = "Edit Face Set";
1432  ot->idname = "SCULPT_OT_face_set_edit";
1433  ot->description = "Edits the current active Face Set";
1434 
1435  /* Api callbacks. */
1438 
1440 
1441  RNA_def_enum(
1444  "modify_hidden",
1445  true,
1446  "Modify Hidden",
1447  "Apply the edit operation to hidden Face Sets");
1448 }
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1235
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
CustomData interface, see also DNA_customdata_types.h.
void * CustomData_get_layer(const struct CustomData *data, int type)
int CustomData_get_offset(const struct CustomData *data, int type)
struct Mesh * BKE_mesh_from_object(struct Object *ob)
Definition: mesh.cc:1365
void BKE_mesh_calc_poly_center(const struct MPoly *mpoly, const struct MLoop *loopstart, const struct MVert *mvarray, float r_cent[3])
void BKE_mesh_batch_cache_dirty_tag(struct Mesh *me, eMeshBatchDirtyMode mode)
void BKE_mesh_flush_hidden_from_verts(struct Mesh *me)
@ MESH_FAIRING_DEPTH_POSITION
Definition: BKE_mesh_fair.h:22
@ MESH_FAIRING_DEPTH_TANGENCY
Definition: BKE_mesh_fair.h:23
void BKE_mesh_prefair_and_fair_vertices(struct Mesh *mesh, struct MVert *deform_mverts, bool *affect_vertices, eMeshFairingDepth depth)
Definition: mesh_fair.cc:471
@ BKE_MESH_BATCH_DIRTY_ALL
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
A BVH for high poly meshes.
void BKE_pbvh_node_mark_update(PBVHNode *node)
Definition: pbvh.c:1869
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode)
Definition: BKE_pbvh.h:439
void BKE_pbvh_node_mark_update_visibility(PBVHNode *node)
Definition: pbvh.c:1895
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1798
void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default)
Definition: pbvh.c:2843
#define BKE_pbvh_vertex_iter_end
Definition: BKE_pbvh.h:509
void BKE_pbvh_vert_tag_update_normal(PBVH *pbvh, int index)
Definition: pbvh.c:1967
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:391
@ 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_update_vertex_data(PBVH *pbvh, int flags)
Definition: pbvh.c:1567
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
@ PBVH_UpdateVisibility
Definition: BKE_pbvh.h:72
#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
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:16
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
BLI_INLINE float BLI_hash_int_01(unsigned int k)
Definition: BLI_hash.h:94
MINLINE int max_ii(int a, int b)
MINLINE int clamp_i(int value, int min, int max)
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
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
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
int BLI_task_parallel_thread_id(const TaskParallelTLS *tls)
#define UNPACK2(a)
#define UNUSED(x)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ CD_FACEMAP
@ CD_SCULPT_FACE_SETS
@ CD_BWEIGHT
Object is a sort of wrapper for general info.
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void ED_sculpt_undo_geometry_begin(struct Object *ob, const char *name)
Definition: sculpt_undo.c:1833
void ED_sculpt_undo_geometry_end(struct Object *ob)
Definition: sculpt_undo.c:1839
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#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_DATA
Definition: WM_types.h:456
#define BM_ELEM_CD_GET_INT(ele, offset)
Definition: bmesh_class.h:518
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_SEAM
Definition: bmesh_class.h:473
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
@ BM_ELEM_SMOOTH
Definition: bmesh_class.h:477
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type)
Definition: bmesh_delete.c:258
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_elem_flag_set(ele, hflag, val)
Definition: bmesh_inline.h:16
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
float BM_elem_float_data_get(CustomData *cd, void *element, int type)
Definition: bmesh_interp.c:990
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_EDGE
@ BM_FACES_OF_MESH
@ BM_EDGES_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.cc:258
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
Definition: bmesh_mesh.cc:125
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:558
void BM_mesh_elem_table_init(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:624
BLI_INLINE BMFace * BM_face_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:115
#define BMALLOC_TEMPLATE_FROM_ME(...)
Definition: bmesh_mesh.h:197
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
@ DEL_FACES
ATTR_WARN_UNUSED_RESULT const BMLoop * l
const Depsgraph * depsgraph
SyclQueue * queue
ccl_gpu_kernel_postfix ccl_global float int int int int float threshold
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_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
T abs(const T &a)
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: noise.h:15
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
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_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3836
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_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
int SCULPT_vertex_count_get(SculptSession *ss)
Definition: sculpt.c:111
void SCULPT_boundary_info_ensure(Object *object)
Definition: sculpt.c:5848
bool SCULPT_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mval[2], bool use_sampled_normal)
Definition: sculpt.c:4835
void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible)
Definition: sculpt.c:376
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
SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss, SculptBrushTest *test, char falloff_shape)
Definition: sculpt.c:1686
void SCULPT_vertex_face_set_set(SculptSession *ss, int index, int face_set)
Definition: sculpt.c:483
float SCULPT_brush_strength_factor(SculptSession *ss, const Brush *br, const float brush_point[3], const float len, const float vno[3], const float fno[3], const float mask, const int vertex_index, const int thread_id)
Definition: sculpt.c:2370
const float * SCULPT_active_vertex_co_get(SculptSession *ss)
Definition: sculpt.c:279
void SCULPT_vertex_random_access_ensure(SculptSession *ss)
Definition: sculpt.c:103
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_face_sets_visibility_all_set(SculptSession *ss, bool visible)
Definition: sculpt.c:412
void SCULPT_face_sets_visibility_invert(SculptSession *ss)
Definition: sculpt.c:398
void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
Definition: sculpt.c:5144
bool SCULPT_vertex_is_boundary(const SculptSession *ss, const int index)
Definition: sculpt.c:865
bool SCULPT_mode_poll(bContext *C)
Definition: sculpt.c:3957
float SCULPT_vertex_mask_get(SculptSession *ss, int index)
Definition: sculpt.c:248
int SCULPT_face_set_next_available_get(SculptSession *ss)
Definition: sculpt.c:693
void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
Definition: sculpt.c:3719
MVert * SCULPT_mesh_deformed_mverts_get(SculptSession *ss)
Definition: sculpt.c:289
int SCULPT_active_face_set_get(SculptSession *ss)
Definition: sculpt.c:325
void SCULPT_visibility_sync_all_face_sets_to_vertices(Object *ob)
Definition: sculpt.c:557
void SCULPT_tag_update_overlays(bContext *C)
Definition: sculpt.c:1048
void SCULPT_relax_vertex(SculptSession *ss, PBVHVertexIter *vd, float factor, bool filter_boundary_face_sets, float *r_final_pos)
static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
void SCULPT_OT_face_sets_change_visibility(wmOperatorType *ot)
static void sculpt_face_sets_init_flood_fill(Object *ob, face_sets_flood_fill_test test, const float threshold)
bool(* face_sets_flood_fill_test)(BMesh *bm, BMFace *from_f, BMEdge *from_e, BMFace *to_f, const float threshold)
void SCULPT_OT_face_sets_init(wmOperatorType *ot)
static bool sculpt_face_sets_init_crease_test(BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh)
static void sculpt_face_set_edit_modify_geometry(bContext *C, Object *ob, const int active_face_set, const eSculptFaceSetEditMode mode, const bool modify_hidden)
static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
static void sculpt_face_set_apply_edit(Object *ob, const int active_face_set_id, const int mode, const bool modify_hidden)
int ED_sculpt_face_sets_active_update_and_get(bContext *C, Object *ob, const float mval[2])
static void sculpt_face_set_shrink(Object *ob, SculptSession *ss, const int *prev_face_sets, const int active_face_set_id, const bool modify_hidden)
static void sculpt_face_set_edit_modify_coordinates(bContext *C, Object *ob, const int active_face_set, const eSculptFaceSetEditMode mode)
static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
eSculptFaceSetsInitMode
@ SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT
@ SCULPT_FACE_SETS_FROM_LOOSE_PARTS
@ SCULPT_FACE_SETS_FROM_CREASES
@ SCULPT_FACE_SETS_FROM_SHARP_EDGES
@ SCULPT_FACE_SETS_FROM_MATERIALS
@ SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES
@ SCULPT_FACE_SETS_FROM_FACE_MAPS
@ SCULPT_FACE_SETS_FROM_NORMALS
@ SCULPT_FACE_SETS_FROM_UV_SEAMS
eSculptFaceGroupsCreateModes
@ SCULPT_FACE_SET_VISIBLE
@ SCULPT_FACE_SET_MASKED
@ SCULPT_FACE_SET_ALL
@ SCULPT_FACE_SET_SELECTION
static void sculpt_face_set_delete_geometry(Object *ob, SculptSession *ss, const int active_face_set_id, const bool modify_hidden)
eSculptFaceGroupVisibilityModes
@ SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE
@ SCULPT_FACE_SET_VISIBILITY_INVERT
@ SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE
@ SCULPT_FACE_SET_VISIBILITY_TOGGLE
@ SCULPT_FACE_SET_VISIBILITY_SHOW_ALL
void ED_sculpt_face_sets_initialize_none_to_id(struct Mesh *mesh, const int new_id)
static void sculpt_face_set_grow(Object *ob, SculptSession *ss, const int *prev_face_sets, const int active_face_set_id, const bool modify_hidden)
static int sculpt_face_sets_change_visibility_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static EnumPropertyItem prop_sculpt_face_sets_change_visibility_types[]
static void sculpt_face_set_edit_fair_face_set(Object *ob, const int active_face_set_id, const int fair_order)
void SCULPT_OT_face_sets_create(wmOperatorType *ot)
static bool sculpt_face_sets_init_sharp_edges_test(BMesh *UNUSED(bm), BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float UNUSED(threshold))
static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
static EnumPropertyItem prop_sculpt_face_sets_init_types[]
eSculptFaceSetEditMode
@ SCULPT_FACE_SET_EDIT_SHRINK
@ SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY
@ SCULPT_FACE_SET_EDIT_FAIR_TANGENCY
@ SCULPT_FACE_SET_EDIT_GROW
@ SCULPT_FACE_SET_EDIT_FAIR_POSITIONS
static bool sculpt_face_sets_init_normals_test(BMesh *UNUSED(bm), BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float threshold)
static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool check_visible_only)
static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void SCULPT_OT_face_sets_edit(struct wmOperatorType *ot)
static bool sculpt_face_set_edit_is_operation_valid(SculptSession *ss, const eSculptFaceSetEditMode mode, const bool modify_hidden)
static bool sculpt_face_sets_init_loose_parts_test(BMesh *UNUSED(bm), BMFace *UNUSED(from_f), BMEdge *UNUSED(from_e), BMFace *UNUSED(to_f), const float UNUSED(threshold))
static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_OT_face_sets_randomize_colors(wmOperatorType *ot)
static bool sculpt_face_sets_init_face_set_boundary_test(BMesh *bm, BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float UNUSED(threshold))
static EnumPropertyItem prop_sculpt_face_set_create_types[]
static void sculpt_face_sets_init_loop(Object *ob, const int mode)
static void sculpt_face_set_edit_modify_face_sets(Object *ob, const int active_face_set, const eSculptFaceSetEditMode mode, const bool modify_hidden)
static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator *UNUSED(op))
static bool sculpt_face_sets_init_uv_seams_test(BMesh *UNUSED(bm), BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float UNUSED(threshold))
void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
static bool sculpt_face_sets_init_bevel_weight_test(BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
static EnumPropertyItem prop_sculpt_face_sets_edit_types[]
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
bool(* SculptBrushTestFn)(SculptBrushTest *test, const float co[3])
@ SCULPT_UPDATE_COORDS
Definition: sculpt_intern.h:45
SculptUndoNode * SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type)
Definition: sculpt_undo.c:1419
@ SCULPT_UNDO_FACE_SETS
@ SCULPT_UNDO_COORDS
short mat_nr
Definition: bmesh_class.h:281
float no[3]
Definition: bmesh_class.h:271
CustomData edata
Definition: bmesh_class.h:337
CustomData pdata
Definition: bmesh_class.h:337
struct CurveMapping * curve
unsigned int v
struct MLoop * mloop
CustomData pdata
int totpoly
int face_sets_color_seed
int face_sets_color_default
struct MPoly * mpoly
float obmat[4][4]
struct SculptSession * sculpt
void * data
struct MVert * mvert
Definition: BKE_pbvh.h:428
float * co
Definition: BKE_pbvh.h:430
float * fno
Definition: BKE_pbvh.h:432
float * no
Definition: BKE_pbvh.h:431
float * mask
Definition: BKE_pbvh.h:433
int * face_sets
Definition: BKE_paint.h:536
struct KeyBlock * shapekey_active
Definition: BKE_paint.h:505
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 StrokeCache * cache
Definition: BKE_paint.h:563
struct PBVH * pbvh
Definition: BKE_paint.h:550
bool deform_modifiers_active
Definition: BKE_paint.h:555
Paint paint
struct UnifiedPaintSettings unified_paint_settings
int mval[2]
Definition: WM_types.h:684
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
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479