Sculpt dyntopo: fix nasty node splitting bug

This commit is contained in:
Joseph Eagar 2021-09-13 20:14:46 -07:00
parent 3df335d330
commit 0eeaeb3fc2
2 changed files with 37 additions and 7 deletions

View File

@ -161,6 +161,7 @@ static void pbvh_bmesh_verify(PBVH *pbvh);
struct EdgeQueueContext;
static bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root);
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,
@ -3693,7 +3694,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
int totl = 0;
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_del) {
MDynTopoVert *mv_l = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, l->v);
MDynTopoVert *mv_l = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, l->next->v);
mv_l->flag |= mupdateflag;
BLI_array_append(ls, l);
@ -3702,7 +3703,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
BM_LOOPS_OF_VERT_ITER_END;
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_conn) {
MDynTopoVert *mv_l = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, l->v);
MDynTopoVert *mv_l = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, l->next->v);
mv_l->flag |= mupdateflag;
BLI_array_append(ls, l);
@ -3962,6 +3963,16 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
MDynTopoVert *mv3 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v_conn);
mv3->flag |= mupdateflag;
if (BM_ELEM_CD_GET_INT(v_conn, pbvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) {
printf("eek!\n");
}
for (int i = 0; i < 3; i++) {
if (!check_for_fins(pbvh, v_conn)) {
break;
}
}
if (wasbad) {
fix_mesh(pbvh, pbvh->bm);
return;

View File

@ -251,7 +251,9 @@ static void pbvh_bmesh_node_finalize(PBVH *pbvh,
bool has_visible = false;
/* Create vert hash sets */
n->bm_unique_verts = BLI_table_gset_new("bm_unique_verts");
if (!n->bm_unique_verts) {
n->bm_unique_verts = BLI_table_gset_new("bm_unique_verts");
}
n->bm_other_verts = BLI_table_gset_new("bm_other_verts");
BB_reset(&n->vb);
@ -356,7 +358,9 @@ static void pbvh_bmesh_node_split(
c1->bm_faces = BLI_table_gset_new_ex("bm_faces", BLI_table_gset_len(n->bm_faces) / 2);
c2->bm_faces = BLI_table_gset_new_ex("bm_faces", BLI_table_gset_len(n->bm_faces) / 2);
c1->bm_unique_verts = c2->bm_unique_verts = NULL;
c1->bm_unique_verts = BLI_table_gset_new("bm_unique_verts");
c2->bm_unique_verts = BLI_table_gset_new("bm_unique_verts");
c1->bm_other_verts = c2->bm_other_verts = NULL;
/* Partition the parent node's faces between the two children */
@ -389,17 +393,32 @@ static void pbvh_bmesh_node_split(
BLI_table_gset_insert(empty, key);
BLI_table_gset_remove(other, key, NULL);
break;
} TGSET_ITER_END
}
TGSET_ITER_END
}
#endif
/* Clear this node */
BMVert *v;
TableGSet *bm_unique_verts = n->bm_unique_verts;
/* Mark this node's unique verts as unclaimed */
/* Assign verts to c1 and c2. Note that the previous
method of simply marking them as untaken and rebuilding
unique verts later doesn't work, as it assumes that dyntopo
never assigns verts to nodes that don't contain their
faces.*/
if (n->bm_unique_verts) {
TGSET_ITER (v, n->bm_unique_verts) {
BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, DYNTOPO_NODE_NONE);
int ni;
if (v->co[axis] < mid) {
BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, (c1 - pbvh->nodes));
BLI_table_gset_add(c1->bm_unique_verts, v);
}
else {
BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, (c2 - pbvh->nodes));
BLI_table_gset_add(c2->bm_unique_verts, v);
}
}
TGSET_ITER_END