* Boundary info is no longer initialized with

SCULPT_boundary_info_ensure, instead PBVH_BMESH keeps
  track of boundary vert flags internally.  This prevents
  nasty first-click lag on the smooth brush as well as anything
  with autosmooth.
This commit is contained in:
Joseph Eagar 2021-04-25 14:51:31 -07:00
parent 0386350de6
commit 8a700673db
4 changed files with 30 additions and 37 deletions

View File

@ -623,7 +623,6 @@ typedef struct SculptSession {
* Set #Main.is_memfile_undo_flush_needed when enabling.
*/
char needs_flush_to_id;
char update_boundary_info_bmesh;
// id of current stroke, used to detect
// if vertex original data needs to be updated

View File

@ -1993,6 +1993,10 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
BMesh *bm = pbvh->bm;
float co_mid[3], no_mid[3];
MDynTopoVert *mv1 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, e->v1);
MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, e->v2);
bool boundary = (mv1->flag & DYNVERT_BOUNDARY) && (mv2->flag & DYNVERT_BOUNDARY);
/* Get all faces adjacent to the edge */
pbvh_bmesh_edge_loops(edge_loops, e);
@ -2022,6 +2026,11 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
float vws[2] = {0.5f, 0.5f};
CustomData_bmesh_interp(&pbvh->bm->vdata, vsrcs, vws, NULL, 2, v_new->head.data);
if (boundary) {
MDynTopoVert *mv_new = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v_new);
mv_new->flag |= DYNVERT_BOUNDARY;
}
/* update paint mask */
if (eq_ctx->cd_dyn_vert != -1) {
float mask_v1 = DYNTOPO_MASK(eq_ctx->cd_dyn_vert, e->v1);
@ -2270,6 +2279,9 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
{
BMVert *v_del, *v_conn;
MDynTopoVert *mv1 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v1);
MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v2);
// customdata interpolation
if (BM_elem_flag_test(e, BM_ELEM_SEAM)) {
for (int step = 0; step < 2; step++) {
@ -2424,9 +2436,9 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
{
bool ok = true;
//check we're not already in deleted_faces
for (int i=0; i<deleted_faces->count; i++) {
if (BLI_buffer_at(deleted_faces, BMFace*, i) == existing_face) {
// check we're not already in deleted_faces
for (int i = 0; i < deleted_faces->count; i++) {
if (BLI_buffer_at(deleted_faces, BMFace *, i) == existing_face) {
ok = false;
break;
}
@ -2495,7 +2507,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
printf("bmesh error!\n");
l1->e = BM_edge_exists(l->v, l->next->v);
if (!l1->e) {
//create
// create
l1->e = BM_edge_create(pbvh->bm, l->v, l->next->v, NULL, 0);
}
}
@ -2550,6 +2562,11 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
PBVH_UpdateTris;
}
BM_LOOPS_OF_VERT_ITER_END;
if (BM_vert_is_boundary(v_conn)) {
MDynTopoVert *mv_conn = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v_conn);
mv_conn->flag |= DYNVERT_BOUNDARY;
}
}
/* Delete v_del */
@ -3625,7 +3642,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
}
#endif
//avoid potential infinite loops
// avoid potential infinite loops
const int totnode = pbvh->totnode;
for (int i = 0; i < totnode; i++) {
@ -3856,12 +3873,11 @@ void BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node)
if (!BLI_ghash_ensure_p(vmap, l->v, &val)) {
SculptVertRef sv = {(intptr_t)l->v};
*val = (void*) BLI_array_len(verts);
*val = (void *)BLI_array_len(verts);
BLI_array_append(verts, sv);
}
tri.v[j] = (intptr_t) val[0];
tri.v[j] = (intptr_t)val[0];
j++;
l = l->next;

View File

@ -8482,7 +8482,6 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
BKE_pbvh_bmesh_after_stroke(ss->pbvh);
ss->update_boundary_info_bmesh = true;
#if 0
if (update_flags & SCULPT_UPDATE_COLOR) {
PBVHNode **nodes;
@ -9778,32 +9777,9 @@ void SCULPT_boundary_info_ensure(Object *object)
{
SculptSession *ss = object->sculpt;
// PBVH_BMESH now handles itself
if (ss->bm) {
if (!ss->update_boundary_info_bmesh) {
return;
}
ss->update_boundary_info_bmesh = 0;
BMVert *v;
BMIter iter;
MEM_SAFE_FREE(ss->vertex_info.boundary);
// return; //XXX
BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
MDynTopoVert *mv = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v);
SculptVertRef sv = {(uintptr_t)v};
if (BM_vert_is_boundary(v) || !SCULPT_vertex_all_face_sets_visible_get(ss, sv)) {
mv->flag |= DYNVERT_BOUNDARY;
}
else {
mv->flag &= ~DYNVERT_BOUNDARY;
}
}
return;
}
else {
if (ss->vertex_info.boundary) {

View File

@ -409,6 +409,10 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
MDynTopoVert *mv = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v);
if (BM_vert_is_boundary(v)) {
mv->flag |= DYNVERT_BOUNDARY;
}
// persistent base
if (cd_pers_co >= 0) {
float(*co)[3] = BM_ELEM_CD_GET_VOID_P(v, cd_pers_co);
@ -444,8 +448,6 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
/* Enable dynamic topology. */
me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
ss->update_boundary_info_bmesh = 1;
/* Enable logging for undo/redo. */
ss->bm_log = BM_log_create(ss->bm, ss->cd_dyn_vert);