[Bf-blender-cvs] [3cae409b24a] temp-texpaint-automasking: temp-texpaint-automasking: Support automasking in new paint

Joseph Eagar noreply at git.blender.org
Mon Jun 27 07:12:41 CEST 2022


Commit: 3cae409b24a9a6b24b783ac9cd2b0c308374e0a1
Author: Joseph Eagar
Date:   Sun Jun 26 22:09:23 2022 -0700
Branches: temp-texpaint-automasking
https://developer.blender.org/rB3cae409b24a9a6b24b783ac9cd2b0c308374e0a1

temp-texpaint-automasking: Support automasking in new paint

* New texture paint now supports automasking.
* Automasking factor cache can now be built incrementally
  by PBVH node.

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

M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/blenkernel/intern/pbvh_intern.h
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_automasking.cc
M	source/blender/editors/sculpt_paint/sculpt_intern.h
M	source/blender/editors/sculpt_paint/sculpt_paint_image.cc

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

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index f517ff3a949..380820030b1 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -79,6 +79,7 @@ typedef enum {
   PBVH_UpdateTopology = 1 << 13,
   PBVH_UpdateColor = 1 << 14,
   PBVH_RebuildPixels = 1 << 15,
+  PBVH_RebuildAutomasking = 1 << 16,
 
 } PBVHNodeFlags;
 
@@ -413,7 +414,7 @@ typedef struct PBVHVertexIter {
   /* mesh */
   struct MVert *mverts;
   float (*vert_normals)[3];
-  int totvert;
+  int totvert, unique_verts;
   const int *vert_indices;
   float *vmask;
 
@@ -587,6 +588,23 @@ void BKE_pbvh_vertex_color_get(const PBVH *pbvh, int vertex, float r_color[4]);
 void BKE_pbvh_ensure_node_loops(PBVH *pbvh);
 bool BKE_pbvh_draw_cache_invalid(const PBVH *pbvh);
 
+void BKE_pbvh_node_automasking_mark(PBVH *pbvh, PBVHNode *node);
+void BKE_pbvh_node_automasking_unmark(PBVH *pbvh, PBVHNode *node);
+bool BKE_pbvh_node_needs_automasking(PBVH *pbvh, PBVHNode *node);
+void BKE_pbvh_node_automasking_mark_all(PBVH *pbvh);
+
+/* XXX Temporary attribute for patch development; remove for final patch! */
+#ifdef __clang__
+#  define ATTR_NO_OPT __attribute__((optnone))
+#elif defined(_MSC_VER)
+#  define ATTR_NO_OPT __pragma(optimize("", off))
+#elif defined(__GNUC__)
+#  define ATTR_NO_OPT __attribute__((optimize("O0")))
+#else
+#  define ATTR_NO_OPT
+#endif
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 3b20bdc826c..88cfa6c5db2 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -3126,6 +3126,9 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
   else {
     vi->totvert = uniq_verts;
   }
+
+  vi->unique_verts = uniq_verts;
+
   vi->vert_indices = vert_indices;
   vi->mverts = verts;
 
@@ -3320,3 +3323,27 @@ void BKE_pbvh_ensure_node_loops(PBVH *pbvh)
 
   MEM_SAFE_FREE(visit);
 }
+
+void BKE_pbvh_node_automasking_mark(PBVH *pbvh, PBVHNode *node)
+{
+  node->flag |= PBVH_RebuildAutomasking;
+}
+
+void BKE_pbvh_node_automasking_unmark(PBVH *pbvh, PBVHNode *node)
+{
+  node->flag &= ~PBVH_RebuildAutomasking;
+}
+
+bool BKE_pbvh_node_needs_automasking(PBVH *pbvh, PBVHNode *node)
+{
+  return node->flag & PBVH_RebuildAutomasking;
+}
+
+void BKE_pbvh_node_automasking_mark_all(PBVH *pbvh)
+{
+  for (int i = 0; i < pbvh->totnode; i++) {
+    if (pbvh->nodes[i].flag & PBVH_Leaf) {
+      pbvh->nodes[i].flag |= PBVH_RebuildAutomasking;
+    }
+  }
+}
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index a4ac2744a73..9f6f02334a2 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -96,7 +96,7 @@ struct PBVHNode {
 
   /* Indicates whether this node is a leaf or not; also used for
    * marking various updates that need to be applied. */
-  PBVHNodeFlags flag : 16;
+  PBVHNodeFlags flag : 32;
 
   /* Used for raycasting: how close bb is to the ray point. */
   float tmin;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 5ea42a5efa5..5e6259e3e07 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1288,7 +1288,10 @@ void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, Scul
   }
 }
 
-void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node, SculptUndoType type)
+void SCULPT_orig_vert_data_init(SculptOrigVertData *data,
+                                Object *ob,
+                                PBVHNode *node,
+                                SculptUndoType type)
 {
   SculptUndoNode *unode;
   unode = SCULPT_undo_push_node(ob, node, type);
@@ -2447,7 +2450,9 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
   avg *= 1.0f - mask;
 
   /* Auto-masking. */
-  avg *= SCULPT_automasking_factor_get(cache->automasking, ss, vertex_index);
+  if (vertex_index != -1) {
+    avg *= SCULPT_automasking_factor_get(cache->automasking, ss, vertex_index);
+  }
 
   return avg;
 }
@@ -4173,6 +4178,7 @@ static void sculpt_update_cache_invariants(
 {
   StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
   UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
+  ToolSettings *tool_settings = CTX_data_tool_settings(C);
   Brush *brush = BKE_paint_brush(&sd->paint);
   ViewContext *vc = paint_stroke_view_context(op->customdata);
   Object *ob = CTX_data_active_object(C);
@@ -4183,6 +4189,8 @@ static void sculpt_update_cache_invariants(
 
   ss->cache = cache;
 
+  cache->use_pixels = sculpt_needs_pbvh_pixels(&tool_settings->paint_mode, brush, ob);
+
   /* Set scaling adjustment. */
   max_scale = 0.0f;
   for (int i = 0; i < 3; i++) {
@@ -5334,6 +5342,11 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
       SCULPT_undo_push_begin(ob, sculpt_tool_name(sd));
     }
 
+    /* Mark all pbvh nodes for update. */
+    if (ss->pbvh) {
+      BKE_pbvh_node_automasking_mark_all(ss->pbvh);
+    }
+
     return true;
   }
   return false;
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.cc b/source/blender/editors/sculpt_paint/sculpt_automasking.cc
index bb101717c9b..4d40f473fd3 100644
--- a/source/blender/editors/sculpt_paint/sculpt_automasking.cc
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.cc
@@ -11,7 +11,10 @@
 #include "BLI_hash.h"
 #include "BLI_index_range.hh"
 #include "BLI_math.h"
+#include "BLI_set.hh"
 #include "BLI_task.h"
+#include "BLI_task.hh"
+#include "BLI_vector.hh"
 
 #include "DNA_brush_types.h"
 #include "DNA_mesh_types.h"
@@ -48,6 +51,8 @@
 #include <cstdlib>
 
 using blender::IndexRange;
+using blender::Set;
+using blender::Vector;
 
 AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss)
 {
@@ -114,18 +119,8 @@ static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush
   return false;
 }
 
-float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert)
+float sculpt_automasking_factor_calc(AutomaskingCache *automasking, SculptSession *ss, int vert)
 {
-  if (!automasking) {
-    return 1.0f;
-  }
-  /* If the cache is initialized with valid info, use the cache. This is used when the
-   * automasking information can't be computed in real time per vertex and needs to be
-   * initialized for the whole mesh when the stroke starts. */
-  if (automasking->factor) {
-    return automasking->factor[vert];
-  }
-
   if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
     if (!SCULPT_vertex_has_face_set(ss, vert, automasking->settings.initial_face_set)) {
       return 0.0f;
@@ -147,6 +142,21 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession
   return 1.0f;
 }
 
+float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert)
+{
+  if (!automasking) {
+    return 1.0f;
+  }
+  /* If the cache is initialized with valid info, use the cache. This is used when the
+   * automasking information can't be computed in real time per vertex and needs to be
+   * initialized for the whole mesh when the stroke starts. */
+  if (automasking->factor) {
+    return automasking->factor[vert];
+  }
+
+  return sculpt_automasking_factor_calc(automasking, ss, vert);
+}
+
 void SCULPT_automasking_cache_free(AutomaskingCache *automasking)
 {
   if (!automasking) {
@@ -335,11 +345,23 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object
   SCULPT_automasking_cache_settings_update(automasking, ss, sd, brush);
   SCULPT_boundary_info_ensure(ob);
 
+  if (!SCULPT_automasking_needs_factors_cache(sd, brush) && ss->cache && ss->cache->use_pixels) {
+    /*
+     * Allocate factor cache but don't initialize it.
+     * Will be filled in by SCULPT_automasking_cache_check.
+     */
+    automasking->factor = (float *)MEM_calloc_arrayN(totvert, sizeof(float), "automask_factor");
+
+    return automasking;
+  }
+
   if (!SCULPT_automasking_needs_factors_cache(sd, brush)) {
     return automasking;
   }
 
+  automasking->has_full_factor_cache = true;
   automasking->factor = (float *)MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor");
+
   for (int i : IndexRange(totvert)) {
     automasking->factor[i] = 1.0f;
   }
@@ -370,3 +392,71 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object
 
   return automasking;
 }
+
+void SCULPT_automasking_cache_check(SculptSession *ss,
+                                    AutomaskingCache *automasking,
+                                    PBVHNode **nodes,
+                                    int totnode)
+{
+  if (!automasking || automasking->has_full_factor_cache) {
+    return;
+  }
+
+  auto cb = [&](PBVHNode *node) {
+    if (!BKE_pbvh_node_needs_automasking(ss->pbvh, node)) {
+      return;
+    }
+
+    BKE_pbvh_node_automasking_unmark(ss->pbvh, node);
+    PBVHVertexIter vi;
+
+    BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vi, PBVH_ITER_ALL) {
+      if (vi.i >= vi.unique_verts) {
+      }
+      else {
+        automasking->factor[vi.index] = SCULPT_automasking_factor_get(
+            automasking, ss, ss->active_face_index);
+      }
+    }
+    BKE_pbvh_vertex_iter_end;
+  };
+
+  Vector<Vector<int>> node_other_verts;
+  node_other_verts.resize(totnode);
+
+  blender::threading::parallel_for(IndexRange(totnode), 2, [&](IndexRange range) {
+    for (int i : range) {
+      PBVHNode *node = nodes[i];
+
+      if (!BKE_pbvh_node_needs_automasking(ss->pbvh, node)) {
+        return;
+      }
+
+      BKE_pbvh_node_automasking_unmark(ss->pbvh, node);
+      PBVHVertexIter vi;
+
+      BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vi, PBVH_ITER_ALL) {
+        if (vi.i >= vi.unique_verts) {
+          node_other_verts[i].append(vi.index);
+        }
+        else {
+          automasking->factor[vi.index] = sculpt_automasking_factor_calc(
+              automasking, ss, vi.index);
+        }
+      }
+      BKE_pbvh_vertex_iter

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list