[Bf-blender-cvs] [9f3bafc4ab7] temp_bmesh_multires: Sculpt dyntopo
Joseph Eagar
noreply at git.blender.org
Thu Sep 9 09:20:49 CEST 2021
Commit: 9f3bafc4ab7cc0ba83c51a7147f63f5c5a9341d8
Author: Joseph Eagar
Date: Wed Sep 8 23:18:07 2021 -0800
Branches: temp_bmesh_multires
https://developer.blender.org/rB9f3bafc4ab7cc0ba83c51a7147f63f5c5a9341d8
Sculpt dyntopo
* Non-manifold "fins" are now detected and automatically
deleted.
* Fixed compile error on linux.
===================================================================
M source/blender/blenkernel/intern/dyntopo.c
M source/blender/blenkernel/intern/pbvh_bmesh.c
M source/blender/bmesh/intern/bmesh_log.c
M source/blender/makesrna/intern/rna_brush.c
===================================================================
diff --git a/source/blender/blenkernel/intern/dyntopo.c b/source/blender/blenkernel/intern/dyntopo.c
index 35f242f2d22..211a35a3abd 100644
--- a/source/blender/blenkernel/intern/dyntopo.c
+++ b/source/blender/blenkernel/intern/dyntopo.c
@@ -161,7 +161,6 @@ 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,
@@ -2205,121 +2204,192 @@ static bool check_face_is_tri(PBVH *pbvh, BMFace *f)
return false;
}
-static bool check_for_flaps(PBVH *pbvh, BMVert *v)
+static bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root)
{
- const int updateflag = DYNVERT_NEED_VALENCE | DYNVERT_NEED_DISK_SORT | DYNVERT_NEED_BOUNDARY;
+ static int max_faces = 64;
+ BMFace **stack = NULL;
+ BLI_array_staticdeclare(stack, 32);
- bool ret = false;
+ BMLoop *l = e_root->l;
+ BMLoop **ls = NULL;
+ BMFace **fs = NULL;
+ BLI_array_staticdeclare(ls, 5);
+ int minfs = INT_MAX;
- if (!v->e) {
+ if (!l) {
return false;
}
- BMEdge *e = v->e;
- BMEdge *enext;
do {
- enext = BM_DISK_EDGE_NEXT(e, v);
+ BLI_array_append(ls, l);
+ } while ((l = l->radial_next) != e_root->l);
- BMLoop *l = e->l;
- BMLoop *lnext;
+ for (int i = 0; i < BLI_array_len(ls); i++) {
+ SmallHash visit;
+ BLI_smallhash_init(&visit);
- bool ok = !l;
- ok = ok || (l == l->radial_next->radial_next);
+ BMLoop *l = ls[i];
+ BMFace *f = l->f;
+ BMFace **fs2 = NULL;
+ BLI_array_staticdeclare(fs2, 32);
- if (false) { //! l) {
- BMVert *v2 = BM_edge_other_vert(e, v);
+ BLI_array_clear(stack);
+ BLI_array_append(stack, f);
+ BLI_array_append(fs2, f);
- MDynTopoVert *mv1 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
- mv1->flag |= updateflag;
+ BLI_smallhash_insert(&visit, (uintptr_t)f, NULL);
- MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v2);
- mv2->flag |= updateflag;
+ bool bad = false;
- BM_log_edge_removed(pbvh->bm_log, e);
- BM_edge_kill(pbvh->bm, e);
+ while (BLI_array_len(stack) > 0) {
+ f = BLI_array_pop(stack);
+ BMLoop *l = f->l_first;
-#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
+ do {
+ if (l->radial_next == l || l->radial_next->radial_next != l) {
+ continue;
+ }
- return true;
- if (!v->e) {
- break;
- }
+ void **val = NULL;
+ BMFace *f2 = l->radial_next->f;
- enext = BM_DISK_EDGE_NEXT(v->e, v);
+ if (!BLI_smallhash_ensure_p(&visit, (uintptr_t)f2, &val)) {
+ if (BLI_array_len(fs2) > max_faces) {
+ bad = true;
+ break;
+ }
- continue;
+ *val = NULL;
+ BLI_array_append(stack, f2);
+ BLI_array_append(fs2, f2);
+ }
+ } while ((l = l->next) != f->l_first);
+
+ if (bad) {
+ break;
+ }
}
- if (ok) {
- continue;
+ if (!bad && BLI_array_len(fs2) < minfs) {
+ minfs = BLI_array_len(fs2);
+ fs = BLI_array_alloca(fs, BLI_array_len(fs2));
+ memcpy(fs, fs2, sizeof(*fs) * BLI_array_len(fs2));
}
- do {
- lnext = l->radial_next;
+ BLI_array_free(fs2);
+ BLI_smallhash_release(&visit);
+ }
- bool ok2 = l->f->len == 3;
- // ok2 = ok2 && l->next->radial_next == l->next;
- // ok2 = ok2 && l->prev->radial_next == l->prev;
+ int nupdateflag = PBVH_UpdateOtherVerts | PBVH_UpdateDrawBuffers | PBVH_UpdateBB |
+ PBVH_UpdateTriAreas;
+ nupdateflag = nupdateflag | PBVH_UpdateNormals | PBVH_UpdateTris | PBVH_RebuildDrawBuffers;
- if (ok2) {
- ret = true;
- printf("destroying non-manifold triangle\n");
+ if (!fs) {
+ return false;
+ }
- BMVert *delv = l->prev->v;
+ if (fs) {
+ printf("manifold fin size: %d\n", minfs);
+ const int tag = BM_ELEM_TAG_ALT;
- // pbvh_bmesh_vert_remove(pbvh, delv);
- // BM_log_vert_removed(pbvh->bm_log, delv, pbvh->cd_vert_mask_offset);
+ for (int i = 0; i < minfs; i++) {
+ BMFace *f = fs[i];
- BMEdge *e1 = l->next->e;
- BMEdge *e2 = l->prev->e;
+ BMLoop *l = f->l_first;
+ do {
+ l->v->head.hflag &= ~tag;
+ l->e->head.hflag &= ~tag;
+ } while ((l = l->next) != f->l_first);
+ }
- pbvh_bmesh_face_remove(pbvh, l->f, true, false, false);
- BM_face_kill(pbvh->bm, l->f);
+ BMVert **vs = NULL;
+ BLI_array_staticdeclare(vs, 32);
+
+ BMEdge **es = NULL;
+ BLI_array_staticdeclare(es, 32);
- if (e1 != e && !e1->l) {
- BM_log_edge_removed(pbvh->bm_log, e1);
- BM_edge_kill(pbvh->bm, e1);
+ for (int i = 0; i < minfs; i++) {
+ BMFace *f = fs[i];
+
+ BMLoop *l = f->l_first;
+ do {
+ if (!(l->v->head.hflag & tag)) {
+ l->v->head.hflag |= tag;
+ BLI_array_append(vs, l->v);
}
- if (e2 != e && !e2->l) {
- BM_log_edge_removed(pbvh->bm_log, e2);
- BM_edge_kill(pbvh->bm, e2);
+ if (!(l->e->head.hflag & tag)) {
+ l->e->head.hflag |= tag;
+ BLI_array_append(es, l->e);
}
+ } while ((l = l->next) != f->l_first);
+ }
- MDynTopoVert *mv1 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, e->v1);
- MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, e->v2);
+ for (int i = 0; i < minfs; i++) {
+ BMFace *f = fs[i];
- mv1->flag |= updateflag;
- mv2->flag |= updateflag;
+ int ni = BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset);
+ if (ni >= 0 && ni < pbvh->totnode) {
+ pbvh->nodes[ni].flag |= nupdateflag;
+ }
- if (!v->e) { // check that v still has edges left
- break;
- }
+ pbvh_bmesh_face_remove(pbvh, f, true, false, false);
+ BM_face_kill(pbvh->bm, f);
+ }
- // enext might not be valid, reset it
- enext = BM_DISK_EDGE_NEXT(v->e, v);
- // return true;
+ const int mupdateflag = DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_DISK_SORT | DYNVERT_NEED_VALENCE;
+
+ for (int i = 0; i < BLI_array_len(es); i++) {
+ BMEdge *e = es[i];
+
+ if (!e->l) {
+ BM_log_edge_removed(pbvh->bm_log, e);
+ BM_edge_kill(pbvh->bm, e);
}
- } while ((l = lnext) != e->l);
- } while ((e = enext) != v->e);
+ }
- return ret;
+ for (int i = 0; i < BLI_array_len(vs); i++) {
+ BMVert *v = vs[i];
+
+ if (!v->e) {
+ pbvh_bmesh_vert_remove(pbvh, v);
+
+ BM_log_vert_removed(pbvh->bm_log, v, pbvh->cd_vert_mask_offset);
+ BM_vert_kill(pbvh->bm, v);
+ }
+ else {
+ MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
+ mv->flag |= mupdateflag;
+ }
+ }
+
+ BLI_array_free(vs);
+ BLI_array_free(es);
+ }
+
+ return true;
}
-static bool check_for_flaps_face(PBVH *pbvh, BMFace *f)
+static bool check_for_fins(PBVH *pbvh, BMVert *v)
{
- BMLoop *l = f->l_first;
+ BMEdge *e = v->e;
+ if (!e) {
+ return false;
+ }
+
do {
- if (check_for_flaps(pbvh, l->v)) {
- return true;
+ if (e->l) {
+ BMLoop *l = e->l->f->l_first;
+
+ do {
+ if (l != l->radial_next && l != l->radial_next->radial_next) {
+ if (destroy_nonmanifold_fins(pbvh, e)) {
+ return true;
+ }
+ }
+ } while ((l = l->next) != e->l->f->l_first);
}
- } while ((l = l->next) != f->l_first);
+ } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
return false;
}
@@ -2489,8 +2559,18 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
BMEdge **edges = td->edges;
for (int j = 0; j < td->totedge; j++) {
BMEdge *e = edges[j];
+
+ if (bm_elem_is_free((BMElem *)e, BM_EDGE)) {
+ continue;
+ }
+
e->head.hflag &= ~BM_ELEM_TAG;
+ if (e->l && e->l != e->l->radial_next->radial_next) {
+ // deal with non-manifold iffyness
+ destroy_nonmanifold_fins(pbvh, e);
+ }
+
MDynTopoVert *mv1 = BKE_PBVH_DYNVERT(cd_dyn_vert, e->v1);
MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(cd_dyn_vert, e->v2);
@@ -3163,6 +3243,10 @@ static bool pbvh_bmesh_subdivide_long_edges(
BLI_mempool_free(eq_ctx->pool, pair);
pair = NULL;
+ if (bm_elem_is_free((BMElem *)v1, BM_VERT) || bm_elem_is_free((BMElem *)v2, BM_VERT)) {
+ continue;
+ }
+
/* Check that the edge still exists */
if (!(e = BM_edge_exists(v1, v2))) {
continue;
@@ -3787,7 +3871,6 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
}
#if 0
- check_for_flaps(pbvh, v_conn);
e = v_conn->e;
if (e) {
@@ -3797,9 +3880,6 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
MDynTopoVert *mv4 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v2);
- if (check_for_flaps(pbvh, v2)) {
- break;
- }
} while ((e = enext) != v_conn->e);
}
#endif
@@ -4455,6 +4535,11 @@ cleanup_valence_3_4(EdgeQueueContext *ectx,
}
BMVert *v = ectx->val34_verts[vi];
+
+ if (bm_elem_is_free((BMElem *)v, BM_VERT)) {
+ continue;
+ }
+
const int n = BM_ELEM_CD_GET_INT(v, cd_vert_node);
if (n == DYNTOPO_NODE_NONE) {
@@ -4465,6 +4550,10 @@ cleanup_valence_3_4(EdgeQueueContext *ectx,
continue;
}
+ if (check_for_fins(pbvh, v)) {
+ continue;
+ }
+
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
mv->flag &= ~DYNVERT_VALENCE_TEMP;
@@ -4797,16 +4886,12 @@ cleanup_valence_3_4(EdgeQueueContext *ectx,
pbvh_kill_vert(pbvh, v);
if (f1 && !bm_elem_is_free((BMElem *)f1, BM_FACE)) {
- check_for_flaps_face(pbvh, f1);
-
if (!bm_elem_is_free((BMElem *)f1, BM_FACE)) {
check_face_is_manifold(pbvh, pbvh->bm, f1);
}
}
if (f2 && !bm_elem_is_free((BMElem *)f2, BM_FACE)) {
- check_for_flaps_face(pbvh, f2);
-
if (!bm_elem_is_free((BMElem *)f2, BM_FACE
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list