diff options
-rw-r--r-- | source/blender/blenkernel/BKE_paint.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/paint.c | 64 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 3 |
3 files changed, 63 insertions, 9 deletions
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index dfd7dafe2eb..41185173a0c 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -583,6 +583,11 @@ void BKE_sculpt_bvh_update_from_ccg(struct PBVH *pbvh, struct SubdivCCG *subdiv_ * updated according to the face sets. */ void BKE_sculpt_sync_face_set_visibility(struct Mesh *mesh, struct SubdivCCG *subdiv_ccg); +/* Ensures that a Face Set datalayers exists. If it does not, it creates one respecting the + * visibility stored in the vertices of the mesh. If it does, it copies the visibility from the + * mesh to the Face Sets. */ +void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(struct Mesh *mesh); + bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d); enum { diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 3ac9db0eb78..f07b98199bc 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1609,14 +1609,10 @@ static void sculpt_update_object(Depsgraph *depsgraph, /* Sculpt Face Sets. */ if (use_face_sets) { if (!CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS)) { - ss->face_sets = CustomData_add_layer( - &me->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, me->totpoly); - for (int i = 0; i < me->totpoly; i++) { - ss->face_sets[i] = 1; - } - - /* Set the default face set color if the datalayer did not exist. */ - me->face_sets_color_default = 1; + /* By checking here if the datalayer already exist this avoids copying the visibility from + * the mesh and looping over all vertices on every sculpt editing operation, using this + * function only the first time the Face Sets datalayer needs to be created. */ + BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(me); } ss->face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS); } @@ -1881,6 +1877,57 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc return deformed; } +void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(Mesh *mesh) +{ + const int face_sets_default_visible_id = 1; + const int face_sets_default_hidden_id = -(face_sets_default_visible_id + 1); + + bool initialize_new_face_sets = false; + + if (CustomData_has_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)) { + /* Make everything visible. */ + int *current_face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); + for (int i = 0; i < mesh->totpoly; i++) { + current_face_sets[i] = abs(current_face_sets[i]); + } + } + else { + initialize_new_face_sets = true; + int *new_face_sets = CustomData_add_layer( + &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, mesh->totpoly); + + /* Initialize the new Face Set datalayer with a default valid visible ID and set the default + * color to render it white. */ + for (int i = 0; i < mesh->totpoly; i++) { + new_face_sets[i] = face_sets_default_visible_id; + } + mesh->face_sets_color_default = face_sets_default_visible_id; + } + + int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); + + /* Show the only the face sets that have all visibile vertices. */ + for (int i = 0; i < mesh->totpoly; i++) { + for (int l = 0; l < mesh->mpoly[i].totloop; l++) { + MLoop *loop = &mesh->mloop[mesh->mpoly[i].loopstart + l]; + if (mesh->mvert[loop->v].flag & ME_HIDE) { + if (initialize_new_face_sets) { + /* When initializing a new Face Set datalayer, assing a new hidden Face Set ID to hidden + * vertices. This way, we get at initial split in two Face Sets between hidden and + * visible vertices based on the previous mesh visibily from other mode that can be + * useful in some cases. */ + face_sets[i] = face_sets_default_hidden_id; + } + else { + /* Otherwise, set the already existing Face Set ID to hidden. */ + face_sets[i] = -abs(face_sets[i]); + } + break; + } + } + } +} + static void sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh) { int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); @@ -1948,6 +1995,7 @@ static void sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *sub void BKE_sculpt_sync_face_set_visibility(struct Mesh *mesh, struct SubdivCCG *subdiv_ccg) { + BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(mesh); sculpt_sync_face_sets_visibility_to_base_mesh(mesh); sculpt_sync_face_sets_visibility_to_grids(mesh, subdiv_ccg); } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 12dbdc686ec..458aca1279c 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -8077,7 +8077,8 @@ static void sculpt_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob) /* Update the Face Sets visibility with the vertex visibility changes that may have been done * outside Sculpt Mode */ - SCULPT_visibility_sync_all_vertex_to_face_sets(ob->sculpt); + Mesh *mesh = ob->data; + BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(mesh); } static int ed_object_sculptmode_flush_recalc_flag(Scene *scene, |