[Bf-blender-cvs] [9c30155c47f] sculpt-dev: Sculpt: fix drag-dot/anchored for face sets

Joseph Eagar noreply at git.blender.org
Thu Sep 30 10:36:37 CEST 2021


Commit: 9c30155c47f51bb796a305b633bdcae87856b0ef
Author: Joseph Eagar
Date:   Thu Sep 30 01:36:08 2021 -0700
Branches: sculpt-dev
https://developer.blender.org/rB9c30155c47f51bb796a305b633bdcae87856b0ef

Sculpt: fix drag-dot/anchored for face sets

* Added an API for original face sets
  based on the SculptCustomLayer API.

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

M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/BKE_pbvh.h
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_intern.h

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

diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 63d0357de49..31aa0b3d2b5 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -567,6 +567,7 @@ enum {
   SCULPT_SCL_PERS_DISP,
   SCULPT_SCL_LAYER_DISP,
   SCULPT_SCL_LAYER_STROKE_ID,
+  SCULPT_SCL_ORIG_FSETS,
   SCULPT_SCL_LAYER_MAX
 };
 
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 6db155e03f1..f4cb0dac6ed 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -38,6 +38,17 @@ extern "C" {
 // experimental feature to detect quad diagonals and mark (but not dissolve) them
 //#define SCULPT_DIAGONAL_EDGE_MARKS
 
+/*
+   These structs represent logical verts/edges/faces.
+   for PBVH_GRIDS and PBVH_FACES they store integer
+   offsets, PBVH_BMESH stores pointers.
+
+   The idea is to enforce stronger type checking by encapsulating
+   intptr_t's in structs.*/
+typedef struct SculptElemRef {
+  intptr_t i;
+} SculptElemRef;
+
 typedef struct SculptVertRef {
   intptr_t i;
 } SculptVertRef;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index f8f44cc54a8..c15ec5340d6 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -2959,11 +2959,18 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
 
   SCULPT_orig_vert_data_unode_init(&orig_data, data->ob, unode);
 
+  bool modified = false;
+
   BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
     SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
 
     if (orig_data.unode->type == SCULPT_UNDO_COORDS) {
+      if (len_squared_v3v3(vd.co, orig_data.co) > FLT_EPSILON) {
+        modified = true;
+      }
+
       copy_v3_v3(vd.co, orig_data.co);
+
       if (vd.no) {
         copy_v3_v3_short(vd.no, orig_data.no);
       }
@@ -2972,9 +2979,17 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
       }
     }
     else if (orig_data.unode->type == SCULPT_UNDO_MASK) {
+      if ((*vd.mask - orig_data.mask) * (*vd.mask - orig_data.mask) > FLT_EPSILON) {
+        modified = true;
+      }
+
       *vd.mask = orig_data.mask;
     }
     else if (orig_data.unode->type == SCULPT_UNDO_COLOR && vd.col && orig_data.col) {
+      if (len_squared_v4v4(vd.col, orig_data.col) > FLT_EPSILON) {
+        modified = true;
+      }
+
       copy_v4_v4(vd.col, orig_data.col);
     }
 
@@ -2984,7 +2999,9 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
   }
   BKE_pbvh_vertex_iter_end;
 
-  BKE_pbvh_node_mark_update(data->nodes[n]);
+  if (modified) {
+    BKE_pbvh_node_mark_update(data->nodes[n]);
+  }
 }
 
 static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
@@ -2997,11 +3014,6 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
 
   BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
 
-  /**
-   * Disable multi-threading when dynamic-topology is enabled. Otherwise,
-   * new entries might be inserted by #SCULPT_undo_push_node() into the #GHash
-   * used internally by #BM_log_original_vert_co() by a different thread. See T33787.
-   */
   SculptThreadedTaskData data = {
       .sd = sd,
       .ob = ob,
@@ -3010,7 +3022,7 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
   };
 
   TaskParallelSettings settings;
-  BKE_pbvh_parallel_range_settings(&settings, true && !ss->bm, totnode);
+  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
   BLI_task_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings);
 
   BKE_pbvh_node_color_buffer_free(ss->pbvh);
@@ -3784,10 +3796,10 @@ static void calc_area_normal_and_center(
  * values pull vertices, negative values push. Uses tablet pressure and a
  * special multiplier found experimentally to scale the strength factor.
  */
-ATTR_NO_OPT static float brush_strength(const Sculpt *sd,
-                                        const StrokeCache *cache,
-                                        const float feather,
-                                        const UnifiedPaintSettings *ups)
+static float brush_strength(const Sculpt *sd,
+                            const StrokeCache *cache,
+                            const float feather,
+                            const UnifiedPaintSettings *ups)
 {
   const Scene *scene = cache->vc->scene;
   const Brush *brush = cache->brush;  // BKE_paint_brush((Paint *)&sd->paint);
@@ -8784,8 +8796,20 @@ void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings
    * Check that original data is for anchored and drag dot modes
    */
   if (brush->flag & (BRUSH_ANCHORED | BRUSH_DRAG_DOT)) {
+    if (SCULPT_stroke_is_first_brush_step(ss->cache) &&
+        brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) {
+
+      SCULPT_face_ensure_original(ss);
+
+      for (int i = 0; i < ss->totfaces; i++) {
+        SculptFaceRef face = BKE_pbvh_table_index_to_face(ss->pbvh, i);
+        SCULPT_face_check_origdata(ss, face);
+      }
+    }
+
     for (int i = 0; i < totnode; i++) {
       PBVHVertexIter vd;
+
       BKE_pbvh_vertex_iter_begin (ss->pbvh, nodes[i], vd, PBVH_ITER_UNIQUE) {
         SCULPT_vertex_check_origdata(ss, vd.vertex);
       }
@@ -11421,13 +11445,11 @@ static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
        BKE_brush_use_size_pressure(brush)) ||
       (brush->flag & BRUSH_DRAG_DOT)) {
 
-    if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
-      SculptUndoNode *unode = SCULPT_undo_get_first_node();
-      if (unode && unode->type == SCULPT_UNDO_FACE_SETS) {
-        for (int i = 0; i < ss->totfaces; i++) {
-          ss->face_sets[i] = unode->face_sets[i];
-        }
-      }
+    for (int i = 0; i < ss->totfaces; i++) {
+      SculptFaceRef face = BKE_pbvh_table_index_to_face(ss->pbvh, i);
+      int origf = SCULPT_face_set_original_get(ss, face);
+
+      SCULPT_face_set_set(ss, face, origf);
     }
 
     paint_mesh_restore_co(sd, ob);
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c
index 53ac6793f3c..85a8eccf11a 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.c
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c
@@ -127,6 +127,57 @@ int SCULPT_face_set_set(SculptSession *ss, SculptFaceRef face, int fset)
   return ret;
 }
 
+const char orig_faceset_attr_name[] = "_sculpt_original_fsets";
+
+void SCULPT_face_check_origdata(SculptSession *ss, SculptFaceRef face)
+{
+  if (!ss->custom_layers[SCULPT_SCL_ORIG_FSETS]) {
+    return;
+  }
+
+  short *s = (short *)SCULPT_temp_cdata_get_f(face, ss->custom_layers[SCULPT_SCL_ORIG_FSETS]);
+
+  // pack ss->stroke_id in higher 16 bits
+  if (s[1] != ss->stroke_id) {
+    s[0] = SCULPT_face_set_get(ss, face);
+    s[1] = ss->stroke_id;
+  }
+}
+
+int SCULPT_face_set_original_get(SculptSession *ss, SculptFaceRef face)
+{
+  if (!ss->custom_layers[SCULPT_SCL_ORIG_FSETS]) {
+    return SCULPT_face_set_get(ss, face);
+  }
+
+  short *s = (short *)SCULPT_temp_cdata_get_f(face, ss->custom_layers[SCULPT_SCL_ORIG_FSETS]);
+
+  if (s[1] != ss->stroke_id) {
+    s[0] = SCULPT_face_set_get(ss, face);
+    s[1] = ss->stroke_id;
+  }
+
+  return s[0];
+}
+
+void SCULPT_face_ensure_original(SculptSession *ss)
+{
+  if (ss->custom_layers[SCULPT_SCL_ORIG_FSETS]) {
+    return;
+  }
+
+  SculptCustomLayer *scl = MEM_callocN(sizeof(*scl), "orig fset scl");
+
+  SCULPT_temp_customlayer_get(ss,
+                              ATTR_DOMAIN_FACE,
+                              CD_PROP_INT32,
+                              "orig_faceset_attr_name",
+                              scl,
+                              &((SculptLayerParams){.permanent = false, .simple_array = false}));
+
+  ss->custom_layers[SCULPT_SCL_ORIG_FSETS] = scl;
+}
+
 int SCULPT_face_set_flag_get(SculptSession *ss, SculptFaceRef face, char flag)
 {
   if (ss->bm) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index cbf2cb6b3b3..600cc8e3cc9 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -336,6 +336,10 @@ bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, SculptVertRef ind
 void SCULPT_face_sets_visibility_invert(SculptSession *ss);
 void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible);
 
+void SCULPT_face_ensure_original(SculptSession *ss);
+int SCULPT_face_set_original_get(SculptSession *ss, SculptFaceRef face);
+void SCULPT_face_check_origdata(SculptSession *ss, SculptFaceRef face);
+
 int SCULPT_face_set_get(SculptSession *ss, SculptFaceRef face);
 
 // returns previous face set
@@ -1800,7 +1804,6 @@ int SCULPT_get_symmetry_pass(const SculptSession *ss);
 void SCULPT_on_sculptsession_bmesh_free(SculptSession *ss);
 void SCULPT_reorder_bmesh(SculptSession *ss);
 
-// TODO: support faces
 static inline void *SCULPT_temp_cdata_get(SculptVertRef vertex, SculptCustomLayer *scl)
 {
   if (scl->data) {
@@ -1808,14 +1811,36 @@ static inline void *SCULPT_temp_cdata_get(SculptVertRef vertex, SculptCustomLaye
     int idx = (int)vertex.i;
 
     if (scl->from_bmesh) {
-      BMVert *v = (BMVert *)vertex.i;
+      BMElem *v = (BMElem *)vertex.i;
+      idx = v->head.index;
+    }
+
+    return p + scl->elemsize * (int)vertex.i;
+  }
+  else {
+    BMElem *v = (BMElem *)vertex.i;
+    return BM_ELEM_CD_GET_VOID_P(v, scl->cd_offset);
+  }
+
+  return NULL;
+}
+
+// arg, duplicate functions!
+static inline void *SCULPT_temp_cdata_get_f(SculptFaceRef vertex, SculptCustomLayer *scl)
+{
+  if (scl->data) {
+    char *p = (char *)scl->data;
+    int idx = (int)vertex.i;
+
+    if (scl->from_bmesh) {
+      BMElem *v = (BMElem *)vertex.i;
       idx = v->head.index;
     }
 
     return p + scl->elemsize * (int)vertex.i;
   }
   else {
-    BMVert *v = (BMVert *)vertex.i;
+    BMElem *v = (BMElem *)vertex.i;
     return BM_ELEM_CD_GET_VOID_P(v, scl->cd_offset);
   }



More information about the Bf-blender-cvs mailing list