diff options
18 files changed, 166 insertions, 328 deletions
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index eef91bacc2f..774765c3ca1 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -529,13 +529,16 @@ typedef struct SculptSession { /* Mesh Face Sets */ /* Total number of polys of the base mesh. */ int totfaces; - /* Face sets store its visibility in the sign of the integer, using the absolute value as the - * Face Set ID. Positive IDs are visible, negative IDs are hidden. - * The 0 ID is not used by the tools or the visibility system, it is just used when creating new + /* The 0 ID is not used by the tools or the visibility system, it is just used when creating new * geometry (the trim tool, for example) to detect which geometry was just added, so it can be * assigned a valid Face Set after creation. Tools are not intended to run with Face Sets IDs set * to 0. */ int *face_sets; + /** + * A reference to the ".hide_poly" attribute, to store whether (base) polygons are hidden. + * May be null. + */ + bool *hide_poly; /* BMesh for dynamic topology sculpting */ struct BMesh *bm; @@ -697,6 +700,12 @@ void BKE_sculpt_update_object_after_eval(struct Depsgraph *depsgraph, struct Obj struct MultiresModifierData *BKE_sculpt_multires_active(const struct Scene *scene, struct Object *ob); int *BKE_sculpt_face_sets_ensure(struct Mesh *mesh); +/** + * Create the attribute used to store face visibility and retrieve its data. + * Note that changes to the face visibility have to be propagated to other domains + * (see #SCULPT_visibility_sync_all_from_faces). + */ +bool *BKE_sculpt_hide_poly_ensure(struct Mesh *mesh); int BKE_sculpt_mask_layers_ensure(struct Object *ob, struct MultiresModifierData *mmd); void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene); @@ -704,31 +713,7 @@ 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); - -/** - * Individual function to sync the Face Set visibility to mesh and grids. - */ -void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(struct Mesh *mesh); -void BKE_sculpt_sync_face_sets_visibility_to_grids(struct Mesh *mesh, - struct SubdivCCG *subdiv_ccg); - -/** - * If a face set layer exists, initialize its visibility (sign) from the mesh's hidden values. - */ -void BKE_sculpt_face_sets_update_from_base_mesh_visibility(struct Mesh *mesh); - -/** - * Makes sculpt data consistent with other data on the mesh. - * - * \note IDs are expected to be original ones here, and calling code should ensure it updates its - * depsgraph properly after calling this function if it needs up-to-date evaluated data. - */ -void BKE_sculpt_ensure_orig_mesh_data(struct Object *object); +void BKE_sculpt_sync_face_visibility_to_grids(struct Mesh *mesh, struct SubdivCCG *subdiv_ccg); /** * Test if PBVH can be used directly for drawing, which is faster than diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 6a194698bd8..c32645e9ce7 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -380,8 +380,6 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden, int totgrid, int gridsize); -void BKE_pbvh_sync_face_sets_to_grids(PBVH *pbvh); - /** * Multi-res level, only valid for type == #PBVH_GRIDS. */ diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h index b30b707759c..ced7ff2aa71 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.h +++ b/source/blender/blenkernel/BKE_subdiv_ccg.h @@ -325,6 +325,7 @@ 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); +void BKE_subdiv_ccg_grid_hidden_free(SubdivCCG *subdiv_ccg, int grid_index); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 7ad9fd3a7c3..ea1bd3c1cc3 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1712,6 +1712,8 @@ static void sculpt_update_object( ss->face_sets = nullptr; } + ss->hide_poly = (bool *)CustomData_get_layer_named(&me->pdata, CD_PROP_BOOL, ".hide_poly"); + ss->subdiv_ccg = me_eval->runtime.subdiv_ccg; PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob); @@ -1720,6 +1722,7 @@ static void sculpt_update_object( BKE_pbvh_subdiv_cgg_set(ss->pbvh, ss->subdiv_ccg); BKE_pbvh_face_sets_set(ss->pbvh, ss->face_sets); + BKE_pbvh_update_hide_attributes_from_mesh(ss->pbvh); BKE_pbvh_face_sets_color_set(ss->pbvh, me->face_sets_color_seed, me->face_sets_color_default); @@ -1940,29 +1943,21 @@ int *BKE_sculpt_face_sets_ensure(Mesh *mesh) &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CONSTRUCT, nullptr, mesh->totpoly)), mesh->totpoly}; - /* Initialize the new face sets with a default valid visible ID and set the default - * color to render it white. */ - if (hide_poly.is_single() && !hide_poly.get_internal_single()) { - face_sets.fill(1); - } - else { - const int face_sets_default_visible_id = 1; - const int face_sets_default_hidden_id = -2; - - const VArraySpan<bool> hide_poly_span{hide_poly}; - for (const int i : face_sets.index_range()) { - /* Assign a new hidden ID to hidden faces. This way we get at initial split in two Face Sets - * between hidden and visible faces based on the previous mesh visibly from other mode that - * can be useful in some cases. */ - face_sets[i] = hide_poly_span[i] ? face_sets_default_hidden_id : - face_sets_default_visible_id; - } - } - + face_sets.fill(1); mesh->face_sets_color_default = 1; return face_sets.data(); } +bool *BKE_sculpt_hide_poly_ensure(Mesh *mesh) +{ + if (bool *hide_poly = static_cast<bool *>( + CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly"))) { + return hide_poly; + } + return static_cast<bool *>(CustomData_add_layer_named( + &mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, mesh->totpoly, ".hide_poly")); +} + int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) { Mesh *me = static_cast<Mesh *>(ob->data); @@ -2082,11 +2077,11 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc return deformed; } -void BKE_sculpt_face_sets_update_from_base_mesh_visibility(Mesh *mesh) +void BKE_sculpt_sync_face_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg) { using namespace blender; using namespace blender::bke; - if (!CustomData_has_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)) { + if (!subdiv_ccg) { return; } @@ -2094,70 +2089,19 @@ void BKE_sculpt_face_sets_update_from_base_mesh_visibility(Mesh *mesh) const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( ".hide_poly", ATTR_DOMAIN_FACE, false); if (hide_poly.is_single() && !hide_poly.get_internal_single()) { + /* Nothing is hidden, so we can just remove all visibility bitmaps. */ + for (const int i : hide_poly.index_range()) { + BKE_subdiv_ccg_grid_hidden_free(subdiv_ccg, i); + } return; } - MutableSpan<int> face_sets{ - static_cast<int *>(CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)), mesh->totpoly}; - - for (const int i : hide_poly.index_range()) { - face_sets[i] = hide_poly[i] ? -std::abs(face_sets[i]) : std::abs(face_sets[i]); - } -} - -static void set_hide_poly_from_face_sets(Mesh &mesh) -{ - using namespace blender; - using namespace blender::bke; - if (!CustomData_has_layer(&mesh.pdata, CD_SCULPT_FACE_SETS)) { - return; - } - - const Span<int> face_sets{ - static_cast<const int *>(CustomData_get_layer(&mesh.pdata, CD_SCULPT_FACE_SETS)), - mesh.totpoly}; - - MutableAttributeAccessor attributes = mesh.attributes_for_write(); - if (std::all_of( - face_sets.begin(), face_sets.end(), [&](const int value) { return value > 0; })) { - attributes.remove(".hide_poly"); - return; - } - - SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_only_span<bool>( - ".hide_poly", ATTR_DOMAIN_FACE); - if (!hide_poly) { - return; - } - for (const int i : hide_poly.span.index_range()) { - hide_poly.span[i] = face_sets[i] < 0; - } - hide_poly.finish(); -} - -void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh) -{ - set_hide_poly_from_face_sets(*mesh); - BKE_mesh_flush_hidden_from_polys(mesh); -} - -void BKE_sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg) -{ - const int *face_sets = static_cast<const int *>( - CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)); - if (!face_sets) { - return; - } - - if (!subdiv_ccg) { - return; - } - + const VArraySpan<bool> hide_poly_span(hide_poly); 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); + const bool is_hidden = hide_poly_span[face_index]; /* 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 @@ -2173,41 +2117,6 @@ void BKE_sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv } } -void BKE_sculpt_sync_face_set_visibility(Mesh *mesh, SubdivCCG *subdiv_ccg) -{ - BKE_sculpt_face_sets_update_from_base_mesh_visibility(mesh); - BKE_sculpt_sync_face_sets_visibility_to_base_mesh(mesh); - BKE_sculpt_sync_face_sets_visibility_to_grids(mesh, subdiv_ccg); -} - -void BKE_sculpt_ensure_orig_mesh_data(Object *object) -{ - Mesh *mesh = BKE_mesh_from_object(object); - BLI_assert(object->mode == OB_MODE_SCULPT); - - /* Copy the current mesh visibility to the Face Sets. */ - BKE_sculpt_face_sets_update_from_base_mesh_visibility(mesh); - - /* Tessfaces aren't used and will become invalid. */ - BKE_mesh_tessface_clear(mesh); - - /* We always need to flush updates from depsgraph here, since at the very least - * `BKE_sculpt_face_sets_update_from_base_mesh_visibility()` will have updated some data layer of - * the mesh. - * - * All known potential sources of updates: - * - Addition of, or changes to, the `CD_SCULPT_FACE_SETS` data layer - * (`BKE_sculpt_face_sets_update_from_base_mesh_visibility`). - * - Addition of a `CD_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`). - * - Object has any active modifier (modifier stack can be different in Sculpt mode). - * - Multires: - * + Differences of subdiv levels between sculpt and object modes - * (`mmd->sculptlvl != mmd->lvl`). - * + Addition of a `CD_GRID_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`). - */ - DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY); -} - static PBVH *build_pbvh_for_dynamic_topology(Object *ob) { PBVH *pbvh = BKE_pbvh_new(); @@ -2239,8 +2148,6 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool BKE_mesh_recalc_looptri( loops.data(), polys.data(), verts.data(), me->totloop, me->totpoly, looptri); - BKE_sculpt_sync_face_set_visibility(me, nullptr); - BKE_pbvh_build_mesh(pbvh, me, polys.data(), @@ -2275,7 +2182,7 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect 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_sculpt_sync_face_visibility_to_grids(base_mesh, subdiv_ccg); BKE_pbvh_build_grids(pbvh, subdiv_ccg->grids, @@ -2369,10 +2276,10 @@ bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const View3D *UNUSED(v3d) void BKE_paint_face_set_overlay_color_get(const int face_set, const int seed, uchar r_color[4]) { float rgba[4]; - float random_mod_hue = GOLDEN_RATIO_CONJUGATE * (abs(face_set) + (seed % 10)); + float random_mod_hue = GOLDEN_RATIO_CONJUGATE * (face_set + (seed % 10)); random_mod_hue = random_mod_hue - floorf(random_mod_hue); - const float random_mod_sat = BLI_hash_int_01(abs(face_set) + seed + 1); - const float random_mod_val = BLI_hash_int_01(abs(face_set) + seed + 2); + const float random_mod_sat = BLI_hash_int_01(face_set + seed + 1); + const float random_mod_val = BLI_hash_int_01(face_set + seed + 2); hsv_to_rgb(random_mod_hue, 0.6f + (random_mod_sat * 0.25f), 1.0f - (random_mod_val * 0.35f), diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 2e273e076d5..b3de2b17dd8 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -366,26 +366,6 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden, return totquad; } -void BKE_pbvh_sync_face_sets_to_grids(PBVH *pbvh) -{ - const int gridsize = pbvh->gridkey.grid_size; - for (int i = 0; i < pbvh->totgrid; i++) { - BLI_bitmap *gh = pbvh->grid_hidden[i]; - const int face_index = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, i); - if (!gh && pbvh->face_sets[face_index] < 0) { - gh = pbvh->grid_hidden[i] = BLI_BITMAP_NEW(pbvh->gridkey.grid_area, - "partialvis_update_grids"); - } - if (gh) { - for (int y = 0; y < gridsize; y++) { - for (int x = 0; x < gridsize; x++) { - BLI_BITMAP_SET(gh, y * gridsize + x, pbvh->face_sets[face_index] < 0); - } - } - } - } -} - static void build_grid_leaf_node(PBVH *pbvh, PBVHNode *node) { int totquads = BKE_pbvh_count_grid_quads( @@ -3218,7 +3198,7 @@ const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh) const bool *BKE_pbvh_get_poly_hide(const PBVH *pbvh) { - BLI_assert(pbvh->header.type == PBVH_FACES); + BLI_assert(ELEM(pbvh->header.type, PBVH_FACES, PBVH_GRIDS)); return pbvh->hide_poly; } diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c index c956ef09af3..03937b270bc 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.c +++ b/source/blender/blenkernel/intern/subdiv_ccg.c @@ -2043,6 +2043,11 @@ void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG *subdiv_ccg, int grid_index) subdiv_ccg->grid_hidden[grid_index] = BLI_BITMAP_NEW(key.grid_area, __func__); } +void BKE_subdiv_ccg_grid_hidden_free(SubdivCCG *subdiv_ccg, int grid_index) +{ + MEM_SAFE_FREE(subdiv_ccg->grid_hidden[grid_index]); +} + static void subdiv_ccg_coord_to_ptex_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, int *r_ptex_face_index, diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 1692fd2d747..244f74cfe59 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -3368,5 +3368,15 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } FOREACH_NODETREE_END; } + + /* Face sets no longer store whether the corresponding face is hidden. */ + LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) { + int *face_sets = (int *)CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); + if (face_sets) { + for (int i = 0; i < mesh->totpoly; i++) { + face_sets[i] = abs(face_sets[i]); + } + } + } } } diff --git a/source/blender/editors/mesh/meshtools.cc b/source/blender/editors/mesh/meshtools.cc index 108fa210075..831ab858b1c 100644 --- a/source/blender/editors/mesh/meshtools.cc +++ b/source/blender/editors/mesh/meshtools.cc @@ -317,15 +317,10 @@ static void mesh_join_offset_face_sets_ID(const Mesh *mesh, int *face_set_offset for (int f = 0; f < mesh->totpoly; f++) { /* As face sets encode the visibility in the integer sign, the offset needs to be added or * subtracted depending on the initial sign of the integer to get the new ID. */ - if (abs(face_sets[f]) <= *face_set_offset) { - if (face_sets[f] > 0) { - face_sets[f] += *face_set_offset; - } - else { - face_sets[f] -= *face_set_offset; - } + if (face_sets[f] <= *face_set_offset) { + face_sets[f] += *face_set_offset; } - max_face_set = max_ii(max_face_set, abs(face_sets[f])); + max_face_set = max_ii(max_face_set, face_sets[f]); } *face_set_offset = max_face_set; } diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc index aa8dc4debd9..adc07d0b411 100644 --- a/source/blender/editors/object/object_remesh.cc +++ b/source/blender/editors/object/object_remesh.cc @@ -186,7 +186,6 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) } if (ob->mode == OB_MODE_SCULPT) { - BKE_sculpt_ensure_orig_mesh_data(ob); ED_sculpt_undo_geometry_end(ob); } @@ -912,7 +911,6 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update } if (ob->mode == OB_MODE_SCULPT) { - BKE_sculpt_ensure_orig_mesh_data(ob); ED_sculpt_undo_geometry_end(ob); } diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index 2b80c62a0ba..9e435ee0748 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -386,8 +386,6 @@ static int hide_show_exec(bContext *C, wmOperator *op) BKE_pbvh_update_hide_attributes_from_mesh(pbvh); } - SCULPT_visibility_sync_all_vertex_to_face_sets(ob->sculpt); - DEG_id_tag_update(&ob->id, ID_RECALC_SHADING); ED_region_tag_redraw(region); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 089a8a4cb54..3ead299a447 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -390,19 +390,15 @@ bool SCULPT_vertex_visible_get(SculptSession *ss, PBVHVertRef vertex) void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible) { BLI_assert(ss->face_sets != NULL); + BLI_assert(ss->hide_poly != NULL); switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: case PBVH_GRIDS: for (int i = 0; i < ss->totfaces; i++) { - if (abs(ss->face_sets[i]) != face_set) { + if (ss->face_sets[i] != face_set) { continue; } - if (visible) { - ss->face_sets[i] = abs(ss->face_sets[i]); - } - else { - ss->face_sets[i] = -abs(ss->face_sets[i]); - } + ss->hide_poly[i] = !visible; } break; case PBVH_BMESH: @@ -410,14 +406,15 @@ void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visibl } } -void SCULPT_face_sets_visibility_invert(SculptSession *ss) +void SCULPT_face_visibility_all_invert(SculptSession *ss) { BLI_assert(ss->face_sets != NULL); + BLI_assert(ss->hide_poly != NULL); switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: case PBVH_GRIDS: for (int i = 0; i < ss->totfaces; i++) { - ss->face_sets[i] *= -1; + ss->hide_poly[i] = !ss->hide_poly[i]; } break; case PBVH_BMESH: @@ -425,47 +422,29 @@ void SCULPT_face_sets_visibility_invert(SculptSession *ss) } } -void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible) +void SCULPT_face_visibility_all_set(SculptSession *ss, bool visible) { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: case PBVH_GRIDS: - if (!ss->face_sets) { - return; - } - for (int i = 0; i < ss->totfaces; i++) { - - /* This can run on geometry without a face set assigned, so its ID sign can't be changed to - * modify the visibility. Force that geometry to the ID 1 to enable changing the visibility - * here. */ - if (ss->face_sets[i] == SCULPT_FACE_SET_NONE) { - ss->face_sets[i] = 1; - } - - if (visible) { - ss->face_sets[i] = abs(ss->face_sets[i]); - } - else { - ss->face_sets[i] = -abs(ss->face_sets[i]); - } - } + BLI_assert(ss->hide_poly != NULL); + memset(ss->hide_poly, !visible, sizeof(bool) * ss->totfaces); break; case PBVH_BMESH: break; } } -bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, PBVHVertRef vertex) +bool SCULPT_vertex_any_face_visible_get(SculptSession *ss, PBVHVertRef vertex) { - const bool *hide_poly = BKE_pbvh_get_poly_hide(ss->pbvh); - if (!hide_poly) { - return true; - } switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { + if (!ss->hide_poly) { + return true; + } MeshElemMap *vert_map = &ss->pmap[vertex.i]; for (int j = 0; j < ss->pmap[vertex.i].count; j++) { - if (!hide_poly[vert_map->indices[j]]) { + if (!ss->hide_poly[vert_map->indices[j]]) { return true; } } @@ -479,17 +458,16 @@ bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, PBVHVertRef verte return true; } -bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, PBVHVertRef vertex) +bool SCULPT_vertex_all_faces_visible_get(const SculptSession *ss, PBVHVertRef vertex) { - const bool *hide_poly = BKE_pbvh_get_poly_hide(ss->pbvh); - if (!hide_poly) { - return true; - } switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { + if (!ss->hide_poly) { + return true; + } MeshElemMap *vert_map = &ss->pmap[vertex.i]; for (int j = 0; j < ss->pmap[vertex.i].count; j++) { - if (hide_poly[vert_map->indices[j]]) { + if (ss->hide_poly[vert_map->indices[j]]) { return false; } } @@ -498,10 +476,13 @@ bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, PBVHVertRe case PBVH_BMESH: return true; case PBVH_GRIDS: { + if (!ss->hide_poly) { + return true; + } const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); const int grid_index = vertex.i / key->grid_area; const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index); - return !hide_poly[face_index]; + return !ss->hide_poly[face_index]; } } return true; @@ -514,11 +495,15 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_ BLI_assert(ss->face_sets != NULL); MeshElemMap *vert_map = &ss->pmap[vertex.i]; for (int j = 0; j < ss->pmap[vertex.i].count; j++) { - if (ss->face_sets[vert_map->indices[j]] > 0) { - ss->face_sets[vert_map->indices[j]] = abs(face_set); + const int poly_index = vert_map->indices[j]; + if (ss->hide_poly && ss->hide_poly[poly_index]) { + /* Skip hidden faces conntected to the vertex. */ + continue; } + ss->face_sets[poly_index] = face_set; } - } break; + break; + } case PBVH_BMESH: break; case PBVH_GRIDS: { @@ -526,11 +511,13 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); const int grid_index = vertex.i / key->grid_area; const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index); - if (ss->face_sets[face_index] > 0) { - ss->face_sets[face_index] = abs(face_set); + if (ss->hide_poly && ss->hide_poly[face_index]) { + /* Skip the vertex if it's in a hidden face. */ + return; } - - } break; + ss->face_sets[face_index] = face_set; + break; + } } } @@ -595,19 +582,23 @@ bool SCULPT_vertex_has_face_set(SculptSession *ss, PBVHVertRef vertex, int face_ return true; } -void SCULPT_visibility_sync_all_face_sets_to_verts(Object *ob) +void SCULPT_visibility_sync_all_from_faces(Object *ob) { SculptSession *ss = ob->sculpt; Mesh *mesh = BKE_object_get_original_mesh(ob); switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { - BKE_sculpt_sync_face_sets_visibility_to_base_mesh(mesh); + /* We may have adjusted the ".hide_poly" attribute, now make the hide status attributes for + * vertices and edges consistent. */ + BKE_mesh_flush_hidden_from_polys(mesh); BKE_pbvh_update_hide_attributes_from_mesh(ss->pbvh); break; } case PBVH_GRIDS: { - BKE_sculpt_sync_face_sets_visibility_to_base_mesh(mesh); - BKE_sculpt_sync_face_sets_visibility_to_grids(mesh, ss->subdiv_ccg); + /* In addition to making the hide status of the base mesh consistent, we also have to + * propagate the status to the Multires grids. */ + BKE_mesh_flush_hidden_from_polys(mesh); + BKE_sculpt_sync_face_visibility_to_grids(mesh, ss->subdiv_ccg); break; } case PBVH_BMESH: @@ -615,46 +606,6 @@ void SCULPT_visibility_sync_all_face_sets_to_verts(Object *ob) } } -static void UNUSED_FUNCTION(sculpt_visibility_sync_vertex_to_face_sets)(SculptSession *ss, - PBVHVertRef vertex) -{ - MeshElemMap *vert_map = &ss->pmap[vertex.i]; - const bool visible = SCULPT_vertex_visible_get(ss, vertex); - for (int i = 0; i < ss->pmap[vertex.i].count; i++) { - if (visible) { - ss->face_sets[vert_map->indices[i]] = abs(ss->face_sets[vert_map->indices[i]]); - } - else { - ss->face_sets[vert_map->indices[i]] = -abs(ss->face_sets[vert_map->indices[i]]); - } - } -} - -void SCULPT_visibility_sync_all_vertex_to_face_sets(SculptSession *ss) -{ - if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) { - if (ss->face_sets == NULL) { - return; - } - for (int i = 0; i < ss->totfaces; i++) { - const MPoly *poly = &ss->mpoly[i]; - bool poly_visible = true; - for (int l = 0; l < poly->totloop; l++) { - const MLoop *loop = &ss->mloop[poly->loopstart + l]; - if (!SCULPT_vertex_visible_get(ss, BKE_pbvh_make_vref(loop->v))) { - poly_visible = false; - } - } - if (poly_visible) { - ss->face_sets[i] = abs(ss->face_sets[i]); - } - else { - ss->face_sets[i] = -abs(ss->face_sets[i]); - } - } - } -} - static bool sculpt_check_unique_face_set_in_base_mesh(SculptSession *ss, int index) { if (!ss->face_sets) { @@ -664,10 +615,10 @@ static bool sculpt_check_unique_face_set_in_base_mesh(SculptSession *ss, int ind int face_set = -1; for (int i = 0; i < ss->pmap[index].count; i++) { if (face_set == -1) { - face_set = abs(ss->face_sets[vert_map->indices[i]]); + face_set = ss->face_sets[vert_map->indices[i]]; } else { - if (abs(ss->face_sets[vert_map->indices[i]]) != face_set) { + if (ss->face_sets[vert_map->indices[i]] != face_set) { return false; } } @@ -751,8 +702,8 @@ int SCULPT_face_set_next_available_get(SculptSession *ss) } int next_face_set = 0; for (int i = 0; i < ss->totfaces; i++) { - if (abs(ss->face_sets[i]) > next_face_set) { - next_face_set = abs(ss->face_sets[i]); + if (ss->face_sets[i] > next_face_set) { + next_face_set = ss->face_sets[i]; } } next_face_set++; @@ -940,7 +891,7 @@ bool SCULPT_vertex_is_boundary(const SculptSession *ss, const PBVHVertRef vertex { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { - if (!SCULPT_vertex_all_face_sets_visible_get(ss, vertex)) { + if (!SCULPT_vertex_all_faces_visible_get(ss, vertex)) { return true; } return sculpt_check_boundary_vertex_in_base_mesh(ss, vertex.i); diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index 8aa645c6af5..90b92845b09 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -67,7 +67,7 @@ int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh) int next_face_set_id = 0; for (int i = 0; i < mesh->totpoly; i++) { - next_face_set_id = max_ii(next_face_set_id, abs(face_sets[i])); + next_face_set_id = max_ii(next_face_set_id, face_sets[i]); } next_face_set_id++; @@ -135,6 +135,10 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, if (!sculpt_brush_test_sq_fn(&test, poly_center)) { continue; } + const bool face_hidden = ss->hide_poly && ss->hide_poly[vert_map->indices[j]]; + if (face_hidden) { + continue; + } const float fade = bstrength * SCULPT_brush_strength_factor(ss, brush, vd.co, @@ -145,8 +149,8 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, vd.vertex, thread_id); - if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) { - ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set); + if (fade > 0.05f) { + ss->face_sets[vert_map->indices[j]] = ss->cache->paint_face_set; } } } @@ -750,7 +754,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op) SCULPT_undo_push_end(ob); /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */ - SCULPT_visibility_sync_all_face_sets_to_verts(ob); + SCULPT_visibility_sync_all_from_faces(ob); for (int i = 0; i < totnode; i++) { BKE_pbvh_node_mark_update_visibility(nodes[i]); @@ -854,10 +858,12 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (!pbvh_has_face_sets(ss->pbvh)) { + if (!ss->face_sets) { return OPERATOR_CANCELLED; } + Mesh *mesh = BKE_object_get_original_mesh(ob); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); const int tot_vert = SCULPT_vertex_count_get(ss); @@ -895,37 +901,49 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op) } } - for (int i = 0; i < ss->totfaces; i++) { - if (ss->face_sets[i] <= 0) { - hidden_vertex = true; - break; + if (ss->hide_poly) { + for (int i = 0; i < ss->totfaces; i++) { + if (ss->hide_poly[i]) { + hidden_vertex = true; + break; + } } } + ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh); + if (hidden_vertex) { - SCULPT_face_sets_visibility_all_set(ss, true); + SCULPT_face_visibility_all_set(ss, true); } else { - SCULPT_face_sets_visibility_all_set(ss, false); + SCULPT_face_visibility_all_set(ss, false); SCULPT_face_set_visibility_set(ss, active_face_set, true); } } if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ALL) { - SCULPT_face_sets_visibility_all_set(ss, true); + /* As an optimization, free the hide attribute when making all geometry visible. This allows + * reduced memory usage without manually clearing it later, and allows sculpt operations to + * avoid checking element's hide status. */ + CustomData_free_layer_named(&mesh->pdata, ".hide_poly", mesh->totpoly); + ss->hide_poly = NULL; + BKE_pbvh_update_hide_attributes_from_mesh(pbvh); } if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE) { - SCULPT_face_sets_visibility_all_set(ss, false); + ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh); + SCULPT_face_visibility_all_set(ss, false); SCULPT_face_set_visibility_set(ss, active_face_set, true); } if (mode == SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE) { + ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh); SCULPT_face_set_visibility_set(ss, active_face_set, false); } if (mode == SCULPT_FACE_SET_VISIBILITY_INVERT) { - SCULPT_face_sets_visibility_invert(ss); + ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh); + SCULPT_face_visibility_all_invert(ss); } /* For modes that use the cursor active vertex, update the rotation origin for viewport @@ -941,7 +959,7 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op) } /* Sync face sets visibility and vertex visibility. */ - SCULPT_visibility_sync_all_face_sets_to_verts(ob); + SCULPT_visibility_sync_all_from_faces(ob); SCULPT_undo_push_end(ob); @@ -1008,7 +1026,7 @@ static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator *UNUSE return OPERATOR_CANCELLED; } - if (!pbvh_has_face_sets(ss->pbvh)) { + if (!ss->face_sets) { return OPERATOR_CANCELLED; } @@ -1172,14 +1190,15 @@ static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool int first_face_set = SCULPT_FACE_SET_NONE; if (check_visible_only) { for (int f = 0; f < ss->totfaces; f++) { - if (face_sets[f] > 0) { - first_face_set = face_sets[f]; - break; + if (ss->hide_poly && ss->hide_poly[f]) { + continue; } + first_face_set = face_sets[f]; + break; } } else { - first_face_set = abs(face_sets[0]); + first_face_set = face_sets[0]; } if (first_face_set == SCULPT_FACE_SET_NONE) { @@ -1187,8 +1206,10 @@ static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool } for (int f = 0; f < ss->totfaces; f++) { - const int face_set_id = check_visible_only ? face_sets[f] : abs(face_sets[f]); - if (face_set_id != first_face_set) { + if (check_visible_only && ss->hide_poly && ss->hide_poly[f]) { + continue; + } + if (face_sets[f] != first_face_set) { return false; } } @@ -1222,9 +1243,10 @@ static void sculpt_face_set_delete_geometry(Object *ob, BMFace *f; BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { const int face_index = BM_elem_index_get(f); - const int face_set_id = modify_hidden ? abs(ss->face_sets[face_index]) : - ss->face_sets[face_index]; - BM_elem_flag_set(f, BM_ELEM_TAG, face_set_id == active_face_set_id); + if (!modify_hidden && ss->hide_poly && ss->hide_poly[face_index]) { + continue; + } + BM_elem_flag_set(f, BM_ELEM_TAG, ss->face_sets[face_index] == active_face_set_id); } BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES); BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); @@ -1353,7 +1375,7 @@ static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **node PBVH *pbvh = ss->pbvh; /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */ - SCULPT_visibility_sync_all_face_sets_to_verts(ob); + SCULPT_visibility_sync_all_from_faces(ob); for (int i = 0; i < totnode; i++) { BKE_pbvh_node_mark_update_visibility(nodes[i]); diff --git a/source/blender/editors/sculpt_paint/sculpt_geodesic.c b/source/blender/editors/sculpt_paint/sculpt_geodesic.c index c0856ab21d2..5dd602bc36d 100644 --- a/source/blender/editors/sculpt_paint/sculpt_geodesic.c +++ b/source/blender/editors/sculpt_paint/sculpt_geodesic.c @@ -170,8 +170,6 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, } } - const bool *hide_poly = BKE_pbvh_get_poly_hide(ss->pbvh); - /* Add edges adjacent to an initial vertex to the queue. */ for (int i = 0; i < totedge; i++) { const int v1 = edges[i].v1; @@ -201,7 +199,7 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, if (ss->epmap[e].count != 0) { for (int poly_map_index = 0; poly_map_index < ss->epmap[e].count; poly_map_index++) { const int poly = ss->epmap[e].indices[poly_map_index]; - if (hide_poly && hide_poly[poly]) { + if (ss->hide_poly && ss->hide_poly[poly]) { continue; } const MPoly *mpoly = &polys[poly]; diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 7a72e5cc84b..681c90bafb6 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -1004,9 +1004,13 @@ void SCULPT_connected_components_ensure(Object *ob); void SCULPT_vertex_visible_set(SculptSession *ss, PBVHVertRef vertex, bool visible); bool SCULPT_vertex_visible_get(SculptSession *ss, PBVHVertRef vertex); +bool SCULPT_vertex_all_faces_visible_get(const SculptSession *ss, PBVHVertRef vertex); +bool SCULPT_vertex_any_face_visible_get(SculptSession *ss, PBVHVertRef vertex); -void SCULPT_visibility_sync_all_face_sets_to_verts(struct Object *ob); -void SCULPT_visibility_sync_all_vertex_to_face_sets(struct SculptSession *ss); +void SCULPT_face_visibility_all_invert(SculptSession *ss); +void SCULPT_face_visibility_all_set(SculptSession *ss, bool visible); + +void SCULPT_visibility_sync_all_from_faces(struct Object *ob); /** \} */ @@ -1024,11 +1028,6 @@ bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, PBVHVertRef vertex); int SCULPT_face_set_next_available_get(SculptSession *ss); void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible); -bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, PBVHVertRef vertex); -bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, PBVHVertRef vertex); - -void SCULPT_face_sets_visibility_invert(SculptSession *ss); -void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible); /** \} */ diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.c b/source/blender/editors/sculpt_paint/sculpt_ops.c index f942aac2e18..cfd02438188 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.c +++ b/source/blender/editors/sculpt_paint/sculpt_ops.c @@ -300,8 +300,6 @@ static void sculpt_init_session(Main *bmain, Depsgraph *depsgraph, Scene *scene, ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); ob->sculpt->mode_type = OB_MODE_SCULPT; - BKE_sculpt_ensure_orig_mesh_data(ob); - BKE_scene_graph_evaluated_ensure(depsgraph, bmain); /* This function expects a fully evaluated depsgraph. */ diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 51af8f878e5..9bf63ad1468 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -767,7 +767,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase BKE_sculpt_update_object_for_edit(depsgraph, ob, true, need_mask, false); - SCULPT_visibility_sync_all_face_sets_to_verts(ob); + SCULPT_visibility_sync_all_from_faces(ob); BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility); @@ -923,7 +923,6 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase } if (update_visibility) { - SCULPT_visibility_sync_all_vertex_to_face_sets(ss); BKE_pbvh_update_visibility(ss->pbvh); } diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 78f595cbff2..c0527357663 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -406,7 +406,7 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id, uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; if (show_face_sets) { - const int fset = abs(sculpt_face_sets[lt->poly]); + const int fset = sculpt_face_sets[lt->poly]; /* Skip for the default color Face Set to render it white. */ if (fset != face_sets_color_default) { BKE_paint_face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color); @@ -766,7 +766,7 @@ void GPU_pbvh_grid_buffers_update(PBVHGPUFormat *vbo_id, if (show_face_sets && subdiv_ccg && sculpt_face_sets) { const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, grid_index); - const int fset = abs(sculpt_face_sets[face_index]); + const int fset = sculpt_face_sets[face_index]; /* Skip for the default color Face Set to render it white. */ if (fset != face_sets_color_default) { BKE_paint_face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index cfc3a832166..467bfa57538 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -497,12 +497,6 @@ static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), Poin void rna_Object_data_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Object *object = (Object *)ptr->data; - - if (object->mode == OB_MODE_SCULPT) { - BKE_sculpt_ensure_orig_mesh_data(object); - } - rna_Object_internal_update_data_dependency(bmain, scene, ptr); } |