[Bf-blender-cvs] [ee23f0f3fb5] master: Sculpt: Separate hide status from face sets, use generic attribute

Hans Goudey noreply at git.blender.org
Wed Sep 14 21:42:06 CEST 2022


Commit: ee23f0f3fb58ce569947171d8f9dff97ec564c27
Author: Hans Goudey
Date:   Wed Sep 14 14:33:55 2022 -0500
Branches: master
https://developer.blender.org/rBee23f0f3fb58ce569947171d8f9dff97ec564c27

Sculpt: Separate hide status from face sets, use generic attribute

Whether faces are hidden and face sets are orthogonal concepts, but
currently sculpt mode stores them together in the face set array.
This means that if anything is hidden, there must be face sets,
and if there are face sets, we have to keep track of what is hidden.
In other words, it adds a bunch of redundant work and state tracking.

On the user level it's nice that face sets and hiding are consistent,
but we don't need to store them together to accomplish that.

This commit uses the `".hide_poly"` attribute from rB2480b55f216c to
read and change hiding in sculpt mode. Face sets don't need to be
negative anymore, and a bunch of "face set <-> hide status" conversion
can be removed. Plus some other benefits:
 - We don't need to allocate either array quite as much.
 - The hide status can be read from 1/4 the memory as face sets.
 - Updates when entering or exiting sculpt mode can be removed.
 - More opportunities for early-outs when nothing is hidden.
 - Separating concerns makes sculpt code more obvious.
 - It will be easier to convert face sets into a generic int attribute.

 Differential Revision: https://developer.blender.org/D15950

===================================================================

M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/BKE_subdiv_ccg.h
M	source/blender/blenkernel/intern/paint.cc
M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/blenkernel/intern/subdiv_ccg.c
M	source/blender/blenloader/intern/versioning_300.c
M	source/blender/editors/mesh/meshtools.cc
M	source/blender/editors/object/object_remesh.cc
M	source/blender/editors/sculpt_paint/paint_hide.c
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_face_set.c
M	source/blender/editors/sculpt_paint/sculpt_geodesic.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h
M	source/blender/editors/sculpt_paint/sculpt_ops.c
M	source/blender/editors/sculpt_paint/sculpt_undo.c
M	source/blender/gpu/intern/gpu_buffers.c
M	source/blender/makesrna/intern/rna_object.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index eef91bacc2f..774765c3ca1 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -529,13 +529,16 @@ typedef struct SculptSession {
   /* Mesh Face Sets */
   /* Total number of polys of the base mesh. */
   int totfaces;
-  /* Face sets store its visibility in the sign of the integer, using the absolute value as the
-   * Face Set ID. Positive IDs are visible, negative IDs are hidden.
-   * The 0 ID is not used by the tools or the visibility system, it is just used when creating new
+  /* The 0 ID is not used by the tools or the visibility system, it is just used when creating new
    * geometry (the trim tool, for example) to detect which geometry was just added, so it can be
    * assigned a valid Face Set after creation. Tools are not intended to run with Face Sets IDs set
    * to 0. */
   int *face_sets;
+  /**
+   * A reference to the ".hide_poly" attribute, to store whether (base) polygons are hidden.
+   * May be null.
+   */
+  bool *hide_poly;
 
   /* BMesh for dynamic topology sculpting */
   struct BMesh *bm;
@@ -697,6 +700,12 @@ void BKE_sculpt_update_object_after_eval(struct Depsgraph *depsgraph, struct Obj
 struct MultiresModifierData *BKE_sculpt_multires_active(const struct Scene *scene,
                                                         struct Object *ob);
 int *BKE_sculpt_face_sets_ensure(struct Mesh *mesh);
+/**
+ * Create the attribute used to store face visibility and retrieve its data.
+ * Note that changes to the face visibility have to be propagated to other domains
+ * (see #SCULPT_visibility_sync_all_from_faces).
+ */
+bool *BKE_sculpt_hide_poly_ensure(struct Mesh *mesh);
 int BKE_sculpt_mask_layers_ensure(struct Object *ob, struct MultiresModifierData *mmd);
 void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene);
 
@@ -704,31 +713,7 @@ struct PBVH *BKE_sculpt_object_pbvh_ensure(struct Depsgraph *depsgraph, struct O
 
 void BKE_sculpt_bvh_update_from_ccg(struct PBVH *pbvh, struct SubdivCCG *subdiv_ccg);
 
-/**
- * This ensure that all elements in the mesh (both vertices and grids) have their visibility
- * updated according to the face sets.
- */
-void BKE_sculpt_sync_face_set_visibility(struct Mesh *mesh, struct SubdivCCG *subdiv_ccg);
-
-/**
- * Individual function to sync the Face Set visibility to mesh and grids.
- */
-void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(struct Mesh *mesh);
-void BKE_sculpt_sync_face_sets_visibility_to_grids(struct Mesh *mesh,
-                                                   struct SubdivCCG *subdiv_ccg);
-
-/**
- * If a face set layer exists, initialize its visibility (sign) from the mesh's hidden values.
- */
-void BKE_sculpt_face_sets_update_from_base_mesh_visibility(struct Mesh *mesh);
-
-/**
- * Makes sculpt data consistent with other data on the mesh.
- *
- * \note IDs are expected to be original ones here, and calling code should ensure it updates its
- * depsgraph properly after calling this function if it needs up-to-date evaluated data.
- */
-void BKE_sculpt_ensure_orig_mesh_data(struct Object *object);
+void BKE_sculpt_sync_face_visibility_to_grids(struct Mesh *mesh, struct SubdivCCG *subdiv_ccg);
 
 /**
  * Test if PBVH can be used directly for drawing, which is faster than
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 6a194698bd8..c32645e9ce7 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -380,8 +380,6 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
                               int totgrid,
                               int gridsize);
 
-void BKE_pbvh_sync_face_sets_to_grids(PBVH *pbvh);
-
 /**
  * Multi-res level, only valid for type == #PBVH_GRIDS.
  */
diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h
index b30b707759c..ced7ff2aa71 100644
--- a/source/blender/blenkernel/BKE_subdiv_ccg.h
+++ b/source/blender/blenkernel/BKE_subdiv_ccg.h
@@ -325,6 +325,7 @@ const int *BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG *subdiv_ccg);
 const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG *subdiv_ccg);
 
 void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG *subdiv_ccg, int grid_index);
+void BKE_subdiv_ccg_grid_hidden_free(SubdivCCG *subdiv_ccg, int grid_index);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc
index 7ad9fd3a7c3..ea1bd3c1cc3 100644
--- a/source/blender/blenkernel/intern/paint.cc
+++ b/source/blender/blenkernel/intern/paint.cc
@@ -1712,6 +1712,8 @@ static void sculpt_update_object(
     ss->face_sets = nullptr;
   }
 
+  ss->hide_poly = (bool *)CustomData_get_layer_named(&me->pdata, CD_PROP_BOOL, ".hide_poly");
+
   ss->subdiv_ccg = me_eval->runtime.subdiv_ccg;
 
   PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
@@ -1720,6 +1722,7 @@ static void sculpt_update_object(
 
   BKE_pbvh_subdiv_cgg_set(ss->pbvh, ss->subdiv_ccg);
   BKE_pbvh_face_sets_set(ss->pbvh, ss->face_sets);
+  BKE_pbvh_update_hide_attributes_from_mesh(ss->pbvh);
 
   BKE_pbvh_face_sets_color_set(ss->pbvh, me->face_sets_color_seed, me->face_sets_color_default);
 
@@ -1940,29 +1943,21 @@ int *BKE_sculpt_face_sets_ensure(Mesh *mesh)
           &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CONSTRUCT, nullptr, mesh->totpoly)),
       mesh->totpoly};
 
-  /* Initialize the new face sets with a default valid visible ID and set the default
-   * color to render it white. */
-  if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
-    face_sets.fill(1);
-  }
-  else {
-    const int face_sets_default_visible_id = 1;
-    const int face_sets_default_hidden_id = -2;
-
-    const VArraySpan<bool> hide_poly_span{hide_poly};
-    for (const int i : face_sets.index_range()) {
-      /* Assign a new hidden ID to hidden faces. This way we get at initial split in two Face Sets
-       * between hidden and visible faces based on the previous mesh visibly from other mode that
-       * can be useful in some cases. */
-      face_sets[i] = hide_poly_span[i] ? face_sets_default_hidden_id :
-                                         face_sets_default_visible_id;
-    }
-  }
-
+  face_sets.fill(1);
   mesh->face_sets_color_default = 1;
   return face_sets.data();
 }
 
+bool *BKE_sculpt_hide_poly_ensure(Mesh *mesh)
+{
+  if (bool *hide_poly = static_cast<bool *>(
+          CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly"))) {
+    return hide_poly;
+  }
+  return static_cast<bool *>(CustomData_add_layer_named(
+      &mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, mesh->totpoly, ".hide_poly"));
+}
+
 int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
 {
   Mesh *me = static_cast<Mesh *>(ob->data);
@@ -2082,11 +2077,11 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc
   return deformed;
 }
 
-void BKE_sculpt_face_sets_update_from_base_mesh_visibility(Mesh *mesh)
+void BKE_sculpt_sync_face_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg)
 {
   using namespace blender;
   using namespace blender::bke;
-  if (!CustomData_has_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)) {
+  if (!subdiv_ccg) {
     return;
   }
 
@@ -2094,70 +2089,19 @@ void BKE_sculpt_face_sets_update_from_base_mesh_visibility(Mesh *mesh)
   const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
       ".hide_poly", ATTR_DOMAIN_FACE, false);
   if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
+    /* Nothing is hidden, so we can just remove all visibility bitmaps. */
+    for (const int i : hide_poly.index_range()) {
+      BKE_subdiv_ccg_grid_hidden_free(subdiv_ccg, i);
+    }
     return;
   }
 
-  MutableSpan<int> face_sets{
-      static_cast<int *>(CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)), mesh->totpoly};
-
-  for (const int i : hide_poly.index_range()) {
-    face_sets[i] = hide_poly[i] ? -std::abs(face_sets[i]) : std::abs(face_sets[i]);
-  }
-}
-
-static void set_hide_poly_from_face_sets(Mesh &mesh)
-{
-  using namespace blender;
-  using namespace blender::bke;
-  if (!CustomData_has_layer(&mesh.pdata, CD_SCULPT_FACE_SETS)) {
-    return;
-  }
-
-  const Span<int> face_sets{
-      static_cast<const int *>(CustomData_get_layer(&mesh.pdata, CD_SCULPT_FACE_SETS)),
-      mesh.totpoly};
-
-  MutableAttributeAccessor attributes = mesh.attributes_for_write();
-  if (std::all_of(
-          face_sets.begin(), face_sets.end(), [&](const int value) { return value > 0; })) {
-    attributes.remove(".hide_poly");
-    return;
-  }
-
-  SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_only_span<bool>(
-      ".hide_poly", ATTR_DOMAIN_FACE);
-  if (!hide_poly) {
-    return;
-  }
-  for (const int i : hide_poly.span.index_range()) {
-    hide_poly.span[i] = face_sets[i] < 0;
-  }
-  hide_poly.finish();
-}
-
-void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh)
-{
-  set_hide_poly_from_face_sets(*mesh);
-  BKE_mesh_flush_hidden_from_polys(mesh);
-}
-
-void BKE_sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg)
-{
-  const int *face_sets = static_cast<const int *>(
-      CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS));
-  if (!face_sets) {
-    return;
-  }
-
-  if (!subdiv_ccg) {
-    return;
-  }
-
+  const VArraySpan<bool> hide_poly_span(hide_poly);
   CCGKey key;
   BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
   for (int i = 0; i < mesh->totloop; i++) {
     const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, i);
-    const bool is_hidden = (face_sets[face_index] < 0);
+    const bool is_hidden = hide_poly_span[face_index];
 
     /* Avoid creating and modifying the grid_hidden bitmap if the base mesh face is visible and
      * there is not bitmap for the grid. This is because missing grid_hidden implies grid is fully
@@ -2173,41 +2117,6 @@ void BKE_sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv
   }
 }
 
-void BKE_sculpt_sync_face_set_visibility(Mesh *mesh, SubdivCCG *subdiv_ccg)
-{
-  BKE_sc

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list