[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