Blender  V2.93
sculpt_face_set.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) 2020 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "MEM_guardedalloc.h"
25 
26 #include "BLI_blenlib.h"
27 #include "BLI_hash.h"
28 #include "BLI_math.h"
29 #include "BLI_task.h"
30 
31 #include "DNA_brush_types.h"
32 #include "DNA_customdata_types.h"
33 #include "DNA_mesh_types.h"
34 #include "DNA_meshdata_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_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_customdata.h"
43 #include "BKE_mesh.h"
44 #include "BKE_mesh_fair.h"
45 #include "BKE_mesh_mapping.h"
46 #include "BKE_multires.h"
47 #include "BKE_node.h"
48 #include "BKE_object.h"
49 #include "BKE_paint.h"
50 #include "BKE_pbvh.h"
51 #include "BKE_scene.h"
52 
53 #include "DEG_depsgraph.h"
54 
55 #include "WM_api.h"
56 #include "WM_message.h"
57 #include "WM_toolsystem.h"
58 #include "WM_types.h"
59 
60 #include "ED_object.h"
61 #include "ED_screen.h"
62 #include "ED_sculpt.h"
63 #include "ED_view3d.h"
64 #include "paint_intern.h"
65 #include "sculpt_intern.h"
66 
67 #include "RNA_access.h"
68 #include "RNA_define.h"
69 
70 #include "bmesh.h"
71 
72 #include <math.h>
73 #include <stdlib.h>
74 
75 /* Utils. */
77 {
78  int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
79  if (!face_sets) {
80  return SCULPT_FACE_SET_NONE;
81  }
82 
83  int next_face_set_id = 0;
84  for (int i = 0; i < mesh->totpoly; i++) {
85  next_face_set_id = max_ii(next_face_set_id, abs(face_sets[i]));
86  }
87  next_face_set_id++;
88 
89  return next_face_set_id;
90 }
91 
92 void ED_sculpt_face_sets_initialize_none_to_id(struct Mesh *mesh, const int new_id)
93 {
94  int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
95  if (!face_sets) {
96  return;
97  }
98 
99  for (int i = 0; i < mesh->totpoly; i++) {
100  if (face_sets[i] == SCULPT_FACE_SET_NONE) {
101  face_sets[i] = new_id;
102  }
103  }
104 }
105 
107 {
108  SculptSession *ss = ob->sculpt;
109  if (!ss) {
110  return SCULPT_FACE_SET_NONE;
111  }
112 
114  if (!SCULPT_cursor_geometry_info_update(C, &gi, mval, false)) {
115  return SCULPT_FACE_SET_NONE;
116  }
117 
118  return SCULPT_active_face_set_get(ss);
119 }
120 
121 /* Draw Face Sets Brush. */
122 
123 static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
124  const int n,
125  const TaskParallelTLS *__restrict tls)
126 {
127  SculptThreadedTaskData *data = userdata;
128  SculptSession *ss = data->ob->sculpt;
129  const Brush *brush = data->brush;
130  const float bstrength = ss->cache->bstrength;
131 
132  PBVHVertexIter vd;
133 
134  SculptBrushTest test;
136  ss, &test, data->brush->falloff_shape);
137  const int thread_id = BLI_task_parallel_thread_id(tls);
138 
140 
141  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
142  if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
143  MeshElemMap *vert_map = &ss->pmap[vd.index];
144  for (int j = 0; j < ss->pmap[vd.index].count; j++) {
145  const MPoly *p = &ss->mpoly[vert_map->indices[j]];
146 
147  float poly_center[3];
148  BKE_mesh_calc_poly_center(p, &ss->mloop[p->loopstart], mvert, poly_center);
149 
150  if (!sculpt_brush_test_sq_fn(&test, poly_center)) {
151  continue;
152  }
153  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
154  brush,
155  vd.co,
156  sqrtf(test.dist),
157  vd.no,
158  vd.fno,
159  vd.mask ? *vd.mask : 0.0f,
160  vd.index,
161  thread_id);
162 
163  if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) {
164  ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set);
165  }
166  }
167  }
168 
169  else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
170  {
171  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
172  continue;
173  }
174  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
175  brush,
176  vd.co,
177  sqrtf(test.dist),
178  vd.no,
179  vd.fno,
180  vd.mask ? *vd.mask : 0.0f,
181  vd.index,
182  thread_id);
183 
184  if (fade > 0.05f) {
186  }
187  }
188  }
189  }
191 }
192 
193 static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
194  const int n,
195  const TaskParallelTLS *__restrict tls)
196 {
197  SculptThreadedTaskData *data = userdata;
198  SculptSession *ss = data->ob->sculpt;
199  const Brush *brush = data->brush;
200  float bstrength = ss->cache->bstrength;
201 
202  PBVHVertexIter vd;
203 
204  SculptBrushTest test;
206  ss, &test, data->brush->falloff_shape);
207 
208  const bool relax_face_sets = !(ss->cache->iteration_count % 3 == 0);
209  /* This operations needs a strength tweak as the relax deformation is too weak by default. */
210  if (relax_face_sets) {
211  bstrength *= 2.0f;
212  }
213 
214  const int thread_id = BLI_task_parallel_thread_id(tls);
215 
216  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
217  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
218  continue;
219  }
220  if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
221  continue;
222  }
223 
224  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
225  brush,
226  vd.co,
227  sqrtf(test.dist),
228  vd.no,
229  vd.fno,
230  vd.mask ? *vd.mask : 0.0f,
231  vd.index,
232  thread_id);
233 
234  SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co);
235  if (vd.mvert) {
237  }
238  }
240 }
241 
242 void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
243 {
244  SculptSession *ss = ob->sculpt;
245  Brush *brush = BKE_paint_brush(&sd->paint);
246 
248 
249  /* Threaded loop over nodes. */
251  .sd = sd,
252  .ob = ob,
253  .brush = brush,
254  .nodes = nodes,
255  };
256 
257  TaskParallelSettings settings;
258  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
259  if (ss->cache->alt_smooth) {
261  for (int i = 0; i < 4; i++) {
263  }
264  }
265  else {
267  }
268 }
269 
270 /* Face Sets Operators */
271 
278 
280  {
282  "MASKED",
283  0,
284  "Face Set from Masked",
285  "Create a new Face Set from the masked faces",
286  },
287  {
289  "VISIBLE",
290  0,
291  "Face Set from Visible",
292  "Create a new Face Set from the visible vertices",
293  },
294  {
296  "ALL",
297  0,
298  "Face Set Full Mesh",
299  "Create an unique Face Set with all faces in the sculpt",
300  },
301  {
303  "SELECTION",
304  0,
305  "Face Set from Edit Mode Selection",
306  "Create an Face Set corresponding to the Edit Mode face selection",
307  },
308  {0, NULL, 0, NULL, NULL},
309 };
310 
312 {
314  SculptSession *ss = ob->sculpt;
316 
317  const int mode = RNA_enum_get(op->ptr, "mode");
318 
319  /* Dyntopo not supported. */
320  if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
321  return OPERATOR_CANCELLED;
322  }
323 
325 
326  const int tot_vert = SCULPT_vertex_count_get(ss);
327  float threshold = 0.5f;
328 
329  PBVH *pbvh = ob->sculpt->pbvh;
330  PBVHNode **nodes;
331  int totnode;
332  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
333 
334  if (!nodes) {
335  return OPERATOR_CANCELLED;
336  }
337 
338  SCULPT_undo_push_begin(ob, "face set change");
340 
341  const int next_face_set = SCULPT_face_set_next_available_get(ss);
342 
343  if (mode == SCULPT_FACE_SET_MASKED) {
344  for (int i = 0; i < tot_vert; i++) {
345  if (SCULPT_vertex_mask_get(ss, i) >= threshold && SCULPT_vertex_visible_get(ss, i)) {
346  SCULPT_vertex_face_set_set(ss, i, next_face_set);
347  }
348  }
349  }
350 
351  if (mode == SCULPT_FACE_SET_VISIBLE) {
352 
353  /* If all vertices in the sculpt are visible, create the new face set and update the default
354  * color. This way the new face set will be white, which is a quick way of disabling all face
355  * sets and the performance hit of rendering the overlay. */
356  bool all_visible = true;
357  for (int i = 0; i < tot_vert; i++) {
358  if (!SCULPT_vertex_visible_get(ss, i)) {
359  all_visible = false;
360  break;
361  }
362  }
363 
364  if (all_visible) {
365  Mesh *mesh = ob->data;
366  mesh->face_sets_color_default = next_face_set;
369  }
370 
371  for (int i = 0; i < tot_vert; i++) {
372  if (SCULPT_vertex_visible_get(ss, i)) {
373  SCULPT_vertex_face_set_set(ss, i, next_face_set);
374  }
375  }
376  }
377 
378  if (mode == SCULPT_FACE_SET_ALL) {
379  for (int i = 0; i < tot_vert; i++) {
380  SCULPT_vertex_face_set_set(ss, i, next_face_set);
381  }
382  }
383 
384  if (mode == SCULPT_FACE_SET_SELECTION) {
385  Mesh *mesh = ob->data;
386  BMesh *bm;
387  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
388  bm = BM_mesh_create(&allocsize,
389  &((struct BMeshCreateParams){
390  .use_toolflags = true,
391  }));
392 
394  mesh,
395  (&(struct BMeshFromMeshParams){
396  .calc_face_normal = true,
397  }));
398 
399  BMIter iter;
400  BMFace *f;
401  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
403  ss->face_sets[BM_elem_index_get(f)] = next_face_set;
404  }
405  }
406  BM_mesh_free(bm);
407  }
408 
409  for (int i = 0; i < totnode; i++) {
410  BKE_pbvh_node_mark_redraw(nodes[i]);
411  }
412 
413  MEM_SAFE_FREE(nodes);
414 
416 
418 
419  return OPERATOR_FINISHED;
420 }
421 
423 {
424  /* identifiers */
425  ot->name = "Create Face Set";
426  ot->idname = "SCULPT_OT_face_sets_create";
427  ot->description = "Create a new Face Set";
428 
429  /* api callbacks */
432 
434 
435  RNA_def_enum(
437 }
438 
450 
452  {
454  "LOOSE_PARTS",
455  0,
456  "Face Sets from Loose Parts",
457  "Create a Face Set per loose part in the mesh",
458  },
459  {
461  "MATERIALS",
462  0,
463  "Face Sets from Material Slots",
464  "Create a Face Set per Material Slot",
465  },
466  {
468  "NORMALS",
469  0,
470  "Face Sets from Mesh Normals",
471  "Create Face Sets for Faces that have similar normal",
472  },
473  {
475  "UV_SEAMS",
476  0,
477  "Face Sets from UV Seams",
478  "Create Face Sets using UV Seams as boundaries",
479  },
480  {
482  "CREASES",
483  0,
484  "Face Sets from Edge Creases",
485  "Create Face Sets using Edge Creases as boundaries",
486  },
487  {
489  "BEVEL_WEIGHT",
490  0,
491  "Face Sets from Bevel Weight",
492  "Create Face Sets using Bevel Weights as boundaries",
493  },
494  {
496  "SHARP_EDGES",
497  0,
498  "Face Sets from Sharp Edges",
499  "Create Face Sets using Sharp Edges as boundaries",
500  },
501  {
503  "FACE_MAPS",
504  0,
505  "Face Sets from Face Maps",
506  "Create a Face Set per Face Map",
507  },
508  {
510  "FACE_SET_BOUNDARIES",
511  0,
512  "Face Sets from Face Set Boundaries",
513  "Create a Face Set per isolated Face Set",
514  },
515 
516  {0, NULL, 0, NULL, NULL},
517 };
518 
520  BMesh *bm, BMFace *from_f, BMEdge *from_e, BMFace *to_f, const float threshold);
521 
523  BMFace *UNUSED(from_f),
524  BMEdge *UNUSED(from_e),
525  BMFace *UNUSED(to_f),
526  const float UNUSED(threshold))
527 {
528  return true;
529 }
530 
532  BMesh *UNUSED(bm), BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float threshold)
533 {
534  return fabsf(dot_v3v3(from_f->no, to_f->no)) > threshold;
535 }
536 
538  BMFace *UNUSED(from_f),
539  BMEdge *from_e,
540  BMFace *UNUSED(to_f),
541  const float UNUSED(threshold))
542 {
543  return !BM_elem_flag_test(from_e, BM_ELEM_SEAM);
544 }
545 
547  BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
548 {
549  return BM_elem_float_data_get(&bm->edata, from_e, CD_CREASE) < threshold;
550 }
551 
553  BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
554 {
555  return BM_elem_float_data_get(&bm->edata, from_e, CD_BWEIGHT) < threshold;
556 }
557 
559  BMFace *UNUSED(from_f),
560  BMEdge *from_e,
561  BMFace *UNUSED(to_f),
562  const float UNUSED(threshold))
563 {
564  return BM_elem_flag_test(from_e, BM_ELEM_SMOOTH);
565 }
566 
568  BMesh *bm, BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float UNUSED(threshold))
569 {
570  const int cd_face_sets_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
571  return BM_ELEM_CD_GET_INT(from_f, cd_face_sets_offset) ==
572  BM_ELEM_CD_GET_INT(to_f, cd_face_sets_offset);
573 }
574 
577  const float threshold)
578 {
579  SculptSession *ss = ob->sculpt;
580  Mesh *mesh = ob->data;
581  BMesh *bm;
582  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
583  bm = BM_mesh_create(&allocsize,
584  &((struct BMeshCreateParams){
585  .use_toolflags = true,
586  }));
587 
589  mesh,
590  (&(struct BMeshFromMeshParams){
591  .calc_face_normal = true,
592  }));
593 
594  BLI_bitmap *visited_faces = BLI_BITMAP_NEW(mesh->totpoly, "visited faces");
595  const int totfaces = mesh->totpoly;
596 
597  int *face_sets = ss->face_sets;
598 
601 
602  int next_face_set = 1;
603 
604  for (int i = 0; i < totfaces; i++) {
605  if (BLI_BITMAP_TEST(visited_faces, i)) {
606  continue;
607  }
608  GSQueue *queue;
609  queue = BLI_gsqueue_new(sizeof(int));
610 
611  face_sets[i] = next_face_set;
612  BLI_BITMAP_ENABLE(visited_faces, i);
613  BLI_gsqueue_push(queue, &i);
614 
615  while (!BLI_gsqueue_is_empty(queue)) {
616  int from_f;
617  BLI_gsqueue_pop(queue, &from_f);
618 
619  BMFace *f, *f_neighbor;
620  BMEdge *ed;
621  BMIter iter_a, iter_b;
622 
623  f = BM_face_at_index(bm, from_f);
624 
625  BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) {
626  BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) {
627  if (f_neighbor == f) {
628  continue;
629  }
630  int neighbor_face_index = BM_elem_index_get(f_neighbor);
631  if (BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) {
632  continue;
633  }
634  if (!test(bm, f, ed, f_neighbor, threshold)) {
635  continue;
636  }
637 
638  face_sets[neighbor_face_index] = next_face_set;
639  BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index);
640  BLI_gsqueue_push(queue, &neighbor_face_index);
641  }
642  }
643  }
644 
645  next_face_set += 1;
646 
648  }
649 
650  MEM_SAFE_FREE(visited_faces);
651 
652  BM_mesh_free(bm);
653 }
654 
655 static void sculpt_face_sets_init_loop(Object *ob, const int mode)
656 {
657  Mesh *mesh = ob->data;
658  SculptSession *ss = ob->sculpt;
659  BMesh *bm;
660  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
661  bm = BM_mesh_create(&allocsize,
662  &((struct BMeshCreateParams){
663  .use_toolflags = true,
664  }));
665 
667  mesh,
668  (&(struct BMeshFromMeshParams){
669  .calc_face_normal = true,
670  }));
671  BMIter iter;
672  BMFace *f;
673 
674  const int cd_fmaps_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
675 
676  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
677  if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) {
678  ss->face_sets[BM_elem_index_get(f)] = (int)(f->mat_nr + 1);
679  }
680  else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) {
681  if (cd_fmaps_offset != -1) {
682  ss->face_sets[BM_elem_index_get(f)] = BM_ELEM_CD_GET_INT(f, cd_fmaps_offset) + 2;
683  }
684  else {
685  ss->face_sets[BM_elem_index_get(f)] = 1;
686  }
687  }
688  }
689  BM_mesh_free(bm);
690 }
691 
693 {
695  SculptSession *ss = ob->sculpt;
697 
698  const int mode = RNA_enum_get(op->ptr, "mode");
699 
700  /* Dyntopo not supported. */
701  if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
702  return OPERATOR_CANCELLED;
703  }
704 
705  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
706 
707  PBVH *pbvh = ob->sculpt->pbvh;
708  PBVHNode **nodes;
709  int totnode;
710  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
711 
712  if (!nodes) {
713  return OPERATOR_CANCELLED;
714  }
715 
716  SCULPT_undo_push_begin(ob, "face set change");
718 
719  const float threshold = RNA_float_get(op->ptr, "threshold");
720 
721  switch (mode) {
724  break;
727  break;
730  break;
733  break;
736  break;
739  break;
742  break;
746  break;
749  break;
750  }
751 
753 
754  /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
756 
757  for (int i = 0; i < totnode; i++) {
759  }
760 
762 
763  MEM_SAFE_FREE(nodes);
764 
765  if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
767  }
768 
770 
771  return OPERATOR_FINISHED;
772 }
773 
775 {
776  /* identifiers */
777  ot->name = "Init Face Sets";
778  ot->idname = "SCULPT_OT_face_sets_init";
779  ot->description = "Initializes all Face Sets in the mesh";
780 
781  /* api callbacks */
784 
786 
787  RNA_def_enum(
790  ot->srna,
791  "threshold",
792  0.5f,
793  0.0f,
794  1.0f,
795  "Threshold",
796  "Minimum value to consider a certain attribute a boundary when creating the Face Sets",
797  0.0f,
798  1.0f);
799 }
800 
808 
810  {
812  "TOGGLE",
813  0,
814  "Toggle Visibility",
815  "Hide all Face Sets except for the active one",
816  },
817  {
819  "SHOW_ACTIVE",
820  0,
821  "Show Active Face Set",
822  "Show Active Face Set",
823  },
824  {
826  "HIDE_ACTIVE",
827  0,
828  "Hide Active Face Sets",
829  "Hide Active Face Sets",
830  },
831  {
833  "INVERT",
834  0,
835  "Invert Face Set Visibility",
836  "Invert Face Set Visibility",
837  },
838  {
840  "SHOW_ALL",
841  0,
842  "Show All Face Sets",
843  "Show All Face Sets",
844  },
845  {0, NULL, 0, NULL, NULL},
846 };
847 
849 {
851  SculptSession *ss = ob->sculpt;
853 
854  /* Dyntopo not supported. */
855  if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
856  return OPERATOR_CANCELLED;
857  }
858 
859  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
860 
861  const int tot_vert = SCULPT_vertex_count_get(ss);
862  const int mode = RNA_enum_get(op->ptr, "mode");
863  const int active_face_set = SCULPT_active_face_set_get(ss);
864 
865  SCULPT_undo_push_begin(ob, "Hide area");
866 
867  PBVH *pbvh = ob->sculpt->pbvh;
868  PBVHNode **nodes;
869  int totnode;
870 
871  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
872 
873  if (totnode == 0) {
874  MEM_SAFE_FREE(nodes);
875  return OPERATOR_CANCELLED;
876  }
877 
879 
880  if (mode == SCULPT_FACE_SET_VISIBILITY_TOGGLE) {
881  bool hidden_vertex = false;
882 
883  /* This can fail with regular meshes with non-manifold geometry as the visibility state can't
884  * be synced from face sets to non-manifold vertices. */
885  if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
886  for (int i = 0; i < tot_vert; i++) {
887  if (!SCULPT_vertex_visible_get(ss, i)) {
888  hidden_vertex = true;
889  break;
890  }
891  }
892  }
893 
894  for (int i = 0; i < ss->totfaces; i++) {
895  if (ss->face_sets[i] <= 0) {
896  hidden_vertex = true;
897  break;
898  }
899  }
900 
901  if (hidden_vertex) {
903  }
904  else {
906  SCULPT_face_set_visibility_set(ss, active_face_set, true);
907  }
908  }
909 
912  }
913 
916  SCULPT_face_set_visibility_set(ss, active_face_set, true);
917  }
918 
920  SCULPT_face_set_visibility_set(ss, active_face_set, false);
921  }
922 
923  if (mode == SCULPT_FACE_SET_VISIBILITY_INVERT) {
925  }
926 
927  /* For modes that use the cursor active vertex, update the rotation origin for viewport
928  * navigation. */
931  float location[3];
933  mul_m4_v3(ob->obmat, location);
934  copy_v3_v3(ups->average_stroke_accum, location);
935  ups->average_stroke_counter = 1;
936  ups->last_stroke_valid = true;
937  }
938 
939  /* Sync face sets visibility and vertex visibility. */
941 
943 
944  for (int i = 0; i < totnode; i++) {
946  }
947 
949 
950  MEM_SAFE_FREE(nodes);
951 
953 
954  return OPERATOR_FINISHED;
955 }
956 
958  wmOperator *op,
959  const wmEvent *event)
960 {
962  SculptSession *ss = ob->sculpt;
963 
964  /* Update the active vertex and Face Set using the cursor position to avoid relying on the paint
965  * cursor updates. */
967  float mouse[2];
968  mouse[0] = event->mval[0];
969  mouse[1] = event->mval[1];
971  SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
972 
974 }
975 
977 {
978  /* Identifiers. */
979  ot->name = "Face Sets Visibility";
980  ot->idname = "SCULPT_OT_face_set_change_visibility";
981  ot->description = "Change the visibility of the Face Sets of the sculpt";
982 
983  /* Api callbacks. */
987 
989 
991  "mode",
994  "Mode",
995  "");
996 }
997 
999 {
1000 
1002  SculptSession *ss = ob->sculpt;
1003 
1004  /* Dyntopo not supported. */
1005  if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
1006  return OPERATOR_CANCELLED;
1007  }
1008 
1009  PBVH *pbvh = ob->sculpt->pbvh;
1010  PBVHNode **nodes;
1011  int totnode;
1012  Mesh *mesh = ob->data;
1013 
1014  mesh->face_sets_color_seed += 1;
1015  if (ss->face_sets) {
1016  const int random_index = clamp_i(ss->totfaces * BLI_hash_int_01(mesh->face_sets_color_seed),
1017  0,
1018  max_ii(0, ss->totfaces - 1));
1019  mesh->face_sets_color_default = ss->face_sets[random_index];
1020  }
1022 
1023  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
1024  for (int i = 0; i < totnode; i++) {
1025  BKE_pbvh_node_mark_redraw(nodes[i]);
1026  }
1027 
1028  MEM_SAFE_FREE(nodes);
1029 
1031 
1032  return OPERATOR_FINISHED;
1033 }
1034 
1036 {
1037  /* Identifiers. */
1038  ot->name = "Randomize Face Sets Colors";
1039  ot->idname = "SCULPT_OT_face_sets_randomize_colors";
1040  ot->description = "Generates a new set of random colors to render the Face Sets in the viewport";
1041 
1042  /* Api callbacks. */
1045 
1047 }
1048 
1056 
1058  {
1060  "GROW",
1061  0,
1062  "Grow Face Set",
1063  "Grows the Face Sets boundary by one face based on mesh topology",
1064  },
1065  {
1067  "SHRINK",
1068  0,
1069  "Shrink Face Set",
1070  "Shrinks the Face Sets boundary by one face based on mesh topology",
1071  },
1072  {
1074  "DELETE_GEOMETRY",
1075  0,
1076  "Delete Geometry",
1077  "Deletes the faces that are assigned to the Face Set",
1078  },
1079  {
1081  "FAIR_POSITIONS",
1082  0,
1083  "Fair Positions",
1084  "Creates a smooth as possible geometry patch from the Face Set minimizing changes in "
1085  "vertex positions",
1086  },
1087  {
1089  "FAIR_TANGENCY",
1090  0,
1091  "Fair Tangency",
1092  "Creates a smooth as possible geometry patch from the Face Set minimizing changes in "
1093  "vertex tangents",
1094  },
1095  {0, NULL, 0, NULL, NULL},
1096 };
1097 
1099  SculptSession *ss,
1100  const int *prev_face_sets,
1101  const int active_face_set_id,
1102  const bool modify_hidden)
1103 {
1105  for (int p = 0; p < mesh->totpoly; p++) {
1106  if (!modify_hidden && prev_face_sets[p] <= 0) {
1107  continue;
1108  }
1109  const MPoly *c_poly = &mesh->mpoly[p];
1110  for (int l = 0; l < c_poly->totloop; l++) {
1111  const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l];
1112  const MeshElemMap *vert_map = &ss->pmap[c_loop->v];
1113  for (int i = 0; i < vert_map->count; i++) {
1114  const int neighbor_face_index = vert_map->indices[i];
1115  if (neighbor_face_index == p) {
1116  continue;
1117  }
1118  if (abs(prev_face_sets[neighbor_face_index]) == active_face_set_id) {
1119  ss->face_sets[p] = active_face_set_id;
1120  }
1121  }
1122  }
1123  }
1124 }
1125 
1127  SculptSession *ss,
1128  const int *prev_face_sets,
1129  const int active_face_set_id,
1130  const bool modify_hidden)
1131 {
1133  for (int p = 0; p < mesh->totpoly; p++) {
1134  if (!modify_hidden && prev_face_sets[p] <= 0) {
1135  continue;
1136  }
1137  if (abs(prev_face_sets[p]) == active_face_set_id) {
1138  const MPoly *c_poly = &mesh->mpoly[p];
1139  for (int l = 0; l < c_poly->totloop; l++) {
1140  const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l];
1141  const MeshElemMap *vert_map = &ss->pmap[c_loop->v];
1142  for (int i = 0; i < vert_map->count; i++) {
1143  const int neighbor_face_index = vert_map->indices[i];
1144  if (neighbor_face_index == p) {
1145  continue;
1146  }
1147  if (abs(prev_face_sets[neighbor_face_index]) != active_face_set_id) {
1148  ss->face_sets[p] = prev_face_sets[neighbor_face_index];
1149  }
1150  }
1151  }
1152  }
1153  }
1154 }
1155 
1156 static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool check_visible_only)
1157 {
1158 
1159  int first_face_set = SCULPT_FACE_SET_NONE;
1160  if (check_visible_only) {
1161  for (int f = 0; f < ss->totfaces; f++) {
1162  if (face_sets[f] > 0) {
1163  first_face_set = face_sets[f];
1164  break;
1165  }
1166  }
1167  }
1168  else {
1169  first_face_set = abs(face_sets[0]);
1170  }
1171 
1172  if (first_face_set == SCULPT_FACE_SET_NONE) {
1173  return true;
1174  }
1175 
1176  for (int f = 0; f < ss->totfaces; f++) {
1177  const int face_set_id = check_visible_only ? face_sets[f] : abs(face_sets[f]);
1178  if (face_set_id != first_face_set) {
1179  return false;
1180  }
1181  }
1182  return true;
1183 }
1184 
1186  SculptSession *ss,
1187  const int active_face_set_id,
1188  const bool modify_hidden)
1189 {
1190 
1191  Mesh *mesh = ob->data;
1192  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
1193  BMesh *bm = BM_mesh_create(&allocsize,
1194  &((struct BMeshCreateParams){
1195  .use_toolflags = true,
1196  }));
1197 
1199  mesh,
1200  (&(struct BMeshFromMeshParams){
1201  .calc_face_normal = true,
1202  }));
1203 
1207  BMIter iter;
1208  BMFace *f;
1209  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
1210  const int face_index = BM_elem_index_get(f);
1211  const int face_set_id = modify_hidden ? abs(ss->face_sets[face_index]) :
1212  ss->face_sets[face_index];
1213  BM_elem_flag_set(f, BM_ELEM_TAG, face_set_id == active_face_set_id);
1214  }
1217 
1219  bm,
1220  ob->data,
1221  (&(struct BMeshToMeshParams){
1222  .calc_object_remap = false,
1223  }));
1224 
1225  BM_mesh_free(bm);
1226 }
1227 
1229  const int active_face_set_id,
1230  const int fair_order)
1231 {
1232  SculptSession *ss = ob->sculpt;
1233  const int totvert = SCULPT_vertex_count_get(ss);
1234 
1235  Mesh *mesh = ob->data;
1236  bool *fair_vertices = MEM_malloc_arrayN(sizeof(bool), totvert, "fair vertices");
1237 
1239 
1240  for (int i = 0; i < totvert; i++) {
1241  fair_vertices[i] = !SCULPT_vertex_is_boundary(ss, i) &&
1242  SCULPT_vertex_has_face_set(ss, i, active_face_set_id) &&
1244  }
1245 
1247  BKE_mesh_prefair_and_fair_vertices(mesh, mvert, fair_vertices, fair_order);
1248  MEM_freeN(fair_vertices);
1249 }
1250 
1252  const int active_face_set_id,
1253  const int mode,
1254  const bool modify_hidden)
1255 {
1256  SculptSession *ss = ob->sculpt;
1257 
1258  switch (mode) {
1260  int *prev_face_sets = MEM_dupallocN(ss->face_sets);
1261  sculpt_face_set_grow(ob, ss, prev_face_sets, active_face_set_id, modify_hidden);
1262  MEM_SAFE_FREE(prev_face_sets);
1263  break;
1264  }
1266  int *prev_face_sets = MEM_dupallocN(ss->face_sets);
1267  sculpt_face_set_shrink(ob, ss, prev_face_sets, active_face_set_id, modify_hidden);
1268  MEM_SAFE_FREE(prev_face_sets);
1269  break;
1270  }
1272  sculpt_face_set_delete_geometry(ob, ss, active_face_set_id, modify_hidden);
1273  break;
1276  break;
1279  break;
1280  }
1281 }
1282 
1284  const eSculptFaceSetEditMode mode,
1285  const bool modify_hidden)
1286 {
1287  if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
1288  /* Dyntopo is not supported. */
1289  return false;
1290  }
1291 
1293  if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
1294  /* Modification of base mesh geometry requires special remapping of multires displacement,
1295  * which does not happen here.
1296  * Disable delete operation. It can be supported in the future by doing similar displacement
1297  * data remapping as what happens in the mesh edit mode. */
1298  return false;
1299  }
1300  if (check_single_face_set(ss, ss->face_sets, !modify_hidden)) {
1301  /* Cancel the operator if the mesh only contains one Face Set to avoid deleting the
1302  * entire object. */
1303  return false;
1304  }
1305  }
1306 
1308  if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
1309  /* TODO: Multires topology representation using grids and duplicates can't be used directly
1310  * by the fair algorithm. Multires topology needs to be exposed in a different way or
1311  * converted to a mesh for this operation. */
1312  return false;
1313  }
1314  }
1315 
1316  return true;
1317 }
1318 
1320  Object *ob,
1321  const int active_face_set,
1322  const eSculptFaceSetEditMode mode,
1323  const bool modify_hidden)
1324 {
1325  ED_sculpt_undo_geometry_begin(ob, "edit face set delete geometry");
1326  sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden);
1331 }
1332 
1333 static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **nodes, int totnode)
1334 {
1335  SculptSession *ss = ob->sculpt;
1336  PBVH *pbvh = ss->pbvh;
1337 
1338  /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
1340 
1341  for (int i = 0; i < totnode; i++) {
1343  }
1344 
1346 
1347  if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
1349  }
1350 }
1351 
1353  const int active_face_set,
1354  const eSculptFaceSetEditMode mode,
1355  const bool modify_hidden)
1356 {
1357  PBVH *pbvh = ob->sculpt->pbvh;
1358  PBVHNode **nodes;
1359  int totnode;
1360  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
1361 
1362  if (!nodes) {
1363  return;
1364  }
1365  SCULPT_undo_push_begin(ob, "face set edit");
1367  sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden);
1369  face_set_edit_do_post_visibility_updates(ob, nodes, totnode);
1370  MEM_freeN(nodes);
1371 }
1372 
1374  Object *ob,
1375  const int active_face_set,
1376  const eSculptFaceSetEditMode mode)
1377 {
1379  SculptSession *ss = ob->sculpt;
1380  PBVH *pbvh = ss->pbvh;
1381  PBVHNode **nodes;
1382  int totnode;
1383  BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
1384  SCULPT_undo_push_begin(ob, "face set edit");
1385  for (int i = 0; i < totnode; i++) {
1386  BKE_pbvh_node_mark_update(nodes[i]);
1388  }
1389  sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, false);
1390 
1391  if (ss->deform_modifiers_active || ss->shapekey_active) {
1392  SCULPT_flush_stroke_deform(sd, ob, true);
1393  }
1397  MEM_freeN(nodes);
1398 }
1399 
1401 {
1403  SculptSession *ss = ob->sculpt;
1405 
1406  const int mode = RNA_enum_get(op->ptr, "mode");
1407  const bool modify_hidden = RNA_boolean_get(op->ptr, "modify_hidden");
1408 
1409  if (!sculpt_face_set_edit_is_operation_valid(ss, mode, modify_hidden)) {
1410  return OPERATOR_CANCELLED;
1411  }
1412 
1413  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
1414 
1415  /* Update the current active Face Set and Vertex as the operator can be used directly from the
1416  * tool without brush cursor. */
1418  const float mouse[2] = {event->mval[0], event->mval[1]};
1419  if (!SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false)) {
1420  /* The cursor is not over the mesh. Cancel to avoid editing the last updated Face Set ID. */
1421  return OPERATOR_CANCELLED;
1422  }
1423  const int active_face_set = SCULPT_active_face_set_get(ss);
1424 
1425  switch (mode) {
1427  sculpt_face_set_edit_modify_geometry(C, ob, active_face_set, mode, modify_hidden);
1428  break;
1431  sculpt_face_set_edit_modify_face_sets(ob, active_face_set, mode, modify_hidden);
1432  break;
1435  sculpt_face_set_edit_modify_coordinates(C, ob, active_face_set, mode);
1436  break;
1437  }
1438 
1440 
1441  return OPERATOR_FINISHED;
1442 }
1443 
1445 {
1446  /* Identifiers. */
1447  ot->name = "Edit Face Set";
1448  ot->idname = "SCULPT_OT_face_set_edit";
1449  ot->description = "Edits the current active Face Set";
1450 
1451  /* Api callbacks. */
1454 
1456 
1457  RNA_def_enum(
1460  "modify_hidden",
1461  true,
1462  "Modify Hidden",
1463  "Apply the edit operation to hidden Face Sets");
1464 }
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1200
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
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.c:1271
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)
Definition: mesh_runtime.c:251
void BKE_mesh_flush_hidden_from_verts(struct Mesh *me)
void BKE_mesh_prefair_and_fair_vertices(struct Mesh *mesh, struct MVert *deform_mverts, bool *affect_vertices, const eMeshFairingDepth depth)
Definition: mesh_fair.cc:486
@ MESH_FAIRING_DEPTH_POSITION
Definition: BKE_mesh_fair.h:37
@ MESH_FAIRING_DEPTH_TANGENCY
Definition: BKE_mesh_fair.h:38
@ 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 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
A BVH for high poly meshes.
void BKE_pbvh_node_mark_update(PBVHNode *node)
Definition: pbvh.c:1732
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode)
Definition: BKE_pbvh.h:384
void BKE_pbvh_node_mark_update_visibility(PBVHNode *node)
Definition: pbvh.c:1748
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1661
void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default)
Definition: pbvh.c:2680
#define BKE_pbvh_vertex_iter_end
Definition: BKE_pbvh.h:457
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:335
@ 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_update_vertex_data(PBVH *pbvh, int flags)
Definition: pbvh.c:1432
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
@ PBVH_UpdateVisibility
Definition: BKE_pbvh.h:72
#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
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
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
BLI_INLINE float BLI_hash_int_01(unsigned int k)
Definition: BLI_hash.h:108
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:732
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(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
int BLI_task_parallel_thread_id(const TaskParallelTLS *tls)
#define UNUSED(x)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ CD_FACEMAP
@ CD_SCULPT_FACE_SETS
@ CD_BWEIGHT
@ ME_VERT_PBVH_UPDATE
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:1591
void ED_sculpt_undo_geometry_end(struct Object *ob)
Definition: sculpt_undo.c:1597
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#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_DATA
Definition: WM_types.h:408
#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:282
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#define BM_elem_flag_set(ele, hflag, val)
Definition: bmesh_inline.h:30
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
float BM_elem_float_data_get(CustomData *cd, void *element, int type)
#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.c:307
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
BMesh Make Mesh.
Definition: bmesh_mesh.c:157
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2276
void BM_mesh_elem_table_init(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2352
BLI_INLINE BMFace * BM_face_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:110
#define BMALLOC_TEMPLATE_FROM_ME(...)
Definition: bmesh_mesh.h:163
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
Mesh -> BMesh.
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
#define fabsf(x)
#define sqrtf(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_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
ThreadQueue * queue
all scheduled work for the cpu
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6355
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_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:3825
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_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
int SCULPT_vertex_count_get(SculptSession *ss)
Definition: sculpt.c:120
void SCULPT_boundary_info_ensure(Object *object)
Definition: sculpt.c:9039
bool SCULPT_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mouse[2], bool use_sampled_normal)
Definition: sculpt.c:7452
void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible)
Definition: sculpt.c:382
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
void SCULPT_relax_vertex(SculptSession *ss, PBVHVertexIter *vd, float factor, bool filter_boundary_face_sets, float *r_final_pos)
Definition: sculpt.c:3506
SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss, SculptBrushTest *test, char falloff_shape)
Definition: sculpt.c:1770
void SCULPT_vertex_face_set_set(SculptSession *ss, int index, int face_set)
Definition: sculpt.c:489
const float * SCULPT_active_vertex_co_get(SculptSession *ss)
Definition: sculpt.c:285
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_face_sets_visibility_all_set(SculptSession *ss, bool visible)
Definition: sculpt.c:418
void SCULPT_face_sets_visibility_invert(SculptSession *ss)
Definition: sculpt.c:404
void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
Definition: sculpt.c:7759
bool SCULPT_vertex_is_boundary(const SculptSession *ss, const int index)
Definition: sculpt.c:868
bool SCULPT_mode_poll(bContext *C)
Definition: sculpt.c:6601
float SCULPT_brush_strength_factor(SculptSession *ss, const Brush *br, const float brush_point[3], const float len, const short vno[3], const float fno[3], const float mask, const int vertex_index, const int thread_id)
Definition: sculpt.c:2463
float SCULPT_vertex_mask_get(SculptSession *ss, int index)
Definition: sculpt.c:254
int SCULPT_face_set_next_available_get(SculptSession *ss)
Definition: sculpt.c:700
void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
Definition: sculpt.c:6340
MVert * SCULPT_mesh_deformed_mverts_get(SculptSession *ss)
Definition: sculpt.c:295
int SCULPT_active_face_set_get(SculptSession *ss)
Definition: sculpt.c:331
void SCULPT_visibility_sync_all_face_sets_to_vertices(Object *ob)
Definition: sculpt.c:563
void SCULPT_tag_update_overlays(bContext *C)
Definition: sculpt.c:1066
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:1383
bool(* SculptBrushTestFn)(SculptBrushTest *test, const float co[3])
@ SCULPT_UPDATE_COORDS
Definition: sculpt_intern.h:58
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
@ SCULPT_UNDO_FACE_SETS
@ SCULPT_UNDO_COORDS
short mat_nr
Definition: bmesh_class.h:281
float no[3]
Definition: bmesh_class.h:280
CustomData edata
Definition: bmesh_class.h:337
CustomData pdata
Definition: bmesh_class.h:337
struct CurveMapping * curve
unsigned int v
struct MLoop * mloop
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:372
short * no
Definition: BKE_pbvh.h:375
float * co
Definition: BKE_pbvh.h:374
float * fno
Definition: BKE_pbvh.h:376
float * mask
Definition: BKE_pbvh.h:377
int * face_sets
Definition: BKE_paint.h:490
struct KeyBlock * shapekey_active
Definition: BKE_paint.h:468
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 StrokeCache * cache
Definition: BKE_paint.h:518
struct PBVH * pbvh
Definition: BKE_paint.h:504
bool deform_modifiers_active
Definition: BKE_paint.h:509
Paint paint
struct UnifiedPaintSettings unified_paint_settings
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
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
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
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3156