[Bf-blender-cvs] [bb1096f4756] temp_bmesh_multires: Sculpt dyntopo:

Joseph Eagar noreply at git.blender.org
Thu Sep 9 01:57:06 CEST 2021


Commit: bb1096f4756247a9ed0f7c4c95da0f96ccfdff9f
Author: Joseph Eagar
Date:   Wed Sep 8 15:51:56 2021 -0800
Branches: temp_bmesh_multires
https://developer.blender.org/rBbb1096f4756247a9ed0f7c4c95da0f96ccfdff9f

Sculpt dyntopo:

* Collapse now uses code from decimate to detect
  degenerate cases.
* Remaining, unknown (and rare) degenerate cases
  are now detected (via presence of duplicate verts
  in faces) and fixed.
* DynTopo fills in undo size properly now,
  so undo memory limiting works.

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

M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/blenkernel/intern/brush.c
M	source/blender/blenkernel/intern/dyntopo.c
M	source/blender/blenkernel/intern/paint.c
M	source/blender/bmesh/intern/bmesh_core.c
M	source/blender/bmesh/intern/bmesh_log.c
M	source/blender/bmesh/intern/bmesh_log.h
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_replay.c
M	source/blender/editors/sculpt_paint/sculpt_undo.c
M	source/blender/makesdna/DNA_brush_defaults.h
M	source/blender/makesdna/DNA_brush_enums.h
M	source/blender/makesdna/DNA_brush_types.h
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/intern/rna_brush.c
M	source/blender/makesrna/intern/rna_sculpt_paint.c

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

diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index e362ae31247..27920a9a57a 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -820,6 +820,7 @@ class VIEW3D_PT_sculpt_dyntopo_advanced(Panel, View3DPaintPanel):
         do_prop("detail_percent")
         do_prop("constant_detail")
         do_prop("mode")
+        do_prop("radius_scale")
 
 # TODO, move to space_view3d.py
 class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
@@ -878,6 +879,7 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
         col.prop(sculpt, "use_flat_vcol_shading")
 
         col.prop(sculpt, "dyntopo_spacing")
+        col.prop(sculpt, "dyntopo_radius_scale");
 
 
 class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 0942cc10994..7c27648161e 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -250,6 +250,11 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id)
 {
   Brush *brush = (Brush *)id;
 
+  if (brush->dyntopo.radius_scale == 0.0f) {
+    brush->dyntopo.radius_scale = 1.0f;
+    brush->dyntopo.inherit |= DYNTOPO_INHERIT_RADIUS_SCALE;
+  }
+
   // detect old file data
   if (brush->autosmooth_radius_factor == 0.0f) {
     brush->autosmooth_radius_factor = 1.0f;
@@ -2681,6 +2686,10 @@ void BKE_brush_get_dyntopo(Brush *brush, Sculpt *sd, DynTopoSettings *out)
     }
   }
 
+  if (inherit & DYNTOPO_INHERIT_RADIUS_SCALE) {
+    out->radius_scale = sd->dyntopo_radius_scale;
+  }
+
   if (inherit & DYNTOPO_INHERIT_DETAIL_SIZE) {
     out->detail_size = sd->detail_size;
   }
diff --git a/source/blender/blenkernel/intern/dyntopo.c b/source/blender/blenkernel/intern/dyntopo.c
index 8370de2af69..35f242f2d22 100644
--- a/source/blender/blenkernel/intern/dyntopo.c
+++ b/source/blender/blenkernel/intern/dyntopo.c
@@ -181,11 +181,112 @@ static void edge_queue_create_local(struct EdgeQueueContext *eq_ctx,
                                     const bool use_projected,
                                     bool is_collapse);
 
+void bmesh_disk_edge_append(BMEdge *e, BMVert *v);
+void bmesh_radial_loop_append(BMEdge *e, BMLoop *l);
+void bm_kill_only_edge(BMesh *bm, BMEdge *e);
+void bm_kill_only_loop(BMesh *bm, BMLoop *l);
+void bm_kill_only_face(BMesh *bm, BMFace *f);
+
+static void fix_mesh(PBVH *pbvh, BMesh *bm)
+{
+  BMIter iter;
+  BMVert *v;
+  BMEdge *e;
+  BMFace *f;
+
+  printf("fixing mesh. . .\n");
+
+  BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+    v->e = NULL;
+    MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
+
+    mv->flag |= DYNVERT_NEED_VALENCE | DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_DISK_SORT |
+                DYNVERT_NEED_TRIANGULATE;
+  }
+
+  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+    e->v1_disk_link.next = e->v1_disk_link.prev = NULL;
+    e->v2_disk_link.next = e->v2_disk_link.prev = NULL;
+    e->l = NULL;
+
+    if (e->v1 == e->v2) {
+      bm_kill_only_edge(bm, e);
+    }
+  }
+
+  // rebuild disk cycles
+  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+    if (BM_edge_exists(e->v1, e->v2)) {
+      printf("duplicate edge %p!", e);
+      bm_kill_only_edge(bm, e);
+
+      continue;
+    }
+
+    bmesh_disk_edge_append(e, e->v1);
+    bmesh_disk_edge_append(e, e->v2);
+  }
+
+  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+    BMLoop *l = f->l_first;
+
+    do {
+      if (f->len < 3) {
+        break;
+      }
+
+      if (l->next->v == l->v) {
+        BMLoop *l_del = l->next;
+
+        l->next = l_del->next;
+        l_del->next->prev = l;
+
+        f->len--;
+
+        if (f->l_first == l_del) {
+          f->l_first = l;
+        }
+
+        bm_kill_only_loop(bm, l_del);
+
+        if (f->len < 3) {
+          break;
+        }
+      }
+    } while ((l = l->next) != f->l_first);
+
+    if (f->len < 3) {
+      int ni = BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset);
+
+      if (ni >= 0 && ni < pbvh->totnode && (pbvh->nodes[ni].flag & PBVH_Leaf)) {
+        BLI_table_gset_remove(pbvh->nodes[ni].bm_faces, f, NULL);
+      }
+
+      bm_kill_only_face(bm, f);
+      continue;
+    }
+
+    do {
+      l->e = BM_edge_exists(l->v, l->next->v);
+
+      if (!l->e) {
+        l->e = BM_edge_create(bm, l->v, l->next->v, NULL, BM_CREATE_NOP);
+      }
+
+      bmesh_radial_loop_append(l->e, l);
+    } while ((l = l->next) != f->l_first);
+  }
+
+  bm->elem_table_dirty |= BM_VERT | BM_EDGE | BM_FACE;
+  bm->elem_index_dirty |= BM_VERT | BM_EDGE | BM_FACE;
+
+  printf("done fixing mesh.\n");
+}
+
 //#define CHECKMESH
 //#define TEST_INVALID_NORMALS
 
 #ifndef CHECKMESH
-#  define fix_mesh(bm)
 #  define validate_vert(pbvh, bm, v, autofix, check_manifold) true
 #  define validate_edge(pbvh, bm, e, autofix, check_manifold) true
 #  define validate_face(pbvh, bm, f, autofix, check_manifold) true
@@ -203,16 +304,13 @@ CHECKMESH_ATTR static void _debugprint(const char *fmt, ...)
   va_end(args);
 }
 
-void bmesh_disk_edge_append(BMEdge *e, BMVert *v);
-void bmesh_radial_loop_append(BMEdge *e, BMLoop *l);
-
 CHECKMESH_ATTR static bool check_face_is_manifold(PBVH *pbvh, BMesh *bm, BMFace *f)
 {
   BMLoop *l = f->l_first;
 
   do {
     if (l->radial_next != l && l->radial_next->radial_next != l) {
-      _debugprint("non-manifold edge in loop\n");
+      //_debugprint("non-manifold edge in loop\n");
 
       BMVert *v1 = l->e->v1, *v2 = l->e->v2;
 
@@ -220,7 +318,15 @@ CHECKMESH_ATTR static bool check_face_is_manifold(PBVH *pbvh, BMesh *bm, BMFace
         BMVert *v = i ? v2 : v1;
         BMEdge *e = v->e;
 
+        if (!e) {
+          continue;
+        }
+
         do {
+          if (!e) {
+            break;
+          }
+
           bool same = e->v1 == v1 && e->v2 == v2;
           same = same || (e->v1 == v2 && e->v2 == v1);
           if (same && e != l->e) {
@@ -248,45 +354,6 @@ CHECKMESH_ATTR static bool check_face_is_manifold(PBVH *pbvh, BMesh *bm, BMFace
   return true;
 }
 
-CHECKMESH_ATTR
-static void fix_mesh(BMesh *bm)
-{
-  BMIter iter;
-  BMVert *v;
-  BMEdge *e;
-  BMFace *f;
-
-  _debugprint("fixing mesh. . .\n");
-
-  BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
-    v->e = NULL;
-  }
-
-  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
-    e->v1_disk_link.next = e->v1_disk_link.prev = NULL;
-    e->v2_disk_link.next = e->v2_disk_link.prev = NULL;
-  }
-
-  // rebuild disk cycles
-  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
-    e->l = NULL;
-
-    bmesh_disk_edge_append(e, e->v1);
-    bmesh_disk_edge_append(e, e->v2);
-  }
-
-  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
-    BMLoop *l = f->l_first;
-
-    do {
-      l->e = BM_edge_exists(l->v, l->next->v);
-
-      bmesh_radial_loop_append(l->e, l);
-    } while ((l = l->next) != f->l_first);
-  }
-  _debugprint("done fixing mesh.\n");
-}
-
 CHECKMESH_ATTR
 static bool validate_vert(PBVH *pbvh, BMesh *bm, BMVert *v, bool autofix, bool check_manifold)
 {
@@ -348,7 +415,7 @@ static bool validate_vert(PBVH *pbvh, BMesh *bm, BMVert *v, bool autofix, bool c
 error:
 
   if (autofix) {
-    fix_mesh(bm);
+    fix_mesh(pbvh, bm);
   }
 
   return false;
@@ -366,7 +433,7 @@ static bool validate_edge(PBVH *pbvh, BMesh *bm, BMEdge *e, bool autofix, bool c
              validate_vert(pbvh, bm, e->v2, false, check_manifold);
 
   if (!ret && autofix) {
-    fix_mesh(bm);
+    fix_mesh(pbvh, bm);
   }
 
   return ret;
@@ -424,7 +491,7 @@ error:
   BLI_array_free(ls);
 
   if (autofix) {
-    fix_mesh(bm);
+    fix_mesh(pbvh, bm);
   }
 
   return false;
@@ -465,7 +532,7 @@ CHECKMESH_ATTR bool validate_vert_faces(
 error:
 
   if (autofix) {
-    fix_mesh(bm);
+    fix_mesh(pbvh, bm);
   }
 
   return false;
@@ -2138,7 +2205,7 @@ static bool check_face_is_tri(PBVH *pbvh, BMFace *f)
   return false;
 }
 
-ATTR_NO_OPT static bool check_for_flaps(PBVH *pbvh, BMVert *v)
+static bool check_for_flaps(PBVH *pbvh, BMVert *v)
 {
   const int updateflag = DYNVERT_NEED_VALENCE | DYNVERT_NEED_DISK_SORT | DYNVERT_NEED_BOUNDARY;
 
@@ -3161,13 +3228,141 @@ static bool pbvh_bmesh_subdivide_long_edges(
   return any_subdivided;
 }
 
-ATTR_NO_OPT static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
-                                                 BMEdge *e,
-                                                 BMVert *v1,
-                                                 BMVert *v2,
-                                                 GHash *deleted_verts,
-                                                 BLI_Buffer *deleted_faces,
-                                                 EdgeQueueContext *eq_ctx)
+static bool bm_edge_tag_test(BMEdge *e)
+{
+  /* is the edge or one of its faces tagged? */
+  return (BM_elem_flag_test(e->v1, BM_ELEM_TAG) || BM_elem_flag_test(e->v2, BM_ELEM_TAG) ||
+          (e->l &&
+           (BM_elem_flag_test(e->l->f, BM_ELEM_TAG) ||
+            (e->l != e->l->radial_next && BM_elem_flag_test(e->l->radial_next->f, BM_ELEM_TAG)))));
+}
+
+static void bm_edge_tag_disable(BMEdge *e)
+{
+  BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
+  BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
+  if (e->l) {
+    BM_elem_flag_disable(e->l->f, BM_ELEM_TAG);
+    if (e->l != e->l->radial_next) {
+      BM_elem_flag_disable(e->l->radial_next->f, BM_ELEM_TAG);
+    }
+  }
+}
+
+/* takes the edges loop */
+BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l)
+{
+#if 0
+  /* less optimized version of check below */
+  return (BM_edge_is_manifold(l->e) || BM_edge_is_boundary(l->e);
+#else
+  /* if the edge is a boundary it points to its self, else this must be a manifold */
+  return LIKELY(l) && LIKELY(l->radial_next->radial_next == l);
+#endif
+}
+
+static void bm_edge_tag_enable(BMEdge *e)
+{
+  BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+  BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+  if (e->l) {
+    BM_elem_flag_enable(e->l->f, BM_ELEM_TAG);
+    if (e->l != e->l->radial_next) {
+      BM_elem_flag_enable(e->l->radial_next->f, BM_ELEM_TAG);
+    }
+  }
+}
+
+// copied from decimate modifier code
+static bool bm_edge_collapse

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list