diff options
50 files changed, 923 insertions, 340 deletions
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 6e27fd2d80f..8bad89a9211 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -11,7 +11,9 @@ #include "BLI_sys_types.h" #include "BLI_utildefines.h" #ifdef __cplusplus +# include "BLI_set.hh" # include "BLI_span.hh" +# include "BLI_string_ref.hh" # include "BLI_vector.hh" #endif @@ -141,6 +143,15 @@ void CustomData_copy(const struct CustomData *source, eCDAllocType alloctype, int totelem); +/** + * Like #CustomData_copy but skips copying layers that are stored as flags on #BMesh. + */ +void CustomData_copy_mesh_to_bmesh(const struct CustomData *source, + struct CustomData *dest, + eCustomDataMask mask, + eCDAllocType alloctype, + int totelem); + /* BMESH_TODO, not really a public function but readfile.c needs it */ void CustomData_update_typemap(struct CustomData *data); @@ -155,6 +166,15 @@ bool CustomData_merge(const struct CustomData *source, int totelem); /** + * Like #CustomData_copy but skips copying layers that are stored as flags on #BMesh. + */ +bool CustomData_merge_mesh_to_bmesh(const struct CustomData *source, + struct CustomData *dest, + eCustomDataMask mask, + eCDAllocType alloctype, + int totelem); + +/** * Reallocate custom data to a new element count. * Only affects on data layers which are owned by the CustomData itself, * referenced data is kept unchanged, @@ -697,7 +717,8 @@ void CustomData_data_transfer(const struct MeshPairRemap *me_remap, * the struct. */ void CustomData_blend_write_prepare(CustomData &data, - blender::Vector<CustomDataLayer, 16> &layers_to_write); + blender::Vector<CustomDataLayer, 16> &layers_to_write, + const blender::Set<blender::StringRef> &skip_names = {}); /** * \param layers_to_write: Layers created by #CustomData_blend_write_prepare. diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 17f541b362e..b0516e96562 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -865,19 +865,7 @@ void BKE_mesh_merge_customdata_for_apply_modifier(struct Mesh *me); /** * Update the hide flag for edges and faces from the corresponding flag in verts. */ -void BKE_mesh_flush_hidden_from_verts_ex(const struct MVert *mvert, - const struct MLoop *mloop, - struct MEdge *medge, - int totedge, - struct MPoly *mpoly, - int totpoly); void BKE_mesh_flush_hidden_from_verts(struct Mesh *me); -void BKE_mesh_flush_hidden_from_polys_ex(struct MVert *mvert, - const struct MLoop *mloop, - struct MEdge *medge, - int totedge, - const struct MPoly *mpoly, - int totpoly); void BKE_mesh_flush_hidden_from_polys(struct Mesh *me); /** * simple poly -> vert/edge selection. diff --git a/source/blender/blenkernel/BKE_mesh_legacy_convert.h b/source/blender/blenkernel/BKE_mesh_legacy_convert.h index 909fd0e0dea..bbc61d5af5e 100644 --- a/source/blender/blenkernel/BKE_mesh_legacy_convert.h +++ b/source/blender/blenkernel/BKE_mesh_legacy_convert.h @@ -18,6 +18,16 @@ struct Mesh; struct MFace; /** + * Convert the hidden element attributes to the old flag format for writing. + */ +void BKE_mesh_legacy_convert_hide_layers_to_flags(struct Mesh *mesh); +/** + * Convert the old hide flags (#ME_HIDE) to the hidden element attribute for reading. + * Only add the attributes when there are any elements in each domain hidden. + */ +void BKE_mesh_legacy_convert_flags_to_hide_layers(struct Mesh *mesh); + +/** * Recreate #MFace Tessellation. * * \note This doesn't use multi-threading like #BKE_mesh_recalc_looptri since diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index 525483bae19..abe590b6806 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -92,6 +92,7 @@ typedef struct MeshElemMap { /* mapping */ UvVertMap *BKE_mesh_uv_vert_map_create(const struct MPoly *mpoly, + const bool *hide_poly, const struct MLoop *mloop, const struct MLoopUV *mloopuv, unsigned int totpoly, diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 8b9deadc960..fa67ff08383 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -213,7 +213,7 @@ bool BKE_paint_always_hide_test(struct Object *ob); * Returns non-zero if any of the face's vertices are hidden, zero otherwise. */ bool paint_is_face_hidden(const struct MLoopTri *lt, - const struct MVert *mvert, + const bool *hide_vert, const struct MLoop *mloop); /** * Returns non-zero if any of the corners of the grid diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index af7effe806c..2be3f323d07 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -533,6 +533,7 @@ typedef struct PBVHVertexIter { /* mesh */ struct MVert *mverts; float (*vert_normals)[3]; + const bool *hide_vert; int totvert; const int *vert_indices; float *vmask; @@ -593,7 +594,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m else if (vi.mverts) { \ vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \ if (vi.respect_hide) { \ - vi.visible = !(vi.mvert->flag & ME_HIDE); \ + vi.visible = !(vi.hide_vert && vi.hide_vert[vi.vert_indices[vi.gx]]); \ if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \ continue; \ } \ @@ -667,6 +668,8 @@ void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh); const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3]; +const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh); +bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh); PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node); void BKE_pbvh_node_color_buffer_free(PBVH *pbvh); diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 1af3cde1821..b9995796a21 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -56,7 +56,7 @@ const char *no_procedural_access_message = bool allow_procedural_attribute_access(StringRef attribute_name) { - return !attribute_name.startswith(".selection"); + return !attribute_name.startswith(".selection") && !attribute_name.startswith(".hide"); } static int attribute_data_type_complexity(const eCustomDataType data_type) diff --git a/source/blender/blenkernel/intern/bvhutils.cc b/source/blender/blenkernel/intern/bvhutils.cc index 03dd5c89b70..d0b57b45d35 100644 --- a/source/blender/blenkernel/intern/bvhutils.cc +++ b/source/blender/blenkernel/intern/bvhutils.cc @@ -27,6 +27,8 @@ #include "MEM_guardedalloc.h" +using blender::VArray; + /* -------------------------------------------------------------------- */ /** \name BVHCache * \{ */ @@ -1181,9 +1183,13 @@ static BLI_bitmap *loose_edges_map_get(const MEdge *medge, } static BLI_bitmap *looptri_no_hidden_map_get(const MPoly *mpoly, + const VArray<bool> &hide_poly, const int looptri_len, int *r_looptri_active_len) { + if (hide_poly.is_single() && !hide_poly.get_internal_single()) { + return nullptr; + } BLI_bitmap *looptri_mask = BLI_BITMAP_NEW(looptri_len, __func__); int looptri_no_hidden_len = 0; @@ -1191,8 +1197,7 @@ static BLI_bitmap *looptri_no_hidden_map_get(const MPoly *mpoly, int i_poly = 0; while (looptri_iter != looptri_len) { int mp_totlooptri = mpoly[i_poly].totloop - 2; - const MPoly &mp = mpoly[i_poly]; - if (mp.flag & ME_HIDE) { + if (hide_poly[i_poly]) { looptri_iter += mp_totlooptri; } else { @@ -1276,9 +1281,15 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, 0.0f, tree_type, 6, mesh->mvert, mesh->mface, mesh->totface, nullptr, -1); break; - case BVHTREE_FROM_LOOPTRI_NO_HIDDEN: - mask = looptri_no_hidden_map_get(mesh->mpoly, looptri_len, &mask_bits_act_len); + case BVHTREE_FROM_LOOPTRI_NO_HIDDEN: { + blender::bke::AttributeAccessor attributes = blender::bke::mesh_attributes(*mesh); + mask = looptri_no_hidden_map_get( + mesh->mpoly, + attributes.lookup_or_default(".hide_poly", ATTR_DOMAIN_FACE, false), + looptri_len, + &mask_bits_act_len); ATTR_FALLTHROUGH; + } case BVHTREE_FROM_LOOPTRI: data->tree = bvhtree_from_mesh_looptri_create_tree(0.0f, tree_type, diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index acb978642aa..69825031795 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -26,6 +26,7 @@ #include "BLI_math_vector.hh" #include "BLI_mempool.h" #include "BLI_path_util.h" +#include "BLI_set.hh" #include "BLI_span.hh" #include "BLI_string.h" #include "BLI_string_ref.hh" @@ -58,6 +59,7 @@ #include "data_transfer_intern.h" using blender::IndexRange; +using blender::Set; using blender::Span; using blender::StringRef; using blender::Vector; @@ -2342,6 +2344,43 @@ bool CustomData_merge(const CustomData *source, return changed; } +static bool attribute_stored_in_bmesh_flag(const StringRef name) +{ + return ELEM(name, ".hide_vert", ".hide_edge", ".hide_poly"); +} + +static CustomData shallow_copy_remove_non_bmesh_attributes(const CustomData &src) +{ + Vector<CustomDataLayer> dst_layers; + for (const CustomDataLayer &layer : Span<CustomDataLayer>{src.layers, src.totlayer}) { + if (!attribute_stored_in_bmesh_flag(layer.name)) { + dst_layers.append(layer); + } + } + + CustomData dst = src; + dst.layers = static_cast<CustomDataLayer *>( + MEM_calloc_arrayN(dst_layers.size(), sizeof(CustomDataLayer), __func__)); + dst.totlayer = dst_layers.size(); + memcpy(dst.layers, dst_layers.data(), dst_layers.as_span().size_in_bytes()); + + CustomData_update_typemap(&dst); + + return dst; +} + +bool CustomData_merge_mesh_to_bmesh(const CustomData *source, + CustomData *dest, + const eCustomDataMask mask, + const eCDAllocType alloctype, + const int totelem) +{ + CustomData source_copy = shallow_copy_remove_non_bmesh_attributes(*source); + const bool result = CustomData_merge(&source_copy, dest, mask, alloctype, totelem); + MEM_SAFE_FREE(source_copy.layers); + return result; +} + void CustomData_realloc(CustomData *data, const int totelem) { BLI_assert(totelem >= 0); @@ -2373,6 +2412,17 @@ void CustomData_copy(const CustomData *source, CustomData_merge(source, dest, mask, alloctype, totelem); } +void CustomData_copy_mesh_to_bmesh(const CustomData *source, + CustomData *dest, + const eCustomDataMask mask, + const eCDAllocType alloctype, + const int totelem) +{ + CustomData source_copy = shallow_copy_remove_non_bmesh_attributes(*source); + CustomData_copy(&source_copy, dest, mask, alloctype, totelem); + MEM_SAFE_FREE(source_copy.layers); +} + static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem) { const LayerTypeInfo *typeInfo; @@ -4303,7 +4353,9 @@ void CustomData_file_write_info(int type, const char **r_struct_name, int *r_str *r_struct_num = typeInfo->structnum; } -void CustomData_blend_write_prepare(CustomData &data, Vector<CustomDataLayer, 16> &layers_to_write) +void CustomData_blend_write_prepare(CustomData &data, + Vector<CustomDataLayer, 16> &layers_to_write, + const Set<StringRef> &skip_names) { for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) { if (layer.flag & CD_FLAG_NOCOPY) { @@ -4312,6 +4364,9 @@ void CustomData_blend_write_prepare(CustomData &data, Vector<CustomDataLayer, 16 if (layer.anonymous_id != nullptr) { continue; } + if (skip_names.contains(layer.name)) { + continue; + } layers_to_write.append(layer); } data.totlayer = layers_to_write.size(); diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 65f3a82eadf..abf47acd5cc 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -28,6 +28,7 @@ #include "BLI_math.h" #include "BLI_math_vector.hh" #include "BLI_memarena.h" +#include "BLI_span.hh" #include "BLI_string.h" #include "BLI_task.hh" #include "BLI_utildefines.h" @@ -36,6 +37,7 @@ #include "BLT_translation.h" #include "BKE_anim_data.h" +#include "BKE_attribute.hh" #include "BKE_bpath.h" #include "BKE_deform.h" #include "BKE_editmesh.h" @@ -62,6 +64,8 @@ #include "BLO_read_write.h" using blender::float3; +using blender::MutableSpan; +using blender::VArray; using blender::Vector; static void mesh_clear_geometry(Mesh *mesh); @@ -241,10 +245,14 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address memset(&mesh->pdata, 0, sizeof(mesh->pdata)); } else { - CustomData_blend_write_prepare(mesh->vdata, vert_layers); - CustomData_blend_write_prepare(mesh->edata, edge_layers); + if (!BLO_write_is_undo(writer)) { + BKE_mesh_legacy_convert_hide_layers_to_flags(mesh); + } + + CustomData_blend_write_prepare(mesh->vdata, vert_layers, {".hide_vert"}); + CustomData_blend_write_prepare(mesh->edata, edge_layers, {".hide_edge"}); CustomData_blend_write_prepare(mesh->ldata, loop_layers); - CustomData_blend_write_prepare(mesh->pdata, poly_layers); + CustomData_blend_write_prepare(mesh->pdata, poly_layers, {".hide_poly"}); } BLO_write_id_struct(writer, Mesh, id_address, &mesh->id); @@ -323,6 +331,10 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) } } + if (!BLO_read_data_is_undo(reader)) { + BKE_mesh_legacy_convert_flags_to_hide_layers(mesh); + } + /* We don't expect to load normals from files, since they are derived data. */ BKE_mesh_normals_tag_dirty(mesh); BKE_mesh_assert_normals_dirty_or_calculated(mesh); diff --git a/source/blender/blenkernel/intern/mesh_evaluate.cc b/source/blender/blenkernel/intern/mesh_evaluate.cc index 7d26262a504..ebe1f8852e4 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.cc +++ b/source/blender/blenkernel/intern/mesh_evaluate.cc @@ -22,15 +22,17 @@ #include "BLI_math.h" #include "BLI_span.hh" #include "BLI_utildefines.h" +#include "BLI_virtual_array.hh" #include "BKE_customdata.h" +#include "BKE_attribute.hh" #include "BKE_mesh.h" #include "BKE_multires.h" -using blender::IndexRange; using blender::MutableSpan; using blender::Span; +using blender::VArray; /* -------------------------------------------------------------------- */ /** \name Polygon Calculations @@ -732,75 +734,89 @@ void BKE_mesh_polygons_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata, int t /** \name Mesh Flag Flushing * \{ */ -void BKE_mesh_flush_hidden_from_verts_ex(const MVert *mvert, - const MLoop *mloop, - MEdge *medge, - const int totedge, - MPoly *mpoly, - const int totpoly) +void BKE_mesh_flush_hidden_from_verts(Mesh *me) { - int i, j; + using namespace blender; + using namespace blender::bke; + MutableAttributeAccessor attributes = mesh_attributes_for_write(*me); - for (i = 0; i < totedge; i++) { - MEdge *e = &medge[i]; - if (mvert[e->v1].flag & ME_HIDE || mvert[e->v2].flag & ME_HIDE) { - e->flag |= ME_HIDE; - } - else { - e->flag &= ~ME_HIDE; - } + const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); + if (hide_vert.is_single() && !hide_vert.get_internal_single()) { + attributes.remove(".hide_edge"); + attributes.remove(".hide_poly"); + return; } - for (i = 0; i < totpoly; i++) { - MPoly *p = &mpoly[i]; - p->flag &= (char)~ME_HIDE; - for (j = 0; j < p->totloop; j++) { - if (mvert[mloop[p->loopstart + j].v].flag & ME_HIDE) { - p->flag |= ME_HIDE; - } - } + const VArraySpan<bool> hide_vert_span{hide_vert}; + const Span<MEdge> edges(me->medge, me->totedge); + const Span<MPoly> polys(me->mpoly, me->totpoly); + const Span<MLoop> loops(me->mloop, me->totloop); + + /* Hide edges when either of their vertices are hidden. */ + SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>( + ".hide_edge", ATTR_DOMAIN_EDGE); + for (const int i : edges.index_range()) { + const MEdge &edge = edges[i]; + hide_edge.span[i] = hide_vert_span[edge.v1] || hide_vert_span[edge.v2]; } -} -void BKE_mesh_flush_hidden_from_verts(Mesh *me) -{ - BKE_mesh_flush_hidden_from_verts_ex( - me->mvert, me->mloop, me->medge, me->totedge, me->mpoly, me->totpoly); + hide_edge.finish(); + + /* Hide faces when any of their vertices are hidden. */ + SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_only_span<bool>( + ".hide_poly", ATTR_DOMAIN_FACE); + for (const int i : polys.index_range()) { + const MPoly &poly = polys[i]; + const Span<MLoop> loops = loops.slice(poly.loopstart, poly.totloop); + hide_poly.span[i] = std::any_of( + loops.begin(), loops.end(), [&](const MLoop &loop) { return hide_vert_span[loop.v]; }); + } + hide_poly.finish(); } -void BKE_mesh_flush_hidden_from_polys_ex(MVert *mvert, - const MLoop *mloop, - MEdge *medge, - const int UNUSED(totedge), - const MPoly *mpoly, - const int totpoly) +void BKE_mesh_flush_hidden_from_polys(Mesh *me) { - int i = totpoly; - for (const MPoly *mp = mpoly; i--; mp++) { - if (mp->flag & ME_HIDE) { - const MLoop *ml; - int j = mp->totloop; - for (ml = &mloop[mp->loopstart]; j--; ml++) { - mvert[ml->v].flag |= ME_HIDE; - medge[ml->e].flag |= ME_HIDE; + using namespace blender; + using namespace blender::bke; + MutableAttributeAccessor attributes = mesh_attributes_for_write(*me); + + 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()) { + attributes.remove(".hide_vert"); + attributes.remove(".hide_edge"); + return; + } + const VArraySpan<bool> hide_face_span{hide_poly}; + const Span<MPoly> polys(me->mpoly, me->totpoly); + const Span<MLoop> loops(me->mloop, me->totloop); + SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_only_span<bool>( + ".hide_vert", ATTR_DOMAIN_POINT); + SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>( + ".hide_edge", ATTR_DOMAIN_EDGE); + + /* Hide all edges or vertices connected to hidden faces. */ + for (const int i : polys.index_range()) { + if (hide_face_span[i]) { + const MPoly &poly = polys[i]; + for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { + hide_vert.span[loop.v] = true; + hide_edge.span[loop.e] = true; } } } - - i = totpoly; - for (const MPoly *mp = mpoly; i--; mp++) { - if ((mp->flag & ME_HIDE) == 0) { - const MLoop *ml; - int j = mp->totloop; - for (ml = &mloop[mp->loopstart]; j--; ml++) { - mvert[ml->v].flag &= (char)~ME_HIDE; - medge[ml->e].flag &= (short)~ME_HIDE; + /* Unhide vertices and edges connected to visible faces. */ + for (const int i : polys.index_range()) { + if (!hide_face_span[i]) { + const MPoly &poly = polys[i]; + for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { + hide_vert.span[loop.v] = false; + hide_edge.span[loop.e] = false; } } } -} -void BKE_mesh_flush_hidden_from_polys(Mesh *me) -{ - BKE_mesh_flush_hidden_from_polys_ex( - me->mvert, me->mloop, me->medge, me->totedge, me->mpoly, me->totpoly); + + hide_vert.finish(); + hide_edge.finish(); } void BKE_mesh_flush_select_from_polys_ex(MVert *mvert, @@ -848,11 +864,13 @@ void BKE_mesh_flush_select_from_polys(Mesh *me) static void mesh_flush_select_from_verts(const Span<MVert> verts, const Span<MLoop> loops, + const VArray<bool> &hide_edge, + const VArray<bool> &hide_poly, MutableSpan<MEdge> edges, MutableSpan<MPoly> polys) { for (const int i : edges.index_range()) { - if ((edges[i].flag & ME_HIDE) == 0) { + if (!hide_edge[i]) { MEdge &edge = edges[i]; if ((verts[edge.v1].flag & SELECT) && (verts[edge.v2].flag & SELECT)) { edge.flag |= SELECT; @@ -864,7 +882,7 @@ static void mesh_flush_select_from_verts(const Span<MVert> verts, } for (const int i : polys.index_range()) { - if (polys[i].flag & ME_HIDE) { + if (hide_poly[i]) { continue; } MPoly &poly = polys[i]; @@ -885,10 +903,14 @@ static void mesh_flush_select_from_verts(const Span<MVert> verts, void BKE_mesh_flush_select_from_verts(Mesh *me) { - mesh_flush_select_from_verts({me->mvert, me->totvert}, - {me->mloop, me->totloop}, - {me->medge, me->totedge}, - {me->mpoly, me->totpoly}); + const blender::bke::AttributeAccessor attributes = blender::bke::mesh_attributes(*me); + mesh_flush_select_from_verts( + {me->mvert, me->totvert}, + {me->mloop, me->totloop}, + attributes.lookup_or_default<bool>(".hide_edge", ATTR_DOMAIN_EDGE, false), + attributes.lookup_or_default<bool>(".hide_poly", ATTR_DOMAIN_FACE, false), + {me->medge, me->totedge}, + {me->mpoly, me->totpoly}); } /** \} */ diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 479dd6a012a..04c1850f4ae 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -7,7 +7,7 @@ * Functions to convert mesh data to and from legacy formats like #MFace. */ -// #include <climits> +#define DNA_DEPRECATED_ALLOW #include "MEM_guardedalloc.h" @@ -18,8 +18,10 @@ #include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_polyfill_2d.h" +#include "BLI_task.hh" #include "BLI_utildefines.h" +#include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_mesh.h" #include "BKE_mesh_legacy_convert.h" @@ -874,3 +876,91 @@ void BKE_mesh_add_mface_layers(CustomData *fdata, CustomData *ldata, int total) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Attribute and Legacy Flag Conversion + * \{ */ + +void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh) +{ + using namespace blender; + using namespace blender::bke; + const AttributeAccessor attributes = mesh_attributes(*mesh); + + MutableSpan<MVert> vertices(mesh->mvert, mesh->totvert); + const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); + threading::parallel_for(vertices.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + SET_FLAG_FROM_TEST(vertices[i].flag, hide_vert[i], ME_HIDE); + } + }); + + MutableSpan<MEdge> edges(mesh->medge, mesh->totedge); + const VArray<bool> hide_edge = attributes.lookup_or_default<bool>( + ".hide_edge", ATTR_DOMAIN_EDGE, false); + threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + SET_FLAG_FROM_TEST(edges[i].flag, hide_edge[i], ME_HIDE); + } + }); + + MutableSpan<MPoly> polygons(mesh->mpoly, mesh->totpoly); + const VArray<bool> hide_face = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + threading::parallel_for(polygons.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + SET_FLAG_FROM_TEST(polygons[i].flag, hide_face[i], ME_HIDE); + } + }); +} + +void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh) +{ + using namespace blender; + using namespace blender::bke; + MutableAttributeAccessor attributes = mesh_attributes_for_write(*mesh); + + const Span<MVert> vertices(mesh->mvert, mesh->totvert); + if (std::any_of(vertices.begin(), vertices.end(), [](const MVert &vert) { + return vert.flag & ME_HIDE; + })) { + SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_only_span<bool>( + ".hide_vert", ATTR_DOMAIN_POINT); + threading::parallel_for(vertices.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + hide_vert.span[i] = vertices[i].flag & ME_HIDE; + } + }); + hide_vert.finish(); + } + + const Span<MEdge> edges(mesh->medge, mesh->totedge); + if (std::any_of( + edges.begin(), edges.end(), [](const MEdge &edge) { return edge.flag & ME_HIDE; })) { + SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>( + ".hide_edge", ATTR_DOMAIN_EDGE); + threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + hide_edge.span[i] = edges[i].flag & ME_HIDE; + } + }); + hide_edge.finish(); + } + + const Span<MPoly> polygons(mesh->mpoly, mesh->totpoly); + if (std::any_of(polygons.begin(), polygons.end(), [](const MPoly &poly) { + return poly.flag & ME_HIDE; + })) { + SpanAttributeWriter<bool> hide_face = attributes.lookup_or_add_for_write_only_span<bool>( + ".hide_poly", ATTR_DOMAIN_FACE); + threading::parallel_for(polygons.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + hide_face.span[i] = polygons[i].flag & ME_HIDE; + } + }); + hide_face.finish(); + } +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index 9c4098e2db6..798fe087ea8 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -29,6 +29,7 @@ /* ngon version wip, based on BM_uv_vert_map_create */ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly, + const bool *hide_poly, const MLoop *mloop, const MLoopUV *mloopuv, uint totpoly, @@ -51,7 +52,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly, /* generate UvMapVert array */ mp = mpoly; for (a = 0; a < totpoly; a++, mp++) { - if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) { + if (!selected || (!(hide_poly && hide_poly[a]) && (mp->flag & ME_FACE_SEL))) { totuv += mp->totloop; } } @@ -74,7 +75,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly, mp = mpoly; for (a = 0; a < totpoly; a++, mp++) { - if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) { + if (!selected || (!(hide_poly && hide_poly[a]) && (mp->flag & ME_FACE_SEL))) { float(*tf_uv)[2] = NULL; if (use_winding) { diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index b540357ce49..922ea45703d 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1243,11 +1243,13 @@ void BKE_paint_blend_read_lib(BlendLibReader *reader, Scene *sce, Paint *p) } } -bool paint_is_face_hidden(const MLoopTri *lt, const MVert *mvert, const MLoop *mloop) +bool paint_is_face_hidden(const MLoopTri *lt, const bool *hide_vert, const MLoop *mloop) { - return ((mvert[mloop[lt->tri[0]].v].flag & ME_HIDE) || - (mvert[mloop[lt->tri[1]].v].flag & ME_HIDE) || - (mvert[mloop[lt->tri[2]].v].flag & ME_HIDE)); + if (!hide_vert) { + return false; + } + return ((hide_vert[mloop[lt->tri[0]].v]) || (hide_vert[mloop[lt->tri[1]].v]) || + (hide_vert[mloop[lt->tri[2]].v])); } bool paint_is_grid_face_hidden(const uint *grid_hidden, int gridsize, int x, int y) @@ -2068,9 +2070,11 @@ void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(Mesh *mesh) } int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); + const bool *hide_poly = (const bool *)CustomData_get_layer_named( + &mesh->pdata, CD_PROP_BOOL, ".hide_poly"); for (int i = 0; i < mesh->totpoly; i++) { - if (!(mesh->mpoly[i].flag & ME_HIDE)) { + if (!(hide_poly && hide_poly[i])) { continue; } @@ -2095,9 +2099,13 @@ void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh) return; } + bool *hide_poly = (bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly"); + if (!hide_poly) { + return; + } + for (int i = 0; i < mesh->totpoly; i++) { - const bool is_face_set_visible = face_sets[i] >= 0; - SET_FLAG_FROM_TEST(mesh->mpoly[i].flag, !is_face_set_visible, ME_HIDE); + hide_poly[i] = face_sets[i] < 0; } BKE_mesh_flush_hidden_from_polys(mesh); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index dae9788d21c..4e6418942be 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -287,7 +287,7 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node) } if (has_visible == false) { - if (!paint_is_face_hidden(lt, pbvh->verts, pbvh->mloop)) { + if (!paint_is_face_hidden(lt, pbvh->hide_vert, pbvh->mloop)) { has_visible = true; } } @@ -562,6 +562,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, pbvh->verts = verts; BKE_mesh_vertex_normals_ensure(mesh); pbvh->vert_normals = BKE_mesh_vertex_normals_for_write(mesh); + pbvh->hide_vert = (bool *)CustomData_get_layer_named(&mesh->vdata, CD_PROP_BOOL, ".hide_vert"); pbvh->vert_bitmap = MEM_calloc_arrayN(totvert, sizeof(bool), "bvh->vert_bitmap"); pbvh->totvert = totvert; pbvh->leaf_limit = LEAF_LIMIT; @@ -1316,7 +1317,6 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata, case PBVH_FACES: node->draw_buffers = GPU_pbvh_mesh_buffers_build( pbvh->mesh, - pbvh->verts, pbvh->looptri, CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS), node->prim_indices, @@ -1590,9 +1590,12 @@ static void pbvh_faces_node_visibility_update(PBVH *pbvh, PBVHNode *node) BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert); BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert); + if (pbvh->hide_vert == NULL) { + BKE_pbvh_node_fully_hidden_set(node, false); + return; + } for (i = 0; i < totvert; i++) { - MVert *v = &mvert[vert_indices[i]]; - if (!(v->flag & ME_HIDE)) { + if (!(pbvh->hide_vert[vert_indices[i]])) { BKE_pbvh_node_fully_hidden_set(node, false); return; } @@ -2291,7 +2294,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh, const MLoopTri *lt = &pbvh->looptri[faces[i]]; const int *face_verts = node->face_vert_indices[i]; - if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) { + if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_vert, mloop)) { continue; } @@ -2600,7 +2603,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh, const MLoopTri *lt = &pbvh->looptri[faces[i]]; const int *face_verts = node->face_vert_indices[i]; - if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) { + if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_vert, mloop)) { continue; } @@ -3127,6 +3130,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m vi->mask = NULL; if (pbvh->header.type == PBVH_FACES) { vi->vert_normals = pbvh->vert_normals; + vi->hide_vert = pbvh->hide_vert; vi->vmask = CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK); } @@ -3207,6 +3211,27 @@ const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3] return pbvh->vert_normals; } +const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh) +{ + BLI_assert(pbvh->header.type == PBVH_FACES); + return pbvh->hide_vert; +} + +bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh) +{ + BLI_assert(pbvh->header.type == PBVH_FACES); + if (pbvh->hide_vert) { + return pbvh->hide_vert; + } + pbvh->hide_vert = CustomData_get_layer_named(&pbvh->mesh->vdata, CD_PROP_BOOL, ".hide_vert"); + if (pbvh->hide_vert) { + return pbvh->hide_vert; + } + pbvh->hide_vert = (bool *)CustomData_add_layer_named( + &pbvh->mesh->vdata, CD_PROP_BOOL, CD_CALLOC, NULL, pbvh->mesh->totvert, ".hide_vert"); + return pbvh->hide_vert; +} + void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg) { pbvh->subdiv_ccg = subdiv_ccg; diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index 0edf224e5ff..5babfd3acbe 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -144,10 +144,11 @@ struct PBVH { int leaf_limit; /* Mesh data */ - const struct Mesh *mesh; + struct Mesh *mesh; /* NOTE: Normals are not `const` because they can be updated for drawing by sculpt code. */ float (*vert_normals)[3]; + bool *hide_vert; struct MVert *verts; const struct MPoly *mpoly; const struct MLoop *mloop; diff --git a/source/blender/blenkernel/intern/subdiv_converter_mesh.c b/source/blender/blenkernel/intern/subdiv_converter_mesh.c index 12a5f00a68b..9c6d507d42c 100644 --- a/source/blender/blenkernel/intern/subdiv_converter_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_converter_mesh.c @@ -205,7 +205,15 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la mesh->totloop, sizeof(int), "loop uv vertex index"); } UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create( - mpoly, mloop, mloopuv, num_poly, num_vert, limit, false, true); + mpoly, + (const bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly"), + mloop, + mloopuv, + num_poly, + num_vert, + limit, + false, + true); /* NOTE: First UV vertex is supposed to be always marked as separate. */ storage->num_uv_coordinates = -1; for (int vertex_index = 0; vertex_index < num_vert; vertex_index++) { diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index efabb4f039a..f19aac68d35 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -284,7 +284,8 @@ static int ss_sync_from_uv(CCGSubSurf *ss, * UV map in really simple cases with mirror + subsurf, see second part of T44530. * Also, initially intention is to treat merged vertices from mirror modifier as seams. * This fixes a very old regression (2.49 was correct here) */ - vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, limit, false, true); + vmap = BKE_mesh_uv_vert_map_create( + mpoly, NULL, mloop, mloopuv, totface, totvert, limit, false, true); if (!vmap) { return 0; } diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index a7637d2712c..0ee5545527b 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -512,16 +512,24 @@ void BM_mesh_copy_init_customdata_from_mesh_array(BMesh *bm_dst, for (int i = 0; i < me_src_array_len; i++) { const Mesh *me_src = me_src_array[i]; if (i == 0) { - CustomData_copy(&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0); - CustomData_copy(&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0); - CustomData_copy(&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0); - CustomData_copy(&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0); + CustomData_copy_mesh_to_bmesh( + &me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0); + CustomData_copy_mesh_to_bmesh( + &me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0); + CustomData_copy_mesh_to_bmesh( + &me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0); + CustomData_copy_mesh_to_bmesh( + &me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0); } else { - CustomData_merge(&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0); - CustomData_merge(&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0); - CustomData_merge(&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0); - CustomData_merge(&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0); + CustomData_merge_mesh_to_bmesh( + &me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0); + CustomData_merge_mesh_to_bmesh( + &me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0); + CustomData_merge_mesh_to_bmesh( + &me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0); + CustomData_merge_mesh_to_bmesh( + &me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0); } cd_flag |= me_src->cd_flag; @@ -714,26 +722,25 @@ BMesh *BM_mesh_copy(BMesh *bm_old) char BM_vert_flag_from_mflag(const char mflag) { - return (((mflag & SELECT) ? BM_ELEM_SELECT : 0) | ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0)); + return ((mflag & SELECT) ? BM_ELEM_SELECT : 0); } char BM_edge_flag_from_mflag(const short mflag) { return (((mflag & SELECT) ? BM_ELEM_SELECT : 0) | ((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | ((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) | - ((mflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0) | /* invert */ - ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0)); + ((mflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0)); } char BM_face_flag_from_mflag(const char mflag) { return (((mflag & ME_FACE_SEL) ? BM_ELEM_SELECT : 0) | - ((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0) | ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0)); + ((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0)); } char BM_vert_flag_to_mflag(BMVert *v) { const char hflag = v->head.hflag; - return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0)); + return (((hflag & BM_ELEM_SELECT) ? SELECT : 0)); } short BM_edge_flag_to_mflag(BMEdge *e) @@ -743,7 +750,6 @@ short BM_edge_flag_to_mflag(BMEdge *e) return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) | ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) | ((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) | - ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) | (BM_edge_is_wire(e) ? ME_LOOSEEDGE : 0) | /* not typical */ ME_EDGERENDER); } @@ -752,5 +758,5 @@ char BM_face_flag_to_mflag(BMFace *f) const char hflag = f->head.hflag; return (((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) | - ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0)); + ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0)); } diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc index 884f6b5388a..cdaaabd1f05 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc @@ -83,7 +83,10 @@ #include "BLI_listbase.h" #include "BLI_math_vector.h" #include "BLI_span.hh" +#include "BLI_string_ref.hh" +#include "BLI_task.hh" +#include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" @@ -103,7 +106,9 @@ static CLG_LogRef LOG = {"bmesh.mesh.convert"}; using blender::Array; using blender::IndexRange; +using blender::MutableSpan; using blender::Span; +using blender::StringRef; void BM_mesh_cd_flag_ensure(BMesh *bm, Mesh *mesh, const char cd_flag) { @@ -212,10 +217,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar if (!me || !me->totvert) { if (me && is_new) { /* No verts? still copy custom-data layout. */ - CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_DEFAULT, 0); - CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_DEFAULT, 0); - CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_DEFAULT, 0); - CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_DEFAULT, 0); + CustomData_copy_mesh_to_bmesh(&me->vdata, &bm->vdata, mask.vmask, CD_DEFAULT, 0); + CustomData_copy_mesh_to_bmesh(&me->edata, &bm->edata, mask.emask, CD_DEFAULT, 0); + CustomData_copy_mesh_to_bmesh(&me->ldata, &bm->ldata, mask.lmask, CD_DEFAULT, 0); + CustomData_copy_mesh_to_bmesh(&me->pdata, &bm->pdata, mask.pmask, CD_DEFAULT, 0); CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT); CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE); @@ -231,10 +236,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar } if (is_new) { - CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, 0); - CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_CALLOC, 0); - CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, 0); - CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, 0); + CustomData_copy_mesh_to_bmesh(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, 0); + CustomData_copy_mesh_to_bmesh(&me->edata, &bm->edata, mask.emask, CD_CALLOC, 0); + CustomData_copy_mesh_to_bmesh(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, 0); + CustomData_copy_mesh_to_bmesh(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, 0); } else { CustomData_bmesh_merge(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, bm, BM_VERT); @@ -352,6 +357,13 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) : -1; + const bool *hide_vert = (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".hide_vert"); + const bool *hide_edge = (const bool *)CustomData_get_layer_named( + &me->edata, CD_PROP_BOOL, ".hide_edge"); + const bool *hide_poly = (const bool *)CustomData_get_layer_named( + &me->pdata, CD_PROP_BOOL, ".hide_poly"); + Span<MVert> mvert{me->mvert, me->totvert}; Array<BMVert *> vtable(me->totvert); for (const int i : mvert.index_range()) { @@ -361,6 +373,9 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar /* Transfer flag. */ v->head.hflag = BM_vert_flag_from_mflag(mvert[i].flag & ~SELECT); + if (hide_vert && hide_vert[i]) { + BM_elem_flag_enable(v, BM_ELEM_HIDDEN); + } /* This is necessary for selection counts to work properly. */ if (mvert[i].flag & SELECT) { @@ -404,6 +419,9 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar /* Transfer flags. */ e->head.hflag = BM_edge_flag_from_mflag(medge[i].flag & ~SELECT); + if (hide_edge && hide_edge[i]) { + BM_elem_flag_enable(e, BM_ELEM_HIDDEN); + } /* This is necessary for selection counts to work properly. */ if (medge[i].flag & SELECT) { @@ -457,6 +475,9 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar /* Transfer flag. */ f->head.hflag = BM_face_flag_from_mflag(mpoly[i].flag & ~ME_FACE_SEL); + if (hide_poly && hide_poly[i]) { + BM_elem_flag_enable(f, BM_ELEM_HIDDEN); + } /* This is necessary for selection counts to work properly. */ if (mpoly[i].flag & ME_FACE_SEL) { @@ -902,6 +923,63 @@ BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e) } } +template<typename GetFn> +static void write_elem_flag_to_attribute(blender::bke::MutableAttributeAccessor &attributes, + const StringRef attribute_name, + const eAttrDomain domain, + const bool do_write, + const GetFn &get_fn) +{ + using namespace blender; + if (do_write) { + bke::SpanAttributeWriter<bool> attribute = attributes.lookup_or_add_for_write_only_span<bool>( + attribute_name, domain); + threading::parallel_for(attribute.span.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + attribute.span[i] = get_fn(i); + } + }); + attribute.finish(); + } + else { + /* To avoid overhead, remove the hide attribute if possible. */ + attributes.remove(attribute_name); + } +} + +static void convert_bmesh_hide_flags_to_mesh_attributes(BMesh &bm, + const bool need_hide_vert, + const bool need_hide_edge, + const bool need_hide_face, + Mesh &mesh) +{ + using namespace blender; + /* The "hide" attributes are stored as flags on #BMesh. */ + BLI_assert(CustomData_get_layer_named(&bm.vdata, CD_PROP_BOOL, ".hide_vert") == nullptr); + BLI_assert(CustomData_get_layer_named(&bm.edata, CD_PROP_BOOL, ".hide_edge") == nullptr); + BLI_assert(CustomData_get_layer_named(&bm.pdata, CD_PROP_BOOL, ".hide_poly") == nullptr); + + if (!(need_hide_vert || need_hide_edge || need_hide_face)) { + return; + } + + bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(mesh); + BM_mesh_elem_table_ensure(&bm, BM_VERT | BM_EDGE | BM_FACE); + + write_elem_flag_to_attribute( + attributes, ".hide_vert", ATTR_DOMAIN_POINT, need_hide_vert, [&](const int i) { + return BM_elem_flag_test(BM_vert_at_index(&bm, i), BM_ELEM_HIDDEN); + }); + write_elem_flag_to_attribute( + attributes, ".hide_edge", ATTR_DOMAIN_EDGE, need_hide_edge, [&](const int i) { + return BM_elem_flag_test(BM_edge_at_index(&bm, i), BM_ELEM_HIDDEN); + }); + write_elem_flag_to_attribute( + attributes, ".hide_poly", ATTR_DOMAIN_FACE, need_hide_face, [&](const int i) { + return BM_elem_flag_test(BM_face_at_index(&bm, i), BM_ELEM_HIDDEN); + }); +} + void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params) { MEdge *med; @@ -938,10 +1016,10 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh { CustomData_MeshMasks mask = CD_MASK_MESH; CustomData_MeshMasks_update(&mask, ¶ms->cd_mask_extra); - CustomData_copy(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert); - CustomData_copy(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge); - CustomData_copy(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop); - CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly); + CustomData_copy_mesh_to_bmesh(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert); + CustomData_copy_mesh_to_bmesh(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge); + CustomData_copy_mesh_to_bmesh(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop); + CustomData_copy_mesh_to_bmesh(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly); } MVert *mvert = bm->totvert ? (MVert *)MEM_callocN(sizeof(MVert) * bm->totvert, "bm_to_me.vert") : @@ -958,6 +1036,10 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop); CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly); + bool need_hide_vert = false; + bool need_hide_edge = false; + bool need_hide_face = false; + /* Clear normals on the mesh completely, since the original vertex and polygon count might be * different than the BMesh's. */ BKE_mesh_clear_derived_normals(me); @@ -972,6 +1054,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh copy_v3_v3(mvert->co, v->co); mvert->flag = BM_vert_flag_to_mflag(v); + if (BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + need_hide_vert = true; + } BM_elem_index_set(v, i); /* set_inline */ @@ -996,6 +1081,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh med->v2 = BM_elem_index_get(e->v2); med->flag = BM_edge_flag_to_mflag(e); + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + need_hide_edge = true; + } BM_elem_index_set(e, i); /* set_inline */ @@ -1025,6 +1113,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh mpoly->totloop = f->len; mpoly->mat_nr = f->mat_nr; mpoly->flag = BM_face_flag_to_mflag(f); + if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + need_hide_face = true; + } l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { @@ -1117,6 +1208,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh } } + convert_bmesh_hide_flags_to_mesh_attributes( + *bm, need_hide_vert, need_hide_edge, need_hide_face, *me); + BKE_mesh_update_customdata_pointers(me, false); { @@ -1210,6 +1304,10 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); + bool need_hide_vert = false; + bool need_hide_edge = false; + bool need_hide_face = false; + /* Clear normals on the mesh completely, since the original vertex and polygon count might be * different than the BMesh's. */ BKE_mesh_clear_derived_normals(me); @@ -1224,6 +1322,13 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * BM_elem_index_set(eve, i); /* set_inline */ mv->flag = BM_vert_flag_to_mflag(eve); + if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + need_hide_vert = true; + } + + if (cd_vert_bweight_offset != -1) { + mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset); + } if (cd_vert_bweight_offset != -1) { mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset); @@ -1242,6 +1347,9 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * med->v2 = BM_elem_index_get(eed->v2); med->flag = BM_edge_flag_to_mflag(eed); + if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + need_hide_edge = true; + } /* Handle this differently to editmode switching, * only enable draw for single user edges rather than calculating angle. */ @@ -1272,6 +1380,10 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * mp->totloop = efa->len; mp->flag = BM_face_flag_to_mflag(efa); + if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + need_hide_face = true; + } + mp->loopstart = j; mp->mat_nr = efa->mat_nr; @@ -1291,5 +1403,8 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * } bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); + convert_bmesh_hide_flags_to_mesh_attributes( + *bm, need_hide_vert, need_hide_edge, need_hide_face, *me); + me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm); } diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index 27f1636cee5..0159c9fc86e 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -228,9 +228,9 @@ static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, MeshBufferCa } } else { - const MPoly *mp = &mr->mpoly[0]; - for (int i = 0; i < mr->poly_len; i++, mp++) { - if (!(mr->use_hide && (mp->flag & ME_HIDE))) { + for (int i = 0; i < mr->poly_len; i++) { + if (!(mr->use_hide && mr->hide_poly && mr->hide_poly[i])) { + const MPoly *mp = &mr->mpoly[i]; const int mat = min_ii(mp->mat_nr, mat_last); tri_first_index[i] = mat_tri_offs[mat]; mat_tri_offs[mat] += mp->totloop - 2; @@ -269,7 +269,7 @@ static void mesh_render_data_mat_tri_len_mesh_range_fn(void *__restrict userdata int *mat_tri_len = static_cast<int *>(tls->userdata_chunk); const MPoly *mp = &mr->mpoly[iter]; - if (!(mr->use_hide && (mp->flag & ME_HIDE))) { + if (!(mr->use_hide && mr->hide_poly && mr->hide_poly[iter])) { int mat = min_ii(mp->mat_nr, mr->mat_len - 1); mat_tri_len[mat] += mp->totloop - 2; } @@ -578,6 +578,13 @@ MeshRenderData *mesh_render_data_create(Object *object, mr->v_origindex = static_cast<const int *>(CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX)); mr->e_origindex = static_cast<const int *>(CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX)); mr->p_origindex = static_cast<const int *>(CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX)); + + mr->hide_vert = static_cast<const bool *>( + CustomData_get_layer_named(&me->vdata, CD_PROP_BOOL, ".hide_vert")); + mr->hide_edge = static_cast<const bool *>( + CustomData_get_layer_named(&me->edata, CD_PROP_BOOL, ".hide_edge")); + mr->hide_poly = static_cast<const bool *>( + CustomData_get_layer_named(&me->pdata, CD_PROP_BOOL, ".hide_poly")); } else { /* #BMesh */ diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 2f8a2540776..075e08eb49f 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -668,7 +668,9 @@ static void draw_subdiv_cache_extra_coarse_face_data_bm(BMesh *bm, } } -static void draw_subdiv_cache_extra_coarse_face_data_mesh(Mesh *mesh, uint32_t *flags_data) +static void draw_subdiv_cache_extra_coarse_face_data_mesh(const MeshRenderData *mr, + Mesh *mesh, + uint32_t *flags_data) { for (int i = 0; i < mesh->totpoly; i++) { uint32_t flag = 0; @@ -678,7 +680,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mesh(Mesh *mesh, uint32_t * if ((mesh->mpoly[i].flag & ME_FACE_SEL) != 0) { flag |= SUBDIV_COARSE_FACE_FLAG_SELECT; } - if ((mesh->mpoly[i].flag & ME_HIDE) != 0) { + if (mr->hide_poly && mr->hide_poly[i]) { flag |= SUBDIV_COARSE_FACE_FLAG_HIDDEN; } flags_data[i] = (uint)(mesh->mpoly[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET); @@ -691,7 +693,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mapped(Mesh *mesh, uint32_t *flags_data) { if (bm == nullptr) { - draw_subdiv_cache_extra_coarse_face_data_mesh(mesh, flags_data); + draw_subdiv_cache_extra_coarse_face_data_mesh(mr, mesh, flags_data); return; } @@ -726,7 +728,7 @@ static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cach draw_subdiv_cache_extra_coarse_face_data_mapped(mesh, cache->bm, mr, flags_data); } else { - draw_subdiv_cache_extra_coarse_face_data_mesh(mesh, flags_data); + draw_subdiv_cache_extra_coarse_face_data_mesh(mr, mesh, flags_data); } /* Make sure updated data is re-uploaded. */ diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index a4773736f0c..57abf088c16 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -83,6 +83,9 @@ struct MeshRenderData { MLoopTri *mlooptri; const float (*vert_normals)[3]; const float (*poly_normals)[3]; + const bool *hide_vert; + const bool *hide_edge; + const bool *hide_poly; float (*loop_normals)[3]; int *lverts, *ledges; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc index 2ff093d0bd8..9f82cc56941 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc @@ -61,7 +61,7 @@ static void extract_edituv_tris_iter_looptri_mesh(const MeshRenderData *mr, MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); const MPoly *mp = &mr->mpoly[mlt->poly]; edituv_tri_add(data, - (mp->flag & ME_HIDE) != 0, + mr->hide_poly && mr->hide_poly[mlt->poly], (mp->flag & ME_FACE_SEL) != 0, mlt->tri[0], mlt->tri[1], @@ -117,7 +117,7 @@ static void extract_edituv_tris_iter_subdiv_bm(const DRWSubdivCache *UNUSED(subd } static void extract_edituv_tris_iter_subdiv_mesh(const DRWSubdivCache *UNUSED(subdiv_cache), - const MeshRenderData *UNUSED(mr), + const MeshRenderData *mr, void *_data, uint subdiv_quad_index, const MPoly *coarse_quad) @@ -125,19 +125,13 @@ static void extract_edituv_tris_iter_subdiv_mesh(const DRWSubdivCache *UNUSED(su MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); const uint loop_idx = subdiv_quad_index * 4; - edituv_tri_add(data, - (coarse_quad->flag & ME_HIDE) != 0, - (coarse_quad->flag & ME_FACE_SEL) != 0, - loop_idx, - loop_idx + 1, - loop_idx + 2); + const bool hidden = mr->hide_poly && mr->hide_poly[coarse_quad - mr->mpoly]; - edituv_tri_add(data, - (coarse_quad->flag & ME_HIDE) != 0, - (coarse_quad->flag & ME_FACE_SEL) != 0, - loop_idx, - loop_idx + 2, - loop_idx + 3); + edituv_tri_add( + data, hidden, (coarse_quad->flag & ME_FACE_SEL) != 0, loop_idx, loop_idx + 1, loop_idx + 2); + + edituv_tri_add( + data, hidden, (coarse_quad->flag & ME_FACE_SEL) != 0, loop_idx, loop_idx + 2, loop_idx + 3); } static void extract_edituv_tris_finish_subdiv(const struct DRWSubdivCache *UNUSED(subdiv_cache), @@ -218,6 +212,8 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr, void *_data) { MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); + const bool hidden = mr->hide_poly && mr->hide_poly[mp - mr->mpoly]; + const MLoop *mloop = mr->mloop; const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { @@ -227,11 +223,8 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_next = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1); const bool real_edge = (mr->e_origindex == nullptr || mr->e_origindex[ml->e] != ORIGINDEX_NONE); - edituv_edge_add(data, - (mp->flag & ME_HIDE) != 0 || !real_edge, - (mp->flag & ME_FACE_SEL) != 0, - ml_index, - ml_index_next); + edituv_edge_add( + data, hidden || !real_edge, (mp->flag & ME_FACE_SEL) != 0, ml_index, ml_index_next); } } @@ -288,6 +281,8 @@ static void extract_edituv_lines_iter_subdiv_mesh(const DRWSubdivCache *subdiv_c const MPoly *coarse_poly) { MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); + const bool hidden = mr->hide_poly && mr->hide_poly[coarse_poly - mr->mpoly]; + int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index); uint start_loop_idx = subdiv_quad_index * 4; @@ -298,7 +293,7 @@ static void extract_edituv_lines_iter_subdiv_mesh(const DRWSubdivCache *subdiv_c (mr->e_origindex == nullptr || mr->e_origindex[edge_origindex] != ORIGINDEX_NONE)); edituv_edge_add(data, - (coarse_poly->flag & ME_HIDE) != 0 || !real_edge, + hidden || !real_edge, (coarse_poly->flag & ME_FACE_SEL) != 0, loop_idx, (loop_idx + 1 == end_loop_idx) ? start_loop_idx : (loop_idx + 1)); @@ -382,14 +377,15 @@ static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr, void *_data) { MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); + const bool hidden = mr->hide_poly && mr->hide_poly[mp - mr->mpoly]; + const MLoop *mloop = mr->mloop; const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { const MLoop *ml = &mloop[ml_index]; const bool real_vert = !mr->v_origindex || mr->v_origindex[ml->v] != ORIGINDEX_NONE; - edituv_point_add( - data, ((mp->flag & ME_HIDE) != 0) || !real_vert, (mp->flag & ME_FACE_SEL) != 0, ml_index); + edituv_point_add(data, hidden || !real_vert, (mp->flag & ME_FACE_SEL) != 0, ml_index); } } @@ -442,6 +438,7 @@ static void extract_edituv_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_ const MPoly *coarse_quad) { MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); + const bool hidden = mr->hide_poly && mr->hide_poly[coarse_quad - mr->mpoly]; int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index); uint start_loop_idx = subdiv_quad_index * 4; @@ -450,10 +447,7 @@ static void extract_edituv_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_ const int vert_origindex = subdiv_loop_vert_index[i]; const bool real_vert = !mr->v_origindex || (vert_origindex != -1 && mr->v_origindex[vert_origindex] != ORIGINDEX_NONE); - edituv_point_add(data, - ((coarse_quad->flag & ME_HIDE) != 0) || !real_vert, - (coarse_quad->flag & ME_FACE_SEL) != 0, - i); + edituv_point_add(data, hidden || !real_vert, (coarse_quad->flag & ME_FACE_SEL) != 0, i); } } @@ -533,6 +527,8 @@ static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr, void *_data) { MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data); + const bool hidden = mr->hide_poly && mr->hide_poly[mp - mr->mpoly]; + if (mr->use_subsurf_fdots) { const BLI_bitmap *facedot_tags = mr->me->runtime.subsurf_face_dot_tags; @@ -543,16 +539,13 @@ static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr, const bool real_fdot = !mr->p_origindex || (mr->p_origindex[mp_index] != ORIGINDEX_NONE); const bool subd_fdot = BLI_BITMAP_TEST(facedot_tags, ml->v); - edituv_facedot_add(data, - ((mp->flag & ME_HIDE) != 0) || !real_fdot || !subd_fdot, - (mp->flag & ME_FACE_SEL) != 0, - mp_index); + edituv_facedot_add( + data, hidden || !real_fdot || !subd_fdot, (mp->flag & ME_FACE_SEL) != 0, mp_index); } } else { const bool real_fdot = !mr->p_origindex || (mr->p_origindex[mp_index] != ORIGINDEX_NONE); - edituv_facedot_add( - data, ((mp->flag & ME_HIDE) != 0) || !real_fdot, (mp->flag & ME_FACE_SEL) != 0, mp_index); + edituv_facedot_add(data, hidden || !real_fdot, (mp->flag & ME_FACE_SEL) != 0, mp_index); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc index cc0b383f12b..8dc00617039 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc @@ -42,6 +42,8 @@ static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr, const int mp_index, void *_userdata) { + const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[mp - mr->mpoly]; + GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata); if (mr->use_subsurf_fdots) { const BLI_bitmap *facedot_tags = mr->me->runtime.subsurf_face_dot_tags; @@ -50,7 +52,7 @@ static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { const MLoop *ml = &mloop[ml_index]; - if (BLI_BITMAP_TEST(facedot_tags, ml->v) && !(mr->use_hide && (mp->flag & ME_HIDE))) { + if (BLI_BITMAP_TEST(facedot_tags, ml->v) && !hidden) { GPU_indexbuf_set_point_vert(elb, mp_index, mp_index); return; } @@ -58,7 +60,7 @@ static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr, GPU_indexbuf_set_point_restart(elb, mp_index); } else { - if (!(mr->use_hide && (mp->flag & ME_HIDE))) { + if (!hidden) { GPU_indexbuf_set_point_vert(elb, mp_index, mp_index); } else { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc index e6c0d815963..fe883fb0c96 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc @@ -58,14 +58,12 @@ static void extract_lines_iter_poly_mesh(const MeshRenderData *mr, GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data); /* Using poly & loop iterator would complicate accessing the adjacent loop. */ const MLoop *mloop = mr->mloop; - const MEdge *medge = mr->medge; if (mr->use_hide || (mr->extract_type == MR_EXTRACT_MAPPED) || (mr->e_origindex != nullptr)) { const int ml_index_last = mp->loopstart + (mp->totloop - 1); int ml_index = ml_index_last, ml_index_next = mp->loopstart; do { const MLoop *ml = &mloop[ml_index]; - const MEdge *med = &medge[ml->e]; - if (!((mr->use_hide && (med->flag & ME_HIDE)) || + if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[ml->e]) || ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && (mr->e_origindex[ml->e] == ORIGINDEX_NONE)))) { GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next); @@ -111,7 +109,7 @@ static void extract_lines_iter_ledge_mesh(const MeshRenderData *mr, GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data); const int l_index_offset = mr->edge_len + ledge_index; const int e_index = mr->ledges[ledge_index]; - if (!((mr->use_hide && (med->flag & ME_HIDE)) || + if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[med - mr->medge]) || ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) { const int l_index = mr->loop_len + ledge_index * 2; @@ -185,9 +183,14 @@ static void extract_lines_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, switch (mr->extract_type) { case MR_EXTRACT_MESH: { - const MEdge *medge = mr->medge; - for (DRWSubdivLooseEdge edge : loose_edges) { - *flags_data++ = (medge[edge.coarse_edge_index].flag & ME_HIDE) != 0; + const bool *hide_vert = mr->hide_vert; + if (hide_vert) { + for (DRWSubdivLooseEdge edge : loose_edges) { + *flags_data++ = hide_vert[edge.coarse_edge_index]; + } + } + else { + MutableSpan<uint>(flags_data, loose_edges.size()).fill(0); } break; } @@ -199,18 +202,23 @@ static void extract_lines_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, } } else { - for (DRWSubdivLooseEdge edge : loose_edges) { - int e = edge.coarse_edge_index; - - if (mr->e_origindex && mr->e_origindex[e] != ORIGINDEX_NONE) { - *flags_data++ = (mr->medge[mr->e_origindex[e]].flag & ME_HIDE) != 0; - } - else { - *flags_data++ = false; + const bool *hide_vert = mr->hide_vert; + if (hide_vert) { + for (DRWSubdivLooseEdge edge : loose_edges) { + int e = edge.coarse_edge_index; + + if (mr->e_origindex && mr->e_origindex[e] != ORIGINDEX_NONE) { + *flags_data++ = hide_vert[edge.coarse_edge_index]; + } + else { + *flags_data++ = false; + } } } + else { + MutableSpan<uint>(flags_data, loose_edges.size()).fill(0); + } } - break; } case MR_EXTRACT_BMESH: { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc index c2cfb66ec28..d6c246c51a9 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc @@ -119,16 +119,17 @@ static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr, void *_data) { MeshExtract_LineAdjacency_Data *data = static_cast<MeshExtract_LineAdjacency_Data *>(_data); - const MPoly *mp = &mr->mpoly[mlt->poly]; - if (!(mr->use_hide && (mp->flag & ME_HIDE))) { - lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v, - mr->mloop[mlt->tri[1]].v, - mr->mloop[mlt->tri[2]].v, - mlt->tri[0], - mlt->tri[1], - mlt->tri[2], - data); + const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[mlt->poly]; + if (hidden) { + return; } + lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v, + mr->mloop[mlt->tri[1]].v, + mr->mloop[mlt->tri[2]].v, + mlt->tri[0], + mlt->tri[1], + mlt->tri[2], + data); } static void extract_lines_adjacency_finish(const MeshRenderData *UNUSED(mr), diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc index 11c71d61775..d5f31c08eaf 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc @@ -47,8 +47,7 @@ static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, const MLoop *ml = &mloop[ml_index]; const int e_index = ml->e; - const MEdge *me = &mr->medge[e_index]; - if (!((mr->use_hide && (me->flag & ME_HIDE)) || + if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[e_index]) || ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) { @@ -122,8 +121,7 @@ static void extract_lines_paint_mask_iter_subdiv_mesh(const DRWSubdivCache *subd GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index); } else { - const MEdge *me = &mr->medge[coarse_edge_index]; - if (!((mr->use_hide && (me->flag & ME_HIDE)) || + if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[coarse_edge_index]) || ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && (mr->e_origindex[coarse_edge_index] == ORIGINDEX_NONE)))) { const uint ml_index_other = (loop_idx == (end_loop_idx - 1)) ? start_loop_idx : diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc index f7c5505422b..ca46a38823d 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc @@ -43,10 +43,10 @@ BLI_INLINE void vert_set_mesh(GPUIndexBufBuilder *elb, const int v_index, const int l_index) { - const MVert *mv = &mr->mvert[v_index]; - if (!((mr->use_hide && (mv->flag & ME_HIDE)) || - ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && - (mr->v_origindex[v_index] == ORIGINDEX_NONE)))) { + const bool hidden = mr->use_hide && mr->hide_vert && mr->hide_vert[v_index]; + + if (!(hidden || ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && + (mr->v_origindex[v_index] == ORIGINDEX_NONE)))) { GPU_indexbuf_set_point_vert(elb, v_index, l_index); } else { @@ -181,8 +181,7 @@ static void extract_points_iter_subdiv_common(GPUIndexBufBuilder *elb, } } else { - const MVert *mv = &mr->mvert[coarse_vertex_index]; - if (mr->use_hide && (mv->flag & ME_HIDE)) { + if (mr->use_hide && mr->hide_vert && mr->hide_vert[coarse_vertex_index]) { GPU_indexbuf_set_point_restart(elb, coarse_vertex_index); continue; } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc index 9fc18620d11..2e3e6c7b6b1 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc @@ -189,12 +189,12 @@ static void extract_tris_single_mat_iter_looptri_mesh(const MeshRenderData *mr, void *_data) { GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data); - const MPoly *mp = &mr->mpoly[mlt->poly]; - if (!(mr->use_hide && (mp->flag & ME_HIDE))) { - GPU_indexbuf_set_tri_verts(elb, mlt_index, mlt->tri[0], mlt->tri[1], mlt->tri[2]); + const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[mlt->poly]; + if (hidden) { + GPU_indexbuf_set_tri_restart(elb, mlt_index); } else { - GPU_indexbuf_set_tri_restart(elb, mlt_index); + GPU_indexbuf_set_tri_verts(elb, mlt_index, mlt->tri[0], mlt->tri[1], mlt->tri[2]); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc index ac517269e7d..ef67e1b540d 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc @@ -62,6 +62,8 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, const int mp_index, void *data) { + const bool hidden = mr->hide_poly && mr->hide_poly[mp_index]; + const MLoop *mloop = mr->mloop; const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { @@ -80,8 +82,8 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, /* Flag for paint mode overlay. * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. * In paint mode it will use the un-mapped data to draw the wire-frame. */ - if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && - (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { + if (hidden || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) && + mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { lnor_data->w = -1; } else if (mp->flag & ME_FACE_SEL) { @@ -185,6 +187,8 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, const int mp_index, void *data) { + const bool hidden = mr->hide_poly && mr->hide_poly[mp_index]; + const MLoop *mloop = mr->mloop; const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { @@ -203,8 +207,8 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, /* Flag for paint mode overlay. * Only use #MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. * In paint mode it will use the un-mapped data to draw the wire-frame. */ - if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && - (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { + if (hidden || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) && + mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { lnor_data->w = -1; } else if (mp->flag & ME_FACE_SEL) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc index 9788beabeb5..4d2a10e83ce 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc @@ -83,10 +83,11 @@ static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr, static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, const MPoly *mp, - const int UNUSED(mp_index), + const int mp_index, void *_data) { MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data); + const bool face_hidden = mr->hide_poly && mr->hide_poly[mp_index]; const MLoop *mloop = mr->mloop; const int ml_index_end = mp->loopstart + mp->totloop; @@ -95,10 +96,11 @@ static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, PosNorLoop *vert = &data->vbo_data[ml_index]; const MVert *mv = &mr->mvert[ml->v]; + const bool vert_hidden = mr->hide_vert && mr->hide_vert[ml->v]; copy_v3_v3(vert->pos, mv->co); vert->nor = data->normals[ml->v].low; /* Flag for paint mode overlay. */ - if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || + if (face_hidden || vert_hidden || ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { vert->nor.w = -1; @@ -432,18 +434,21 @@ static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr, void *_data) { MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data); + const bool face_hidden = mr->hide_poly && mr->hide_poly[mp - mr->mpoly]; + const MLoop *mloop = mr->mloop; const int ml_index_end = mp->loopstart + mp->totloop; for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { const MLoop *ml = &mloop[ml_index]; + const bool vert_hidden = mr->hide_vert && mr->hide_vert[ml->v]; PosNorHQLoop *vert = &data->vbo_data[ml_index]; const MVert *mv = &mr->mvert[ml->v]; copy_v3_v3(vert->pos, mv->co); copy_v3_v3_short(vert->nor, data->normals[ml->v].high); /* Flag for paint mode overlay. */ - if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || + if (face_hidden || vert_hidden || ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { vert->nor[3] = -1; diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 9d3fd5af47f..71ddffca8a9 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -390,7 +390,10 @@ void ED_keymap_mesh(struct wmKeyConfig *keyconf); * Copy the face flags, most importantly selection from the mesh to the final derived mesh, * use in object mode when selecting faces (while painting). */ -void paintface_flush_flags(struct bContext *C, struct Object *ob, short flag); +void paintface_flush_flags(struct bContext *C, + struct Object *ob, + bool flush_selection, + bool flush_hidden); /** * \return True when pick finds an element or the selection changed. */ diff --git a/source/blender/editors/mesh/editface.cc b/source/blender/editors/mesh/editface.cc index 3608e162727..96a493cba49 100644 --- a/source/blender/editors/mesh/editface.cc +++ b/source/blender/editors/mesh/editface.cc @@ -17,6 +17,7 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" +#include "BKE_attribute.hh" #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_global.h" @@ -36,14 +37,18 @@ /* own include */ -void paintface_flush_flags(bContext *C, Object *ob, short flag) +void paintface_flush_flags(bContext *C, + Object *ob, + const bool flush_selection, + const bool flush_hidden) { + using namespace blender; Mesh *me = BKE_mesh_from_object(ob); MPoly *polys, *mp_orig; const int *index_array = nullptr; int totpoly; - BLI_assert((flag & ~(SELECT | ME_HIDE)) == 0); + BLI_assert(flush_selection || flush_hidden); if (me == nullptr) { return; @@ -53,7 +58,7 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag) /* we could call this directly in all areas that change selection, * since this could become slow for realtime updates (circle-select for eg) */ - if (flag & SELECT) { + if (flush_selection) { BKE_mesh_flush_select_from_polys(me); } @@ -64,8 +69,11 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag) return; } + bke::AttributeAccessor attributes_me = bke::mesh_attributes(*me); Mesh *me_orig = (Mesh *)ob_eval->runtime.data_orig; + bke::MutableAttributeAccessor attributes_orig = bke::mesh_attributes_for_write(*me_orig); Mesh *me_eval = (Mesh *)ob_eval->runtime.data_eval; + bke::MutableAttributeAccessor attributes_eval = bke::mesh_attributes_for_write(*me_eval); bool updated = false; if (me_orig != nullptr && me_eval != nullptr && me_orig->totpoly == me->totpoly) { @@ -73,13 +81,17 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag) for (int i = 0; i < me->totpoly; i++) { me_orig->mpoly[i].flag = me->mpoly[i].flag; } - - /* If the mesh has only deform modifiers, the evaluated mesh shares arrays. */ - if (me_eval->mpoly == me_orig->mpoly) { - updated = true; + if (flush_hidden) { + const VArray<bool> hide_face_me = attributes_me.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> hide_face_orig = + attributes_orig.lookup_or_add_for_write_only_span<bool>(".hide_poly", ATTR_DOMAIN_FACE); + hide_face_me.materialize(hide_face_orig.span); + hide_face_orig.finish(); } + /* Mesh polys => Final derived polys */ - else if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) { + if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) { polys = me_eval->mpoly; totpoly = me_eval->totpoly; @@ -91,13 +103,24 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag) polys[i].flag = mp_orig->flag; } } + const VArray<bool> hide_face_orig = attributes_orig.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + bke::SpanAttributeWriter<bool> hide_face_eval = + attributes_eval.lookup_or_add_for_write_only_span<bool>(".hide_poly", ATTR_DOMAIN_FACE); + for (const int i : IndexRange(me_eval->totpoly)) { + const int orig_face_index = index_array[i]; + if (orig_face_index != ORIGINDEX_NONE) { + hide_face_eval.span[i] = hide_face_orig[orig_face_index]; + } + } + hide_face_eval.finish(); updated = true; } } if (updated) { - if (flag & ME_HIDE) { + if (flush_hidden) { BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_ALL); } else { @@ -115,59 +138,79 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag) void paintface_hide(bContext *C, Object *ob, const bool unselected) { + using namespace blender; Mesh *me = BKE_mesh_from_object(ob); if (me == nullptr || me->totpoly == 0) { return; } + bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me); + bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>( + ".hide_poly", ATTR_DOMAIN_FACE); + for (int i = 0; i < me->totpoly; i++) { MPoly *mpoly = &me->mpoly[i]; - if ((mpoly->flag & ME_HIDE) == 0) { + if (!hide_poly.span[i]) { if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) { - mpoly->flag |= ME_HIDE; + hide_poly.span[i] = true; } } - if (mpoly->flag & ME_HIDE) { + if (hide_poly.span[i]) { mpoly->flag &= ~ME_FACE_SEL; } } + hide_poly.finish(); + BKE_mesh_flush_hidden_from_polys(me); - paintface_flush_flags(C, ob, SELECT | ME_HIDE); + paintface_flush_flags(C, ob, true, true); } void paintface_reveal(bContext *C, Object *ob, const bool select) { + using namespace blender; Mesh *me = BKE_mesh_from_object(ob); if (me == nullptr || me->totpoly == 0) { return; } - for (int i = 0; i < me->totpoly; i++) { - MPoly *mpoly = &me->mpoly[i]; - if (mpoly->flag & ME_HIDE) { - SET_FLAG_FROM_TEST(mpoly->flag, select, ME_FACE_SEL); - mpoly->flag &= ~ME_HIDE; + bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me); + + if (select) { + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + for (int i = 0; i < me->totpoly; i++) { + MPoly *mpoly = &me->mpoly[i]; + if (hide_poly[i]) { + mpoly->flag |= ME_FACE_SEL; + } } } + attributes.remove(".hide_poly"); + BKE_mesh_flush_hidden_from_polys(me); - paintface_flush_flags(C, ob, SELECT | ME_HIDE); + paintface_flush_flags(C, ob, true, true); } /* Set object-mode face selection seams based on edge data, uses hash table to find seam edges. */ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bool select) { + using namespace blender; bool do_it = true; bool mark = false; BLI_bitmap *edge_tag = BLI_BITMAP_NEW(me->totedge, __func__); BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__); + bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + if (index != (uint)-1) { /* only put face under cursor in array */ MPoly *mp = &me->mpoly[index]; @@ -178,7 +221,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo /* fill array by selection */ for (int i = 0; i < me->totpoly; i++) { MPoly *mp = &me->mpoly[i]; - if (mp->flag & ME_HIDE) { + if (hide_poly[i]) { /* pass */ } else if (mp->flag & ME_FACE_SEL) { @@ -194,7 +237,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo /* expand selection */ for (int i = 0; i < me->totpoly; i++) { MPoly *mp = &me->mpoly[i]; - if (mp->flag & ME_HIDE) { + if (hide_poly[i]) { continue; } @@ -249,22 +292,27 @@ void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const b select_linked_tfaces_with_seams(me, index, select); - paintface_flush_flags(C, ob, SELECT); + paintface_flush_flags(C, ob, true, false); } bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags) { + using namespace blender; Mesh *me = BKE_mesh_from_object(ob); if (me == nullptr) { return false; } + bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + if (action == SEL_TOGGLE) { action = SEL_SELECT; for (int i = 0; i < me->totpoly; i++) { MPoly *mpoly = &me->mpoly[i]; - if ((mpoly->flag & ME_HIDE) == 0 && mpoly->flag & ME_FACE_SEL) { + if (!hide_poly[i] && mpoly->flag & ME_FACE_SEL) { action = SEL_DESELECT; break; } @@ -275,7 +323,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl for (int i = 0; i < me->totpoly; i++) { MPoly *mpoly = &me->mpoly[i]; - if ((mpoly->flag & ME_HIDE) == 0) { + if (!hide_poly[i]) { switch (action) { case SEL_SELECT: if ((mpoly->flag & ME_FACE_SEL) == 0) { @@ -299,7 +347,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl if (changed) { if (flush_flags) { - paintface_flush_flags(C, ob, SELECT); + paintface_flush_flags(C, ob, true, false); } } return changed; @@ -307,6 +355,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) { + using namespace blender; bool ok = false; float vec[3], bmat[3][3]; @@ -318,9 +367,13 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) copy_m3_m4(bmat, ob->obmat); + bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + for (int i = 0; i < me->totpoly; i++) { MPoly *mp = &me->mpoly[i]; - if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL)) { + if (hide_poly[i] || !(mp->flag & ME_FACE_SEL)) { continue; } @@ -342,6 +395,7 @@ bool paintface_mouse_select(bContext *C, const SelectPick_Params *params, Object *ob) { + using namespace blender; MPoly *mpoly_sel = nullptr; uint index; bool changed = false; @@ -350,10 +404,14 @@ bool paintface_mouse_select(bContext *C, /* Get the face under the cursor */ Mesh *me = BKE_mesh_from_object(ob); + bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + if (ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) { if (index < me->totpoly) { mpoly_sel = me->mpoly + index; - if ((mpoly_sel->flag & ME_HIDE) == 0) { + if (!hide_poly[index]) { found = true; } } @@ -402,7 +460,7 @@ bool paintface_mouse_select(bContext *C, /* image window redraw */ - paintface_flush_flags(C, ob, SELECT); + paintface_flush_flags(C, ob, true, false); ED_region_tag_redraw(CTX_wm_region(C)); /* XXX: should redraw all 3D views. */ changed = true; } @@ -463,17 +521,24 @@ void paintvert_tag_select_update(bContext *C, Object *ob) bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) { + using namespace blender; Mesh *me = BKE_mesh_from_object(ob); if (me == nullptr) { return false; } + bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + if (action == SEL_TOGGLE) { action = SEL_SELECT; for (int i = 0; i < me->totvert; i++) { MVert *mvert = &me->mvert[i]; - if ((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) { + if (!hide_poly[i] && mvert->flag & SELECT) { action = SEL_DESELECT; break; } @@ -483,7 +548,7 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) bool changed = false; for (int i = 0; i < me->totvert; i++) { MVert *mvert = &me->mvert[i]; - if ((mvert->flag & ME_HIDE) == 0) { + if (!hide_vert[i]) { switch (action) { case SEL_SELECT: if ((mvert->flag & SELECT) == 0) { @@ -526,6 +591,7 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags) { + using namespace blender; Mesh *me = BKE_mesh_from_object(ob); if (me == nullptr || me->dvert == nullptr) { @@ -536,10 +602,14 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags) paintvert_deselect_all_visible(ob, SEL_DESELECT, false); } + bke::AttributeAccessor attributes = bke::mesh_attributes(*me); + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + for (int i = 0; i < me->totvert; i++) { MVert *mv = &me->mvert[i]; MDeformVert *dv = &me->dvert[i]; - if ((mv->flag & ME_HIDE) == 0) { + if (!hide_poly[i]) { if (dv->dw == nullptr) { /* if null weight then not grouped */ mv->flag |= SELECT; @@ -554,25 +624,30 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags) void paintvert_hide(bContext *C, Object *ob, const bool unselected) { - Mesh *const me = BKE_mesh_from_object(ob); - - if (me == nullptr || me->totvert == 0) { + using namespace blender; + Mesh *me = BKE_mesh_from_object(ob); + if (me == NULL || me->totvert == 0) { return; } - for (int i = 0; i < me->totvert; i++) { - MVert *const mvert = &me->mvert[i]; + bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me); + bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>( + ".hide_vert", ATTR_DOMAIN_POINT); + MutableSpan<MVert> vertices(me->mvert, me->totvert); - if ((mvert->flag & ME_HIDE) == 0) { - if (((mvert->flag & SELECT) == 0) == unselected) { - mvert->flag |= ME_HIDE; + for (const int i : vertices.index_range()) { + MVert &vert = vertices[i]; + if (!hide_vert.span[i]) { + if (((vert.flag & SELECT) == 0) == unselected) { + hide_vert.span[i] = true; } } - if (mvert->flag & ME_HIDE) { - mvert->flag &= ~SELECT; + if (hide_vert.span[i]) { + vert.flag &= ~SELECT; } } + hide_vert.finish(); BKE_mesh_flush_hidden_from_verts(me); @@ -582,21 +657,27 @@ void paintvert_hide(bContext *C, Object *ob, const bool unselected) void paintvert_reveal(bContext *C, Object *ob, const bool select) { - Mesh *const me = BKE_mesh_from_object(ob); - - if (me == nullptr || me->totvert == 0) { + using namespace blender; + Mesh *me = BKE_mesh_from_object(ob); + if (me == NULL || me->totvert == 0) { return; } - for (int i = 0; i < me->totvert; i++) { - MVert *const mvert = &me->mvert[i]; + bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me); + const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); + MutableSpan<MVert> vertices(me->mvert, me->totvert); - if (mvert->flag & ME_HIDE) { - SET_FLAG_FROM_TEST(mvert->flag, select, SELECT); - mvert->flag &= ~ME_HIDE; + for (const int i : vertices.index_range()) { + MVert &vert = vertices[i]; + if (hide_vert[i]) { + SET_FLAG_FROM_TEST(vert.flag, select, SELECT); } } + /* Remove the hide attribute to reveal all vertices. */ + attributes.remove(".hide_vert"); + BKE_mesh_flush_hidden_from_verts(me); paintvert_flush_flags(ob); diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index d75c92f963f..af8084e16c4 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -594,6 +594,10 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo /* Uncomment for troubleshooting. */ // BM_mesh_validate(em->bm); + /* Copy the ID name characters to the mesh so code that depends on accessing the ID type can work + * on it. Necessary to use the attribute API. */ + strcpy(um->me.id.name, "MEundomesh_from_editmesh"); + BM_mesh_bm_to_me( NULL, em->bm, diff --git a/source/blender/editors/mesh/meshtools.cc b/source/blender/editors/mesh/meshtools.cc index 9e28e1bafdd..b1004b23a21 100644 --- a/source/blender/editors/mesh/meshtools.cc +++ b/source/blender/editors/mesh/meshtools.cc @@ -1329,6 +1329,7 @@ bool ED_mesh_pick_face_vert( */ struct VertPickData { const MVert *mvert; + const bool *hide_vert; const float *mval_f; /* [2] */ ARegion *region; @@ -1343,16 +1344,16 @@ static void ed_mesh_pick_vert__mapFunc(void *userData, const float UNUSED(no[3])) { VertPickData *data = static_cast<VertPickData *>(userData); - if ((data->mvert[index].flag & ME_HIDE) == 0) { - float sco[2]; - - if (ED_view3d_project_float_object(data->region, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) == - V3D_PROJ_RET_OK) { - const float len = len_manhattan_v2v2(data->mval_f, sco); - if (len < data->len_best) { - data->len_best = len; - data->v_idx_best = index; - } + if (data->hide_vert && data->hide_vert[index]) { + return; + } + float sco[2]; + if (ED_view3d_project_float_object(data->region, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) == + V3D_PROJ_RET_OK) { + const float len = len_manhattan_v2v2(data->mval_f, sco); + if (len < data->len_best) { + data->len_best = len; + data->v_idx_best = index; } } } @@ -1416,6 +1417,8 @@ bool ED_mesh_pick_vert( data.mval_f = mval_f; data.len_best = FLT_MAX; data.v_idx_best = -1; + data.hide_vert = (const bool *)CustomData_get_layer_named( + &me_eval->vdata, CD_PROP_BOOL, ".hide_vert"); BKE_mesh_foreach_mapped_vert(me_eval, ed_mesh_pick_vert__mapFunc, &data, MESH_FOREACH_NOP); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 6369afac632..eb5aaf7ef61 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -1034,6 +1034,7 @@ static void vgroup_select_verts(Object *ob, int select) } else { if (me->dvert) { + const bool *hide_vert = CustomData_get_layer_named(&me->vdata, CD_PROP_BOOL, ".hide_vert"); MVert *mv; MDeformVert *dv; int i; @@ -1042,7 +1043,7 @@ static void vgroup_select_verts(Object *ob, int select) dv = me->dvert; for (i = 0; i < me->totvert; i++, mv++, dv++) { - if (!(mv->flag & ME_HIDE)) { + if (hide_vert != NULL && !hide_vert[i]) { if (BKE_defvert_find_index(dv, def_nr)) { if (select) { mv->flag |= SELECT; @@ -1930,7 +1931,11 @@ static void vgroup_smooth_subset(Object *ob, #define IS_BM_VERT_READ(v) (use_hide ? (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == 0) : true) #define IS_BM_VERT_WRITE(v) (use_select ? (BM_elem_flag_test(v, BM_ELEM_SELECT) != 0) : true) -#define IS_ME_VERT_READ(v) (use_hide ? (((v)->flag & ME_HIDE) == 0) : true) + const bool *hide_vert = me ? (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".hide_vert") : + NULL; + +#define IS_ME_VERT_READ(v) (use_hide ? (hide_vert && hide_vert[v]) : true) #define IS_ME_VERT_WRITE(v) (use_select ? (((v)->flag & SELECT) != 0) : true) /* initialize used verts */ @@ -1956,8 +1961,8 @@ static void vgroup_smooth_subset(Object *ob, if (IS_ME_VERT_WRITE(v)) { for (int j = 0; j < emap[i].count; j++) { const MEdge *e = &me->medge[emap[i].indices[j]]; - const MVert *v_other = &me->mvert[(e->v1 == i) ? e->v2 : e->v1]; - if (IS_ME_VERT_READ(v_other)) { + const int i_other = (e->v1 == i) ? e->v2 : e->v1; + if (IS_ME_VERT_READ(i_other)) { STACK_PUSH(verts_used, i); break; } @@ -2031,9 +2036,7 @@ static void vgroup_smooth_subset(Object *ob, for (j = 0; j < emap[i].count; j++) { MEdge *e = &me->medge[emap[i].indices[j]]; const int i_other = (e->v1 == i ? e->v2 : e->v1); - MVert *v_other = &me->mvert[i_other]; - - if (IS_ME_VERT_READ(v_other)) { + if (IS_ME_VERT_READ(i_other)) { WEIGHT_ACCUMULATE; } } diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index 944b3f953a0..c904d533db8 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -78,6 +78,12 @@ static void partialvis_update_mesh(Object *ob, BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert); paint_mask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK); + bool *hide_vert = CustomData_get_layer_named(&me->vdata, CD_PROP_BOOL, ".hide_vert"); + if (hide_vert == NULL) { + hide_vert = CustomData_add_layer_named( + &me->vdata, CD_PROP_BOOL, CD_CALLOC, NULL, me->totvert, ".hide_vert"); + } + SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN); for (i = 0; i < totvert; i++) { @@ -86,16 +92,11 @@ static void partialvis_update_mesh(Object *ob, /* Hide vertex if in the hide volume. */ if (is_effected(area, planes, v->co, vmask)) { - if (action == PARTIALVIS_HIDE) { - v->flag |= ME_HIDE; - } - else { - v->flag &= ~ME_HIDE; - } + hide_vert[vert_indices[i]] = (action == PARTIALVIS_HIDE); any_changed = true; } - if (!(v->flag & ME_HIDE)) { + if (!hide_vert[vert_indices[i]]) { any_visible = true; } } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 02d21941a25..ffa931268fd 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -344,9 +344,11 @@ int SCULPT_active_face_set_get(SculptSession *ss) void SCULPT_vertex_visible_set(SculptSession *ss, PBVHVertRef vertex, bool visible) { switch (BKE_pbvh_type(ss->pbvh)) { - case PBVH_FACES: - SET_FLAG_FROM_TEST(ss->mvert[vertex.i].flag, !visible, ME_HIDE); + case PBVH_FACES: { + bool *hide_vert = BKE_pbvh_get_vert_hide_for_write(ss->pbvh); + hide_vert[vertex.i] = visible; break; + } case PBVH_BMESH: { BMVert *v = (BMVert *)vertex.i; BM_elem_flag_set(v, BM_ELEM_HIDDEN, !visible); @@ -360,8 +362,10 @@ void SCULPT_vertex_visible_set(SculptSession *ss, PBVHVertRef vertex, bool visib bool SCULPT_vertex_visible_get(SculptSession *ss, PBVHVertRef vertex) { switch (BKE_pbvh_type(ss->pbvh)) { - case PBVH_FACES: - return !(ss->mvert[vertex.i].flag & ME_HIDE); + case PBVH_FACES: { + const bool *hide_vert = BKE_pbvh_get_vert_hide(ss->pbvh); + return hide_vert == NULL || !hide_vert[vertex.i]; + } case PBVH_BMESH: return !BM_elem_flag_test((BMVert *)vertex.i, BM_ELEM_HIDDEN); case PBVH_GRIDS: { diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c index 4f91d2215fb..40b4b74a441 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c @@ -227,8 +227,9 @@ static void SCULPT_dynamic_topology_disable_ex( me->face_sets_color_default = 1; /* Sync the visibility to vertices manually as the pmap is still not initialized. */ - for (int i = 0; i < me->totvert; i++) { - me->mvert[i].flag &= ~ME_HIDE; + bool *hide_vert = (bool *)CustomData_get_layer_named(&me->vdata, CD_PROP_BOOL, ".hide_vert"); + if (hide_vert != NULL) { + memset(hide_vert, 0, sizeof(bool) * me->totvert); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index dc814d6d22f..04b2b2f04bf 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -346,14 +346,13 @@ static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode, bool SculptSession *ss = ob->sculpt; SubdivCCG *subdiv_ccg = ss->subdiv_ccg; - if (unode->maxvert) { - MVert *mvert = ss->mvert; + bool *hide_vert = BKE_pbvh_get_vert_hide_for_write(ss->pbvh); + if (unode->maxvert) { for (int i = 0; i < unode->totvert; i++) { - MVert *v = &mvert[unode->index[i]]; - if ((BLI_BITMAP_TEST(unode->vert_hidden, i) != 0) != ((v->flag & ME_HIDE) != 0)) { + if ((BLI_BITMAP_TEST(unode->vert_hidden, i) != 0) != hide_vert[i]) { BLI_BITMAP_FLIP(unode->vert_hidden, i); - v->flag ^= ME_HIDE; + hide_vert[unode->index[i]] = !hide_vert[i]; modified_vertices[unode->index[i]] = true; } } @@ -1247,6 +1246,11 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode) PBVH *pbvh = ob->sculpt->pbvh; PBVHNode *node = unode->node; + const bool *hide_vert = BKE_pbvh_get_vert_hide(pbvh); + if (hide_vert == NULL) { + return; + } + if (unode->grids) { /* Already stored during allocation. */ } @@ -1258,7 +1262,7 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode) BKE_pbvh_node_num_verts(pbvh, node, NULL, &allvert); BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert); for (int i = 0; i < allvert; i++) { - BLI_BITMAP_SET(unode->vert_hidden, i, mvert[vert_indices[i]].flag & ME_HIDE); + BLI_BITMAP_SET(unode->vert_hidden, i, hide_vert[vert_indices[i]]); } } } diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index 35d4746608b..6256eeb9621 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -205,6 +205,7 @@ typedef struct foreachScreenObjectVert_userData { void (*func)(void *userData, MVert *mv, const float screen_co[2], int index); void *userData; ViewContext vc; + const bool *hide_vert; eV3DProjTest clip_flag; } foreachScreenObjectVert_userData; @@ -262,18 +263,19 @@ static void meshobject_foreachScreenVert__mapFunc(void *userData, const float UNUSED(no[3])) { foreachScreenObjectVert_userData *data = userData; + if (data->hide_vert && data->hide_vert[index]) { + return; + } struct MVert *mv = &((Mesh *)(data->vc.obact->data))->mvert[index]; - if (!(mv->flag & ME_HIDE)) { - float screen_co[2]; - - if (ED_view3d_project_float_object(data->vc.region, co, screen_co, data->clip_flag) != - V3D_PROJ_RET_OK) { - return; - } + float screen_co[2]; - data->func(data->userData, mv, screen_co, index); + if (ED_view3d_project_float_object(data->vc.region, co, screen_co, data->clip_flag) != + V3D_PROJ_RET_OK) { + return; } + + data->func(data->userData, mv, screen_co, index); } void meshobject_foreachScreenVert( @@ -297,6 +299,8 @@ void meshobject_foreachScreenVert( data.func = func; data.userData = userData; data.clip_flag = clip_flag; + data.hide_vert = (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".hide_vert"); if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { ED_view3d_clipping_local(vc->rv3d, vc->obact->obmat); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 571c39f30cb..cd609f7e8cf 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -335,14 +335,16 @@ static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp sel_op) { MVert *mv = me->mvert; - uint index; bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; if (mv) { - for (index = 0; index < me->totvert; index++, mv++) { - if (!(mv->flag & ME_HIDE)) { + const bool *hide_vert = (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".hide_vert"); + + for (int index = 0; index < me->totvert; index++, mv++) { + if (!(hide_vert && hide_vert[index])) { const bool is_select = mv->flag & SELECT; const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); @@ -362,14 +364,16 @@ static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *me, const eSelectOp sel_op) { MPoly *mpoly = me->mpoly; - uint index; bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; if (mpoly) { - for (index = 0; index < me->totpoly; index++, mpoly++) { - if (!(mpoly->flag & ME_HIDE)) { + const bool *hide_poly = (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".hide_poly"); + + for (int index = 0; index < me->totpoly; index++, mpoly++) { + if (!(hide_poly && hide_poly[index])) { const bool is_select = mpoly->flag & ME_FACE_SEL; const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); @@ -1260,7 +1264,7 @@ static bool do_lasso_select_paintface(ViewContext *vc, } if (changed) { - paintface_flush_flags(vc->C, ob, SELECT); + paintface_flush_flags(vc->C, ob, true, false); } return changed; } @@ -3192,7 +3196,7 @@ static bool do_paintface_box_select(ViewContext *vc, } if (changed) { - paintface_flush_flags(vc->C, vc->obact, SELECT); + paintface_flush_flags(vc->C, vc->obact, true, false); } return changed; } @@ -4093,7 +4097,7 @@ static bool paint_facesel_circle_select(ViewContext *vc, } if (changed) { - paintface_flush_flags(vc->C, ob, SELECT); + paintface_flush_flags(vc->C, ob, true, false); } return changed; } diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index 6dc49ff494d..d1d91cb7508 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -48,7 +48,6 @@ typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers; * Threaded: do not call any functions that use OpenGL calls! */ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const struct Mesh *mesh, - const struct MVert *vertices, const struct MLoopTri *looptri, const int *sculpt_face_sets, const int *face_indices, diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 2a0f624ac45..d64b8b4118a 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -211,11 +211,11 @@ static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim) * \{ */ static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt, - const MVert *mvert, + const bool *hide_vert, const MLoop *mloop, const int *sculpt_face_sets) { - return (!paint_is_face_hidden(lt, mvert, mloop) && sculpt_face_sets && + return (!paint_is_face_hidden(lt, hide_vert, mloop) && sculpt_face_sets && sculpt_face_sets[lt->poly] > SCULPT_FACE_SET_NONE); } @@ -233,6 +233,9 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id, GPUAttrRef vcol_refs[MAX_GPU_ATTR]; GPUAttrRef cd_uvs[MAX_GPU_ATTR]; + const bool *hide_vert = (bool *)CustomData_get_layer_named( + &mesh->vdata, CD_PROP_BOOL, ".hide_vert"); + const CustomDataLayer *actcol = BKE_id_attributes_active_color_get(&mesh->id); eAttrDomain actcol_domain = actcol ? BKE_id_attribute_domain(&mesh->id, actcol) : ATTR_DOMAIN_AUTO; @@ -310,7 +313,7 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id, for (uint i = 0; i < buffers->face_indices_len; i++) { const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; - if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) { + if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, buffers->mloop, sculpt_face_sets)) { continue; } @@ -350,7 +353,7 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id, buffers->mloop[lt->tri[2]].v, }; - if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) { + if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, buffers->mloop, sculpt_face_sets)) { continue; } @@ -390,7 +393,7 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id, buffers->mloop[lt->tri[2]].v, }; - if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) { + if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, buffers->mloop, sculpt_face_sets)) { continue; } @@ -454,7 +457,6 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id, } GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh, - const MVert *vertices, const MLoopTri *looptri, const int *sculpt_face_sets, const int *face_indices, @@ -469,6 +471,9 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh, buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); + const bool *hide_vert = (bool *)CustomData_get_layer_named( + &mesh->vdata, CD_PROP_BOOL, ".hide_vert"); + /* smooth or flat for all */ buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH; @@ -477,7 +482,7 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh, /* Count the number of visible triangles */ for (i = 0, tottri = 0; i < face_indices_len; i++) { const MLoopTri *lt = &looptri[face_indices[i]]; - if (gpu_pbvh_is_looptri_visible(lt, vertices, mloop, sculpt_face_sets)) { + if (gpu_pbvh_is_looptri_visible(lt, hide_vert, mloop, sculpt_face_sets)) { int r_edges[3]; BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges); for (int j = 0; j < 3; j++) { @@ -510,7 +515,7 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh, const MLoopTri *lt = &looptri[face_indices[i]]; /* Skip hidden faces */ - if (!gpu_pbvh_is_looptri_visible(lt, vertices, mloop, sculpt_face_sets)) { + if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, mloop, sculpt_face_sets)) { continue; } diff --git a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc index d8af2fc584d..3a14c060484 100644 --- a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc +++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc @@ -137,7 +137,7 @@ eAttrDomain BKE_id_attribute_domain(const struct ID *UNUSED(id), /** \name Stubs of BKE_paint.h * \{ */ bool paint_is_face_hidden(const struct MLoopTri *UNUSED(lt), - const struct MVert *UNUSED(mvert), + const bool *UNUSED(hide_vert), const struct MLoop *UNUSED(mloop)) { BLI_assert_unreachable(); diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 9460746630d..9b050af0891 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -296,7 +296,7 @@ void OBJMesh::store_uv_coords_and_indices() const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT}; UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create( - mpoly, mloop, mloopuv, totpoly, totvert, limit, false, false); + mpoly, nullptr, mloop, mloopuv, totpoly, totvert, limit, false, false); uv_indices_.resize(totpoly); /* At least total vertices of a mesh will be present in its texture map. So diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 4090c45a753..abef90495c5 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -30,10 +30,13 @@ typedef struct MVert { } MVert; /** #MVert.flag */ + +#ifdef DNA_DEPRECATED_ALLOW enum { /* SELECT = (1 << 0), */ ME_HIDE = (1 << 4), }; +#endif /** * Mesh Edges. @@ -351,7 +354,7 @@ typedef struct MDisps { /** * Used for hiding parts of a multires mesh. - * Essentially the multires equivalent of #MVert.flag's ME_HIDE bit. + * Essentially the multires equivalent of the mesh ".hide_vert" boolean layer. * * \note This is a bitmap, keep in sync with type used in BLI_bitmap.h */ diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 9aef19c8230..bdc96f6dec1 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -356,6 +356,27 @@ static void rna_MeshVertex_normal_get(PointerRNA *ptr, float *value) copy_v3_v3(value, vert_normals[index]); } +static bool rna_MeshVertex_hide_get(PointerRNA *ptr) +{ + const Mesh *mesh = rna_mesh(ptr); + const bool *hide_vert = (const bool *)CustomData_get_layer_named( + &mesh->vdata, CD_PROP_BOOL, ".hide_vert"); + const int index = (const MVert *)ptr->data - mesh->mvert; + BLI_assert(index >= 0); + BLI_assert(index < mesh->totvert); + return hide_vert[index]; +} + +static void rna_MeshVertex_hide_set(PointerRNA *ptr, bool value) +{ + Mesh *mesh = rna_mesh(ptr); + bool *hide_vert = (bool *)CustomData_get_layer_named(&mesh->vdata, CD_PROP_BOOL, ".hide_vert"); + const int index = (const MVert *)ptr->data - mesh->mvert; + BLI_assert(index >= 0); + BLI_assert(index < mesh->totvert); + hide_vert[index] = value; +} + static float rna_MeshVertex_bevel_weight_get(PointerRNA *ptr) { MVert *mvert = (MVert *)ptr->data; @@ -464,6 +485,27 @@ static void rna_MeshPolygon_normal_get(PointerRNA *ptr, float *values) BKE_mesh_calc_poly_normal(mp, me->mloop + mp->loopstart, me->mvert, values); } +static bool rna_MeshPolygon_hide_get(PointerRNA *ptr) +{ + const Mesh *mesh = rna_mesh(ptr); + const bool *hide_poly = (const bool *)CustomData_get_layer_named( + &mesh->pdata, CD_PROP_BOOL, ".hide_poly"); + const int index = (const MPoly *)ptr->data - mesh->mpoly; + BLI_assert(index >= 0); + BLI_assert(index < mesh->totpoly); + return hide_poly[index]; +} + +static void rna_MeshPolygon_hide_set(PointerRNA *ptr, bool value) +{ + Mesh *mesh = rna_mesh(ptr); + bool *hide_poly = (bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly"); + const int index = (const MPoly *)ptr->data - mesh->mpoly; + BLI_assert(index >= 0); + BLI_assert(index < mesh->totpoly); + hide_poly[index] = value; +} + static void rna_MeshPolygon_center_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); @@ -1188,6 +1230,27 @@ static int rna_MeshEdge_index_get(PointerRNA *ptr) return (int)(edge - me->medge); } +static bool rna_MeshEdge_hide_get(PointerRNA *ptr) +{ + const Mesh *mesh = rna_mesh(ptr); + const bool *hide_edge = (const bool *)CustomData_get_layer_named( + &mesh->pdata, CD_PROP_BOOL, ".hide_edge"); + const int index = (const MEdge *)ptr->data - mesh->medge; + BLI_assert(index >= 0); + BLI_assert(index < mesh->totedge); + return hide_edge[index]; +} + +static void rna_MeshEdge_hide_set(PointerRNA *ptr, bool value) +{ + Mesh *mesh = rna_mesh(ptr); + bool *hide_edge = (bool *)CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, ".hide_edge"); + const int index = (const MEdge *)ptr->data - mesh->medge; + BLI_assert(index >= 0); + BLI_assert(index < mesh->totedge); + hide_edge[index] = value; +} + static int rna_MeshLoopTriangle_index_get(PointerRNA *ptr) { Mesh *me = rna_mesh(ptr); @@ -1830,8 +1893,8 @@ static void rna_def_mvert(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Mesh_update_select"); prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_HIDE); RNA_def_property_ui_text(prop, "Hide", ""); + RNA_def_property_boolean_funcs(prop, "rna_MeshVertex_hide_get", "rna_MeshVertex_hide_set"); RNA_def_property_update(prop, 0, "rna_Mesh_update_select"); prop = RNA_def_property(srna, "bevel_weight", PROP_FLOAT, PROP_NONE); @@ -1906,8 +1969,8 @@ static void rna_def_medge(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Mesh_update_select"); prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_HIDE); RNA_def_property_ui_text(prop, "Hide", ""); + RNA_def_property_boolean_funcs(prop, "rna_MeshEdge_hide_get", "rna_MeshEdge_hide_set"); RNA_def_property_update(prop, 0, "rna_Mesh_update_select"); prop = RNA_def_property(srna, "use_seam", PROP_BOOLEAN, PROP_NONE); @@ -2119,8 +2182,8 @@ static void rna_def_mpolygon(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Mesh_update_select"); prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_HIDE); RNA_def_property_ui_text(prop, "Hide", ""); + RNA_def_property_boolean_funcs(prop, "rna_MeshPolygon_hide_get", "rna_MeshPolygon_hide_set"); RNA_def_property_update(prop, 0, "rna_Mesh_update_select"); prop = RNA_def_property(srna, "use_smooth", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 3df4fbcbea8..55d9d148d10 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -201,11 +201,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * updateFaceCount(ctx, dmd, bm->totface); - result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); /* make sure we never alloc'd these */ BLI_assert(bm->vtoolflagpool == NULL && bm->etoolflagpool == NULL && bm->ftoolflagpool == NULL); BLI_assert(bm->vtable == NULL && bm->etable == NULL && bm->ftable == NULL); + result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); + BM_mesh_free(bm); #ifdef USE_TIMEIT |