[Bf-blender-cvs] [3e6edf5278e] temp_bmesh_multires: Sculpt dyntopo:

Joseph Eagar noreply at git.blender.org
Wed Sep 8 10:32:25 CEST 2021


Commit: 3e6edf5278e8fbc1f7163f62b67074867b531bfc
Author: Joseph Eagar
Date:   Tue Sep 7 23:49:54 2021 -0800
Branches: temp_bmesh_multires
https://developer.blender.org/rB3e6edf5278e8fbc1f7163f62b67074867b531bfc

Sculpt dyntopo:

* BLI_table_gset now internally uses a SmallHash instead of
  a GHash.  Profiling revealed this to be quite a bit
  faster.
* This is something of a stopgap until C++-afication of
  pbvh, when we'll have our pick of a bunch of
  really nice C++ hashmap libs.
* pbvh_collapse_edge bites the dust; dyntopo now uses
  BM_collapse_edge.  Of the three topology operations
  (subdivide edge, collapse edge, dissolve 3/4 valence
  vertex) only dissolve still has a dyntopo-specific
  implementation.
* Fixed a bunch of annoying memory corruption bugs.
* Non-manifold triangles are now detected in more
  places.

SmallHash changes:

* Enabled removal
* Fixed infinite loop bug caused by
  improperly counting free*d* cells
  versus free cells.
* Added a BLI_smallhash_ensure_p method
  that works just like the GHash version.

Sculpt replay system

* Roughed out a simple system to record and
  play back sculpt strokes using a simple
  text format.
* This is exclusively for
  performance profiling and unit tests.
* For each brush stroke the system saves a copy
  of the active StrokeCache and PaintStroke
  and parts of Sculpt.

This should make profiling DRAM thrashing a lot
easier.

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

M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/intern/dyntopo.c
M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/blenkernel/intern/pbvh_bmesh.c
M	source/blender/blenkernel/intern/pbvh_intern.h
M	source/blender/blenlib/BLI_smallhash.h
M	source/blender/blenlib/intern/BLI_table_gset.c
M	source/blender/blenlib/intern/smallhash.c
M	source/blender/bmesh/intern/bmesh_log.c
M	source/blender/bmesh/intern/bmesh_mesh.c
M	source/blender/editors/sculpt_paint/CMakeLists.txt
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
A	source/blender/editors/sculpt_paint/sculpt_replay.c
M	source/blender/editors/sculpt_paint/sculpt_smooth.c
M	source/blender/editors/sculpt_paint/sculpt_undo.c
M	source/blender/makesrna/intern/rna_sculpt_paint.c

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

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index c017c42aee1..edea39f1d3e 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -29,7 +29,7 @@
 #include "BKE_ccg.h"
 #include <stdint.h>
 
-#define DEFRAGMENT_MEMORY
+//#define DEFRAGMENT_MEMORY
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/source/blender/blenkernel/intern/dyntopo.c b/source/blender/blenkernel/intern/dyntopo.c
index c6f9b8a6437..8370de2af69 100644
--- a/source/blender/blenkernel/intern/dyntopo.c
+++ b/source/blender/blenkernel/intern/dyntopo.c
@@ -7,6 +7,7 @@
 
 #include "BLI_alloca.h"
 #include "BLI_array.h"
+#include "BLI_asan.h"
 #include "BLI_bitmap.h"
 #include "BLI_buffer.h"
 #include "BLI_compiler_attrs.h"
@@ -33,6 +34,8 @@
 
 #include <stdio.h>
 
+//#define DYNTOPO_REPORT
+
 #define DYNVERT_VALENCE_TEMP (1 << 14)
 
 #define USE_NEW_SPLIT
@@ -72,7 +75,7 @@
    to improve convergence of remesher */
 #define DYNTOPO_SAFE_SMOOTH_FAC 0.05f
 
-#define DYNTOPO_SAFE_SMOOTH_SUBD_ONLY_FAC 0.75f
+#define DYNTOPO_SAFE_SMOOTH_SUBD_ONLY_FAC 0.075f
 
 #ifdef USE_EDGEQUEUE_EVEN_SUBDIV
 #  include "BKE_global.h"
@@ -158,6 +161,7 @@ static void pbvh_bmesh_verify(PBVH *pbvh);
 
 struct EdgeQueueContext;
 
+static bool check_for_flaps(PBVH *pbvh, BMVert *v);
 static bool check_face_is_tri(PBVH *pbvh, BMFace *f);
 static bool check_vert_fan_are_tris(PBVH *pbvh, BMVert *v);
 static void pbvh_split_edges(struct EdgeQueueContext *eq_ctx,
@@ -182,11 +186,11 @@ static void edge_queue_create_local(struct EdgeQueueContext *eq_ctx,
 
 #ifndef CHECKMESH
 #  define fix_mesh(bm)
-#  define validate_vert(bm, v, autofix, check_manifold) true
-#  define validate_edge(bm, e, autofix, check_manifold) true
-#  define validate_face(bm, f, autofix, check_manifold) true
-#  define validate_vert_faces(bm, v, autofix, check_manifold) true
-#  define check_face_is_manifold(bm, f) true
+#  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
+#  define validate_vert_faces(pbvh, bm, v, autofix, check_manifold) true
+#  define check_face_is_manifold(pbvh, bm, f) true
 #else
 
 #  define CHECKMESH_ATTR ATTR_NO_OPT
@@ -202,13 +206,34 @@ CHECKMESH_ATTR static void _debugprint(const char *fmt, ...)
 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(BMesh *bm, BMFace *f)
+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");
+
+      BMVert *v1 = l->e->v1, *v2 = l->e->v2;
+
+      for (int i = 0; i < 2; i++) {
+        BMVert *v = i ? v2 : v1;
+        BMEdge *e = v->e;
+
+        do {
+          bool same = e->v1 == v1 && e->v2 == v2;
+          same = same || (e->v1 == v2 && e->v2 == v1);
+          if (same && e != l->e) {
+            printf("duplicate edges!");
+          }
+        } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
+      }
+      l->e->head.hflag |= BM_ELEM_SELECT;
+      l->f->head.hflag |= BM_ELEM_SELECT;
+      l->v->head.hflag |= BM_ELEM_SELECT;
+
+      // pbvh->dyntopo_stop = true;
+
       return false;
     }
 
@@ -263,7 +288,7 @@ static void fix_mesh(BMesh *bm)
 }
 
 CHECKMESH_ATTR
-static bool validate_vert(BMesh *bm, BMVert *v, bool autofix, bool check_manifold)
+static bool validate_vert(PBVH *pbvh, BMesh *bm, BMVert *v, bool autofix, bool check_manifold)
 {
   if (v->head.htype != BM_VERT) {
     _debugprint("bad vertex\n");
@@ -305,7 +330,7 @@ static bool validate_vert(BMesh *bm, BMVert *v, bool autofix, bool check_manifol
         }
 
         if (check_manifold) {
-          check_face_is_manifold(bm, l->f);
+          check_face_is_manifold(pbvh, bm, l->f);
         }
       } while ((l = l->radial_next) != e->l);
     }
@@ -330,15 +355,15 @@ error:
 }
 
 CHECKMESH_ATTR
-static bool validate_edge(BMesh *bm, BMEdge *e, bool autofix, bool check_manifold)
+static bool validate_edge(PBVH *pbvh, BMesh *bm, BMEdge *e, bool autofix, bool check_manifold)
 {
   if (e->head.htype != BM_EDGE) {
     _debugprint("corrupted edge!\n");
     return false;
   }
 
-  bool ret = validate_vert(bm, e->v1, false, check_manifold) &&
-             validate_vert(bm, e->v2, false, check_manifold);
+  bool ret = validate_vert(pbvh, bm, e->v1, false, check_manifold) &&
+             validate_vert(pbvh, bm, e->v2, false, check_manifold);
 
   if (!ret && autofix) {
     fix_mesh(bm);
@@ -348,7 +373,7 @@ static bool validate_edge(BMesh *bm, BMEdge *e, bool autofix, bool check_manifol
 }
 
 CHECKMESH_ATTR
-static bool validate_face(BMesh *bm, BMFace *f, bool autofix, bool check_manifold)
+static bool validate_face(PBVH *pbvh, BMesh *bm, BMFace *f, bool autofix, bool check_manifold)
 {
   if (f->head.htype != BM_FACE) {
     _debugprint("corrupted edge!\n");
@@ -368,7 +393,7 @@ static bool validate_face(BMesh *bm, BMFace *f, bool autofix, bool check_manifol
       goto error;
     }
 
-    if (!validate_edge(bm, l->e, false, check_manifold)) {
+    if (!validate_edge(pbvh, bm, l->e, false, check_manifold)) {
       goto error;
     }
 
@@ -405,9 +430,10 @@ error:
   return false;
 }
 
-CHECKMESH_ATTR bool validate_vert_faces(BMesh *bm, BMVert *v, int autofix, bool check_manifold)
+CHECKMESH_ATTR bool validate_vert_faces(
+    PBVH *pbvh, BMesh *bm, BMVert *v, int autofix, bool check_manifold)
 {
-  if (!validate_vert(bm, v, autofix, check_manifold)) {
+  if (!validate_vert(pbvh, bm, v, autofix, check_manifold)) {
     return false;
   }
 
@@ -424,11 +450,11 @@ CHECKMESH_ATTR bool validate_vert_faces(BMesh *bm, BMVert *v, int autofix, bool
     }
 
     do {
-      if (!validate_edge(bm, l->e, false, false)) {
+      if (!validate_edge(pbvh, bm, l->e, false, false)) {
         goto error;
       }
 
-      if (!validate_face(bm, l->f, false, check_manifold)) {
+      if (!validate_face(pbvh, bm, l->f, false, check_manifold)) {
         goto error;
       }
     } while ((l = l->radial_next) != e->l);
@@ -495,13 +521,12 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v, float fac)
     BMVert *v2 = e->v1 == v ? e->v2 : e->v1;
 
     // can't check for boundary here, thread
-    // pbvh_check_vert_boundary(pbvh, v2);
+    pbvh_check_vert_boundary(pbvh, v2);
 
     MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(cd_dyn_vert, v2);
     const bool bound2 = mv2->flag & DYNVERT_SMOOTH_BOUNDARY;
 
-    if (bound1 != bound2) {
-      e = v == e->v1 ? e->v1_disk_link.next : e->v2_disk_link.next;
+    if (bound1 && !bound2) {
       continue;
     }
 
@@ -512,8 +537,7 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v, float fac)
     add_v3_v3(co, tan);
     tot += 1.0f;
 
-    e = v == e->v1 ? e->v1_disk_link.next : e->v2_disk_link.next;
-  } while (e != v->e);
+  } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
 
   if (tot == 0.0f) {
     return;
@@ -535,8 +559,7 @@ static void pbvh_kill_vert(PBVH *pbvh, BMVert *v)
   if (e) {
     do {
       BM_log_edge_removed(pbvh->bm_log, e);
-      e = BM_DISK_EDGE_NEXT(e, v);
-    } while (e != v->e);
+    } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
   }
 
   BM_vert_kill(pbvh->bm, v);
@@ -1409,6 +1432,29 @@ static float dist_to_tri_sphere_simple(
   return dis;
 }
 
+static int sizes[] = {-1,
+                      (int)sizeof(BMVert),
+                      (int)sizeof(BMEdge),
+                      0,
+                      (int)sizeof(BMLoop),
+                      -1,
+                      -1,
+                      -1,
+                      (int)sizeof(BMFace)};
+
+static bool bm_elem_is_free(BMElem *elem, int htype)
+{
+  BLI_asan_unpoison(elem, sizes[htype]);
+
+  bool ret = elem->head.htype != htype;
+
+  if (ret) {
+    BLI_asan_poison(elem, sizes[htype]);
+  }
+
+  return ret;
+}
+
 static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
 {
   BMLoop *l = f->l_first;
@@ -1895,6 +1941,11 @@ static void short_edge_queue_task_cb(void *__restrict userdata,
     BMLoop *l = f->l_first;
 
     do {
+      if (!l->e) {
+        printf("bmesh error! %s\n", __func__);
+        continue;
+      }
+
       l->e->head.hflag &= ~BM_ELEM_TAG;
       l = l->next;
     } while (l != f->l_first);
@@ -1987,7 +2038,7 @@ static bool check_face_is_tri(PBVH *pbvh, BMFace *f)
 
   BMLoop *l = f->l_first;
   do {
-    validate_vert(pbvh->bm, l->v, true, true);
+    validate_vert(pbvh, pbvh->bm, l->v, true, true);
 
     if (l->e->head.index == -1) {
       l->e->head.index = 0;
@@ -2065,7 +2116,7 @@ static bool check_face_is_tri(PBVH *pbvh, BMFace *f)
       }
     } while ((l = l->next) != f2->l_first);
 
-    validate_face(pbvh->bm, f2, false, true);
+    validate_face(pbvh, pbvh->bm, f2, false, true);
     BKE_pbvh_bmesh_add_face(pbvh, f2, true, true);
   }
 
@@ -2087,6 +2138,125 @@ static bool check_face_is_tri(PBVH *pbvh, BMFace *f)
   return false;
 }
 
+ATTR_NO_OPT static bool check_for_flaps(PBVH *pbvh, BMVert *v)
+{
+  const int updateflag = DYNVERT_NEED_VALENCE | DYNVERT_NEED_DISK_SORT | DYNVERT_NEED_BOUNDARY;
+
+  bool ret = false;
+
+  if (!v->e) {
+    return false;
+  }
+
+  BMEdge *e = v->e;
+  BMEdge *enext;
+  do {
+    enext = BM_DISK_EDGE_NEXT(e, v);
+
+    BMLoop *l = e->l;
+    BMLoop *lnext;
+
+    bool ok = !l;
+    ok = ok || (l == l->radial_next->radial_next);
+
+    if (false) {  //! l) {
+      BMVert *v2 = BM_edge_other_vert(e, v);
+
+      MDynTopoVert *mv1 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
+      mv1->flag |= updateflag;
+
+      MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v2);
+      mv2->flag |= updateflag;
+
+      BM_log_edge_removed(pbvh->bm_log, e);
+      BM_edge_kill(pbvh->bm, e);
+
+#if 0
+      if (!v2->e) {
+        pbvh_bmesh_vert_remove(pbvh, v2);
+        BM_log_vert_removed(pbvh->bm_log, v2, pbvh->cd_vert_mask_offset);
+        BM_vert_kill(pbvh->bm, v2);
+      }
+#endif
+
+      return true;
+      if (!v->e) {
+        break;
+      }
+
+      enext = BM_DISK_EDGE_NEXT(

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list