From 3724ebeaa6cb77a17604a5f1e7d5589e9f044e61 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 6 Aug 2025 13:40:51 +0200 Subject: [PATCH] Refactor: Extract BMesh attribute lookup function This is the second time I've needed a function to find an attribute by name on all attribute domains, with a third time coming soon. It seems time to put this in a BMesh header. Pull Request: https://projects.blender.org/blender/blender/pulls/144039 --- source/blender/bmesh/intern/bmesh_interp.cc | 36 ++++++++++++++ source/blender/bmesh/intern/bmesh_interp.hh | 23 +++++++++ source/blender/draw/intern/draw_pbvh.cc | 45 +---------------- .../extract_mesh_vbo_attributes.cc | 49 ++----------------- 4 files changed, 63 insertions(+), 90 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_interp.cc b/source/blender/bmesh/intern/bmesh_interp.cc index 5521c83db02..b18f0906026 100644 --- a/source/blender/bmesh/intern/bmesh_interp.cc +++ b/source/blender/bmesh/intern/bmesh_interp.cc @@ -21,6 +21,8 @@ #include "BLI_task.h" #include "BKE_attribute.h" +#include "BKE_attribute.hh" +#include "BKE_attribute_legacy_convert.hh" #include "BKE_customdata.hh" #include "BKE_multires.hh" @@ -1067,6 +1069,40 @@ void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float } } +BMDataLayerLookup BM_data_layer_lookup(const BMesh &bm, const blender::StringRef name) +{ + using namespace blender; + for (const CustomDataLayer &layer : Span(bm.vdata.layers, bm.vdata.totlayer)) { + if (layer.name == name) { + return {layer.offset, + bke::AttrDomain::Point, + *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; + } + } + for (const CustomDataLayer &layer : Span(bm.edata.layers, bm.edata.totlayer)) { + if (layer.name == name) { + return {layer.offset, + bke::AttrDomain::Edge, + *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; + } + } + for (const CustomDataLayer &layer : Span(bm.pdata.layers, bm.pdata.totlayer)) { + if (layer.name == name) { + return {layer.offset, + bke::AttrDomain::Face, + *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; + } + } + for (const CustomDataLayer &layer : Span(bm.ldata.layers, bm.ldata.totlayer)) { + if (layer.name == name) { + return {layer.offset, + bke::AttrDomain::Corner, + *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; + } + } + return {}; +} + /* -------------------------------------------------------------------- */ /** \name Loop interpolation functions: BM_vert_loop_groups_data_layer_*** * diff --git a/source/blender/bmesh/intern/bmesh_interp.hh b/source/blender/bmesh/intern/bmesh_interp.hh index 38936efb03b..cbd3d92ebb6 100644 --- a/source/blender/bmesh/intern/bmesh_interp.hh +++ b/source/blender/bmesh/intern/bmesh_interp.hh @@ -15,6 +15,11 @@ struct LinkNode; struct MemArena; +namespace blender::bke { +enum class AttrDomain : int8_t; +enum class AttrType : int16_t; +} // namespace blender::bke + void BM_loop_interp_multires_ex(BMesh *bm, BMLoop *l_dst, const BMFace *f_src, @@ -88,6 +93,24 @@ bool BM_data_layer_free_named(BMesh *bm, CustomData *data, blender::StringRef na void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n); void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n); +/* See #BM_data_layer_lookup. */ +struct BMDataLayerLookup { + const int offset = -1; + blender::bke::AttrDomain domain; + blender::bke::AttrType type; + operator bool() const + { + return offset != -1; + } +}; + +/** + * Search for a named custom data layer on all attribute domains and return the domain and type. + * This is roughly analogous to #Mesh::attributes().lookup(...), but keep in mind that certain + * attributes stored on #Mesh are not stored as attributes on #BMesh. + */ +BMDataLayerLookup BM_data_layer_lookup(const BMesh &bm, const blender::StringRef name); + float BM_elem_float_data_get(CustomData *cd, void *element, int type); void BM_elem_float_data_set(CustomData *cd, void *element, int type, float val); diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index 7b889e272a0..2bba72f6f49 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -1054,49 +1054,6 @@ BLI_NOINLINE static void update_face_sets_bmesh(const Object &object, } } -struct BMeshAttributeLookup { - const int offset = -1; - bke::AttrDomain domain; - bke::AttrType type; - operator bool() const - { - return offset != -1; - } -}; - -static BMeshAttributeLookup lookup_bmesh_attribute(const BMesh &bm, const StringRef name) -{ - for (const CustomDataLayer &layer : Span(bm.vdata.layers, bm.vdata.totlayer)) { - if (layer.name == name) { - return {layer.offset, - bke::AttrDomain::Point, - *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; - } - } - for (const CustomDataLayer &layer : Span(bm.edata.layers, bm.edata.totlayer)) { - if (layer.name == name) { - return {layer.offset, - bke::AttrDomain::Edge, - *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; - } - } - for (const CustomDataLayer &layer : Span(bm.pdata.layers, bm.pdata.totlayer)) { - if (layer.name == name) { - return {layer.offset, - bke::AttrDomain::Face, - *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; - } - } - for (const CustomDataLayer &layer : Span(bm.ldata.layers, bm.ldata.totlayer)) { - if (layer.name == name) { - return {layer.offset, - bke::AttrDomain::Corner, - *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; - } - } - return {}; -} - BLI_NOINLINE static void update_generic_attribute_bmesh(const Object &object, const OrigMeshData &orig_mesh_data, const IndexMask &node_mask, @@ -1106,7 +1063,7 @@ BLI_NOINLINE static void update_generic_attribute_bmesh(const Object &object, const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object); const Span nodes = pbvh.nodes(); const BMesh &bm = *object.sculpt->bm; - const BMeshAttributeLookup attr = lookup_bmesh_attribute(bm, name); + const BMDataLayerLookup attr = BM_data_layer_lookup(bm, name); if (!attr || attr.domain == bke::AttrDomain::Edge) { return; } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc index 4326ec0081c..d8fcc5cfc45 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc @@ -171,51 +171,8 @@ static void extract_data_bmesh_loop(const BMesh &bm, const int cd_offset, gpu::V } } -struct BMeshAttributeLookup { - const int offset = -1; - bke::AttrDomain domain; - bke::AttrType type; - operator bool() const - { - return offset != -1; - } -}; - -static BMeshAttributeLookup lookup_bmesh_attribute(const BMesh &bm, const StringRef name) -{ - for (const CustomDataLayer &layer : Span(bm.vdata.layers, bm.vdata.totlayer)) { - if (layer.name == name) { - return {layer.offset, - bke::AttrDomain::Point, - *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; - } - } - for (const CustomDataLayer &layer : Span(bm.edata.layers, bm.edata.totlayer)) { - if (layer.name == name) { - return {layer.offset, - bke::AttrDomain::Edge, - *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; - } - } - for (const CustomDataLayer &layer : Span(bm.pdata.layers, bm.pdata.totlayer)) { - if (layer.name == name) { - return {layer.offset, - bke::AttrDomain::Face, - *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; - } - } - for (const CustomDataLayer &layer : Span(bm.ldata.layers, bm.ldata.totlayer)) { - if (layer.name == name) { - return {layer.offset, - bke::AttrDomain::Corner, - *bke::custom_data_type_to_attr_type(eCustomDataType(layer.type))}; - } - } - return {}; -} - static void extract_attribute_data(const MeshRenderData &mr, - const BMeshAttributeLookup &attr, + const BMDataLayerLookup &attr, gpu::VertBuf &vbo) { bke::attribute_math::convert_to_static_type(attr.type, [&](auto dummy) { @@ -272,7 +229,7 @@ gpu::VertBufPtr extract_attribute(const MeshRenderData &mr, const StringRef name { gpu::VertBuf *vbo = GPU_vertbuf_calloc(); if (mr.extract_type == MeshExtractType::BMesh) { - const BMeshAttributeLookup attr = lookup_bmesh_attribute(*mr.bm, name); + const BMDataLayerLookup attr = BM_data_layer_lookup(*mr.bm, name); if (!attr) { return {}; } @@ -313,7 +270,7 @@ gpu::VertBufPtr extract_attribute_subdiv(const MeshRenderData &mr, gpu::VertBufPtr coarse_vbo; bke::AttrType type; if (mr.extract_type == MeshExtractType::BMesh) { - const BMeshAttributeLookup attr = lookup_bmesh_attribute(*mr.bm, name); + const BMDataLayerLookup attr = BM_data_layer_lookup(*mr.bm, name); if (!attr) { return {}; }