[Bf-blender-cvs] [17d4c7abb12] temp_bmesh_multires: Sculpt dyntopo:

Joseph Eagar noreply at git.blender.org
Fri Jun 25 08:54:08 CEST 2021


Commit: 17d4c7abb12f0f5fc6646822afecb476864859c5
Author: Joseph Eagar
Date:   Thu Jun 24 23:50:49 2021 -0700
Branches: temp_bmesh_multires
https://developer.blender.org/rB17d4c7abb12f0f5fc6646822afecb476864859c5

Sculpt dyntopo:

* Got automasking to work with dyntopo properly.
  - AutomaskingCache->factor
    has been replaced with the new temp layer API (which works for all
    PBVH modes).
  - AutomaskingCache->factor is, however, only initialized for
    topology and face set boundary modes (if DynTopo is enabled)
    since it's probably better to calculate the rest dynamically
    in that case.
* Fixed stats bug

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

M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/intern/pbvh_bmesh.c
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_automasking.c
M	source/blender/editors/sculpt_paint/sculpt_detail.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h
M	source/blender/editors/space_info/info_stats.c

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

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 9bfa706bc27..854c1559617 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -391,6 +391,9 @@ typedef enum {
   PBVH_Collapse = 2,
   PBVH_Cleanup = 4,  // dissolve verts surrounded by either 3 or 4 triangles then triangulate
 } PBVHTopologyUpdateMode;
+
+typedef float (*DyntopoMaskCB)(SculptVertRef vertex, void *userdata);
+
 bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
                                     PBVHTopologyUpdateMode mode,
                                     const float center[3],
@@ -399,7 +402,9 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
                                     const bool use_frontface,
                                     const bool use_projected,
                                     int symaxis,
-                                    bool updatePBVH);
+                                    bool updatePBVH,
+                                    DyntopoMaskCB mask_cb,
+                                    void *mask_cb_data);
 
 bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
                                           bool (*searchcb)(PBVHNode *node, void *data),
@@ -412,7 +417,9 @@ bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
                                           const bool use_frontface,
                                           const bool use_projected,
                                           int sym_axis,
-                                          bool updatePBVH);
+                                          bool updatePBVH,
+                                          DyntopoMaskCB mask_cb,
+                                          void *mask_cb_data);
 /* Node Access */
 
 void BKE_pbvh_node_mark_update(PBVHNode *node);
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 8d5ece6e2d9..04c5b0c2e4a 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -1349,6 +1349,8 @@ typedef struct {
   EdgeQueue *q;
   BLI_mempool *pool;
   BMesh *bm;
+  DyntopoMaskCB mask_cb;
+  void *mask_cb_data;
   int cd_dyn_vert;
   int cd_vert_mask_offset;
   int cd_vert_node_offset;
@@ -1359,6 +1361,21 @@ typedef struct {
   float totedge;
 } EdgeQueueContext;
 
+BLI_INLINE float maskcb_get(EdgeQueueContext *eq_ctx, BMEdge *e)
+{
+  if (eq_ctx->mask_cb) {
+    SculptVertRef sv1 = {(intptr_t)e->v1};
+    SculptVertRef sv2 = {(intptr_t)e->v2};
+
+    float w1 = eq_ctx->mask_cb(sv1, eq_ctx->mask_cb_data);
+    float w2 = eq_ctx->mask_cb(sv2, eq_ctx->mask_cb_data);
+
+    return (w1 + w2) * 0.5f;
+  }
+
+  return 1.0f;
+}
+
 BLI_INLINE float calc_weighted_edge_split(EdgeQueueContext *eq_ctx, BMVert *v1, BMVert *v2)
 {
 #ifdef FANCY_EDGE_WEIGHTS
@@ -1480,10 +1497,6 @@ static float dist_to_tri_sphere_simple(
 
 static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
 {
-  float c[3];
-  float v1[3], v2[3], v3[3], co[3];
-  const float mul = 1.0f;
-
   BMLoop *l = f->l_first;
 
   /* Check if triangle intersects the sphere */
@@ -1551,29 +1564,14 @@ static bool edge_queue_vert_in_circle(const EdgeQueue *q, BMVert *v)
   return len_squared_v3v3(q->center_proj, c) <= q->radius_squared;
 }
 
-/* Return true if the vertex mask is less than 1.0, false otherwise */
-static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v)
-{
-  return DYNTOPO_MASK(eq_ctx->cd_dyn_vert, v) < 1.0f;
-}
-
 static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, float priority)
 {
   void **elems = eq_ctx->q->elems;
   BLI_array_declare(elems);
   BLI_array_len_set(elems, eq_ctx->q->totelems);
 
-  /* Don't let topology update affect fully masked vertices. This used to
-   * have a 50% mask cutoff, with the reasoning that you can't do a 50%
-   * topology update. But this gives an ugly border in the mesh. The mask
-   * should already make the brush move the vertices only 50%, which means
-   * that topology updates will also happen less frequent, that should be
-   * enough. */
-  if (((eq_ctx->cd_vert_mask_offset == -1) ||
-       (check_mask(eq_ctx, e->v1) || check_mask(eq_ctx, e->v2))) &&
-      !(BM_elem_flag_test_bool(e->v1, BM_ELEM_HIDDEN) ||
-        BM_elem_flag_test_bool(e->v2, BM_ELEM_HIDDEN))) {
-
+  if (eq_ctx->cd_vert_mask_offset == -1 ||
+      !((e->v1->head.hflag | e->v2->head.hflag) & BM_ELEM_HIDDEN)) {
     float dis = len_v3v3(e->v1->co, e->v2->co);
     eq_ctx->avg_elen += dis;
     eq_ctx->max_elen = MAX2(eq_ctx->max_elen, dis);
@@ -1604,7 +1602,9 @@ static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx, BMEdge *e)
   if (EDGE_QUEUE_TEST(e) == false)
 #endif
   {
-    const float len_sq = BM_edge_calc_length_squared(e);
+    const float w = maskcb_get(eq_ctx, e);
+    const float len_sq = BM_edge_calc_length_squared(e) * w * w;
+
     if (len_sq > eq_ctx->q->limit_len_squared) {
       edge_queue_insert(eq_ctx, e, -len_sq);
     }
@@ -1652,6 +1652,10 @@ static void long_edge_queue_edge_add_recursive(EdgeQueueContext *eq_ctx,
       BMLoop *l_adjacent[2] = {l_iter->next, l_iter->prev};
       for (int i = 0; i < (int)ARRAY_SIZE(l_adjacent); i++) {
         float len_sq_other = BM_edge_calc_length_squared(l_adjacent[i]->e);
+        float w = maskcb_get(eq_ctx, l_adjacent[i]->e);
+
+        len_sq_other *= w * w;
+
         if (len_sq_other > max_ff(len_sq_cmp, limit_len_sq)) {
           //                  edge_queue_insert(eq_ctx, l_adjacent[i]->e, -len_sq_other);
           long_edge_queue_edge_add_recursive(eq_ctx,
@@ -1696,7 +1700,11 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, BMFace *f, bool i
     BMLoop *l_iter = l_first;
     do {
 #ifdef USE_EDGEQUEUE_EVEN_SUBDIV
-      const float len_sq = BM_edge_calc_length_squared(l_iter->e);
+      float len_sq = BM_edge_calc_length_squared(l_iter->e);
+      float w = maskcb_get(eq_ctx, l_iter->e);
+
+      len_sq *= w * w;
+
       if (len_sq > eq_ctx->q->limit_len_squared) {
         long_edge_queue_edge_add_recursive(eq_ctx,
                                            l_iter->radial_next,
@@ -1829,12 +1837,16 @@ static void long_edge_queue_edge_add_recursive_2(EdgeQueueThreadData *tdata,
     do {
       BMLoop *l_adjacent[2] = {l_iter->next, l_iter->prev};
       for (int i = 0; i < (int)ARRAY_SIZE(l_adjacent); i++) {
+        BMEdge *e = l_adjacent[i]->e;
 
         float len_sq_other = calc_weighted_edge_split(
             tdata->eq_ctx, l_adjacent[i]->e->v1, l_adjacent[i]->e->v2);
 
+        float w = maskcb_get(tdata->eq_ctx, e);
+
+        len_sq_other *= w * w;
+
         if (len_sq_other > max_ff(len_sq_cmp, limit_len_sq)) {
-          //                  edge_queue_insert(eq_ctx, l_adjacent[i]->e, -len_sq_other);
           long_edge_queue_edge_add_recursive_2(tdata,
                                                l_adjacent[i]->radial_next,
                                                l_adjacent[i],
@@ -1886,7 +1898,11 @@ void long_edge_queue_task_cb(void *__restrict userdata,
         surface_smooth_v_safe(l_iter->v);
 
 #ifdef USE_EDGEQUEUE_EVEN_SUBDIV
-        const float len_sq = BM_edge_calc_length_squared(l_iter->e);
+        float w = maskcb_get(eq_ctx, l_iter->e);
+        float len_sq = BM_edge_calc_length_squared(l_iter->e);
+
+        len_sq *= w * w;
+
         if (len_sq > eq_ctx->q->limit_len_squared) {
           long_edge_queue_edge_add_recursive_2(
               tdata, l_iter->radial_next, l_iter, len_sq, eq_ctx->q->limit_len, 0);
@@ -1903,9 +1919,9 @@ void long_edge_queue_task_cb(void *__restrict userdata,
   TGSET_ITER_END
 }
 
-void short_edge_queue_task_cb(void *__restrict userdata,
-                              const int n,
-                              const TaskParallelTLS *__restrict tls)
+static void short_edge_queue_task_cb(void *__restrict userdata,
+                                     const int n,
+                                     const TaskParallelTLS *__restrict tls)
 {
   EdgeQueueThreadData *tdata = ((EdgeQueueThreadData *)userdata) + n;
   PBVHNode *node = tdata->node;
@@ -1937,8 +1953,16 @@ void short_edge_queue_task_cb(void *__restrict userdata,
       BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
       BMLoop *l_iter = l_first;
       do {
+        float w = maskcb_get(eq_ctx, l_iter->e);
+
+        if (w == 0.0f) {
+          continue;
+        }
+
 #ifdef USE_EDGEQUEUE_EVEN_SUBDIV
-        const float len_sq = calc_weighted_edge_collapse(eq_ctx, l_iter->e->v1, l_iter->e->v2);
+        float len_sq = calc_weighted_edge_collapse(eq_ctx, l_iter->e->v1, l_iter->e->v2);
+        len_sq /= w * w;
+
         if (len_sq < eq_ctx->q->limit_len_squared) {
           short_edge_queue_edge_add_recursive_2(
               tdata, l_iter->radial_next, l_iter, len_sq, eq_ctx->q->limit_len, 0);
@@ -2047,7 +2071,13 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
     for (int j = 0; j < td->totedge; j++) {
       BMEdge *e = edges[j];
       e->head.hflag &= ~BM_ELEM_TAG;
-      edge_queue_insert(eq_ctx, e, -calc_weighted_edge_split(eq_ctx, e->v1, e->v2));
+
+      float w = -calc_weighted_edge_split(eq_ctx, e->v1, e->v2);
+      float w2 = maskcb_get(eq_ctx, e);
+
+      w *= w2 * w2;
+
+      edge_queue_insert(eq_ctx, e, w);
     }
 
     if (td->edges) {
@@ -2145,8 +2175,18 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
     BMEdge **edges = td->edges;
     for (int j = 0; j < td->totedge; j++) {
       BMEdge *e = edges[j];
+      float w = calc_weighted_edge_collapse(eq_ctx, e->v1, e->v2);
+      float w2 = maskcb_get(eq_ctx, e);
+
+      if (w2 > 0.0f) {
+        w /= w2 * w2;
+      }
+      else {
+        w = 100000.0f;
+      }
+
       e->head.hflag &= ~BM_ELEM_TAG;
-      edge_queue_insert(eq_ctx, e, calc_weighted_edge_collapse(eq_ctx, e->v1, e->v2));
+      edge_queue_insert(eq_ctx, e, w);
     }
 
     if (td->edges) {
@@ -2213,7 +2253,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
 
     float mask_v_new = 0.5f * (mask_v1 + mask_v2);
 
-    BM_ELEM_CD_SET_FLOAT(v_new, eq_ctx->cd_vert_mask_offset, mask_v_new);
+    // BM_ELEM_CD_SET_FLOAT(v_new, eq_ctx->cd_v

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list