From 3ebe97c06b67d1611dfeaa3919512155416b0378 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Mon, 27 Jul 2020 23:40:19 +0200 Subject: Fix T78665: Face Set visibility reverted when chaning Multires Levels Face Sets where only set and updated on the PBVH after starting a sculpt tool. In order to preserve the visibility they store when changing levels, they need to be updated and sync also on PBVH creation Reviewed By: sergey Maniphest Tasks: T78665 Differential Revision: https://developer.blender.org/D8225 --- source/blender/blenkernel/BKE_paint.h | 4 ++ source/blender/blenkernel/BKE_subdiv_ccg.h | 2 + source/blender/blenkernel/intern/paint.c | 64 +++++++++++++++++++++++++++ source/blender/blenkernel/intern/subdiv_ccg.c | 11 +++++ 4 files changed, 81 insertions(+) diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 1c02aece06f..de18ec6b792 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -471,6 +471,10 @@ struct PBVH *BKE_sculpt_object_pbvh_ensure(struct Depsgraph *depsgraph, struct O void BKE_sculpt_bvh_update_from_ccg(struct PBVH *pbvh, struct SubdivCCG *subdiv_ccg); +/* This ensure that all elements in the mesh (both vertices and grids) have their visibility + * updated according to the face sets. */ +void BKE_sculpt_sync_face_set_visibility(struct Mesh *mesh, struct SubdivCCG *subdiv_ccg); + bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d); enum { diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h index 5808f223f32..02b83a043b4 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.h +++ b/source/blender/blenkernel/BKE_subdiv_ccg.h @@ -338,6 +338,8 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const Subdi const int *BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG *subdiv_ccg); const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG *subdiv_ccg); +void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG *subdiv_ccg, int grid_index); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index d6fbba74a89..0ba5ec43318 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1825,6 +1825,64 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc return deformed; } +static void sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh) +{ + int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); + if (!face_sets) { + return; + } + + for (int i = 0; i < mesh->totvert; i++) { + mesh->mvert[i].flag |= ME_HIDE; + } + + for (int i = 0; i < mesh->totpoly; i++) { + if (face_sets[i] >= 0) { + for (int l = 0; l < mesh->mpoly[i].totloop; l++) { + MLoop *loop = &mesh->mloop[mesh->mpoly[i].loopstart + l]; + mesh->mvert[loop->v].flag &= ~ME_HIDE; + } + } + } +} + +static void sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg) +{ + int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); + if (!face_sets) { + return; + } + + if (!subdiv_ccg) { + return; + } + + CCGKey key; + BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); + for (int i = 0; i < mesh->totloop; i++) { + const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, i); + const bool is_hidden = (face_sets[face_index] < 0); + + /* Avoid creating and modifying the grid_hidden bitmap if the base mesh face is visible and + * there is not bitmap for the grid. This is because missing grid_hidden implies grid is fully + * visible. */ + if (is_hidden) { + BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg, i); + } + + BLI_bitmap *gh = subdiv_ccg->grid_hidden[i]; + if (gh) { + BLI_bitmap_set_all(gh, is_hidden, key.grid_area); + } + } +} + +void BKE_sculpt_sync_face_set_visibility(struct Mesh *mesh, struct SubdivCCG *subdiv_ccg) +{ + sculpt_sync_face_sets_visibility_to_base_mesh(mesh); + sculpt_sync_face_sets_visibility_to_grids(mesh, subdiv_ccg); +} + static PBVH *build_pbvh_for_dynamic_topology(Object *ob) { PBVH *pbvh = BKE_pbvh_new(); @@ -1850,6 +1908,8 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri); + BKE_sculpt_sync_face_set_visibility(me, NULL); + BKE_pbvh_build_mesh(pbvh, me, me->mpoly, @@ -1882,6 +1942,10 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); PBVH *pbvh = BKE_pbvh_new(); BKE_pbvh_respect_hide_set(pbvh, respect_hide); + + Mesh *base_mesh = BKE_mesh_from_object(ob); + BKE_sculpt_sync_face_set_visibility(base_mesh, subdiv_ccg); + BKE_pbvh_build_grids(pbvh, subdiv_ccg->grids, subdiv_ccg->num_grids, diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c index 11d5df4f672..bc1b79f62c5 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.c +++ b/source/blender/blenkernel/intern/subdiv_ccg.c @@ -1922,4 +1922,15 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const Subdi return SUBDIV_CCG_ADJACENT_NONE; } +void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG *subdiv_ccg, int grid_index) +{ + if (subdiv_ccg->grid_hidden[grid_index] != NULL) { + return; + } + + CCGKey key; + BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); + subdiv_ccg->grid_hidden[grid_index] = BLI_BITMAP_NEW(key.grid_area, __func__); +} + /** \} */ -- cgit v1.2.3