diff --git a/examples/gl_viewer/gl_viewer.cpp b/examples/gl_viewer/gl_viewer.cpp index a66a591f6..3899d8e36 100644 --- a/examples/gl_viewer/gl_viewer.cpp +++ b/examples/gl_viewer/gl_viewer.cpp @@ -415,7 +415,7 @@ bool loadMesh(Viewer* viewer, fastgltf::Mesh& mesh) { { // Position - auto& positionAccessor = asset.accessors[positionIt->second]; + auto& positionAccessor = asset.accessors[positionIt->accessorIndex]; if (!positionAccessor.bufferViewIndex.has_value()) continue; @@ -442,7 +442,7 @@ bool loadMesh(Viewer* viewer, fastgltf::Mesh& mesh) { auto texcoordAttribute = std::string("TEXCOORD_") + std::to_string(baseColorTexcoordIndex); if (const auto* texcoord = it->findAttribute(texcoordAttribute); texcoord != it->attributes.end()) { // Tex coord - auto& texCoordAccessor = asset.accessors[texcoord->second]; + auto& texCoordAccessor = asset.accessors[texcoord->accessorIndex]; if (!texCoordAccessor.bufferViewIndex.has_value()) continue; diff --git a/include/fastgltf/types.hpp b/include/fastgltf/types.hpp index 37c00b109..8556e1417 100644 --- a/include/fastgltf/types.hpp +++ b/include/fastgltf/types.hpp @@ -1632,7 +1632,10 @@ namespace fastgltf { math::fvec3 scale = math::fvec3(1.f); }; - FASTGLTF_EXPORT using attribute_type = std::pair; + FASTGLTF_EXPORT struct Attribute { + FASTGLTF_STD_PMR_NS::string name; + std::size_t accessorIndex; + }; FASTGLTF_EXPORT struct Node { Optional meshIndex; @@ -1657,13 +1660,13 @@ namespace fastgltf { /** * Only ever non-empty when EXT_mesh_gpu_instancing is enabled and used by the asset. */ - FASTGLTF_STD_PMR_NS::vector instancingAttributes; + FASTGLTF_STD_PMR_NS::vector instancingAttributes; FASTGLTF_STD_PMR_NS::string name; [[nodiscard]] auto findInstancingAttribute(std::string_view attributeName) noexcept { for (auto it = instancingAttributes.begin(); it != instancingAttributes.end(); ++it) { - if (it->first == attributeName) + if (it->name == attributeName) return it; } return instancingAttributes.end(); @@ -1671,7 +1674,7 @@ namespace fastgltf { [[nodiscard]] auto findInstancingAttribute(std::string_view attributeName) const noexcept { for (auto it = instancingAttributes.cbegin(); it != instancingAttributes.cend(); ++it) { - if (it->first == attributeName) + if (it->name == attributeName) return it; } return instancingAttributes.cend(); @@ -1681,10 +1684,10 @@ namespace fastgltf { FASTGLTF_EXPORT struct Primitive { // Instead of a map, we have a list of attributes here. Each pair contains // the name of the attribute and the corresponding accessor index. - FASTGLTF_FG_PMR_NS::SmallVector attributes; + FASTGLTF_FG_PMR_NS::SmallVector attributes; PrimitiveType type = PrimitiveType::Triangles; - FASTGLTF_STD_PMR_NS::vector> targets; + FASTGLTF_STD_PMR_NS::vector> targets; Optional indicesAccessor; Optional materialIndex; @@ -1697,16 +1700,16 @@ namespace fastgltf { std::vector> mappings; [[nodiscard]] auto findAttribute(std::string_view name) noexcept { - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - if (it->first == name) + for (auto* it = attributes.begin(); it != attributes.end(); ++it) { + if (it->name == name) return it; } return attributes.end(); } [[nodiscard]] auto findAttribute(std::string_view name) const noexcept { - for (auto it = attributes.cbegin(); it != attributes.cend(); ++it) { - if (it->first == name) + for (const auto* it = attributes.cbegin(); it != attributes.cend(); ++it) { + if (it->name == name) return it; } return attributes.cend(); @@ -1714,8 +1717,8 @@ namespace fastgltf { [[nodiscard]] auto findTargetAttribute(std::size_t targetIndex, std::string_view name) noexcept { auto& targetAttributes = targets[targetIndex]; - for (auto it = targetAttributes.begin(); it != targetAttributes.end(); ++it) { - if (it->first == name) + for (auto* it = targetAttributes.begin(); it != targetAttributes.end(); ++it) { + if (it->name == name) return it; } return targetAttributes.end(); @@ -1723,8 +1726,8 @@ namespace fastgltf { [[nodiscard]] auto findTargetAttribute(std::size_t targetIndex, std::string_view name) const noexcept { const auto& targetAttributes = targets[targetIndex]; - for (auto it = targetAttributes.cbegin(); it != targetAttributes.cend(); ++it) { - if (it->first == name) + for (const auto* it = targetAttributes.cbegin(); it != targetAttributes.cend(); ++it) { + if (it->name == name) return it; } return targetAttributes.cend(); diff --git a/src/fastgltf.cpp b/src/fastgltf.cpp index 9844d9a99..c35dada6d 100644 --- a/src/fastgltf.cpp +++ b/src/fastgltf.cpp @@ -807,12 +807,14 @@ template fg::Error fg::Parser::parseAttributes(simdjson::dom::objec for (const auto& field : object) { const auto key = field.key; - std::uint64_t attributeIndex; - if (field.value.get_uint64().get(attributeIndex) != SUCCESS) FASTGLTF_UNLIKELY { + std::uint64_t accessorIndex; + if (field.value.get_uint64().get(accessorIndex) != SUCCESS) FASTGLTF_UNLIKELY { return Error::InvalidGltf; } - attributes.emplace_back( - std::make_pair(FASTGLTF_CONSTRUCT_PMR_RESOURCE(FASTGLTF_STD_PMR_NS::string, resourceAllocator.get(), key), static_cast(attributeIndex))); + attributes.emplace_back(Attribute { + .name = FASTGLTF_CONSTRUCT_PMR_RESOURCE(FASTGLTF_STD_PMR_NS::string, resourceAllocator.get(), key), + .accessorIndex = static_cast(accessorIndex), + }); } return Error::None; } @@ -820,7 +822,7 @@ template fg::Error fg::Parser::parseAttributes(simdjson::dom::objec // TODO: Is there some nicer way of declaring a templated version parseAttributes? // Currently, this exists because resourceAllocator is a optional field of Parser, which we can't unconditionally // pass as a parameter to a function, so parseAttributes needs to be a member function of Parser. -template fg::Error fg::Parser::parseAttributes(simdjson::dom::object&, FASTGLTF_STD_PMR_NS::vector&); +template fg::Error fg::Parser::parseAttributes(simdjson::dom::object&, FASTGLTF_STD_PMR_NS::vector&); template fg::Error fg::Parser::parseAttributes(simdjson::dom::object&, decltype(fastgltf::Primitive::attributes)&); namespace fastgltf { @@ -886,7 +888,7 @@ fg::Error fg::Parser::generateMeshIndices(fastgltf::Asset& asset) const { if (positionAttribute == primitive.attributes.end()) { return Error::InvalidGltf; } - auto positionCount = asset.accessors[positionAttribute->second].count; + auto positionCount = asset.accessors[positionAttribute->accessorIndex].count; auto primitiveCount = [&]() -> std::size_t { switch (primitive.type) { @@ -4754,7 +4756,7 @@ void fg::Exporter::writeMeshes(const Asset& asset, std::string& json) { { json += R"("attributes":{)"; for (auto ita = itp->attributes.begin(); ita != itp->attributes.end(); ++ita) { - json += '"' + std::string(ita->first) + "\":" + std::to_string(ita->second); + json += '"' + std::string(ita->name) + "\":" + std::to_string(ita->accessorIndex); if (uabs(std::distance(itp->attributes.begin(), ita)) + 1 attributes.size()) json += ','; } @@ -4929,7 +4931,7 @@ void fg::Exporter::writeNodes(const Asset& asset, std::string& json) { if (!it->instancingAttributes.empty()) { json += R"("EXT_mesh_gpu_instancing":{"attributes":{)"; for (auto ait = it->instancingAttributes.begin(); ait != it->instancingAttributes.end(); ++ait) { - json += '"' + std::string(ait->first) + "\":" + std::to_string(ait->second); + json += '"' + std::string(ait->name) + "\":" + std::to_string(ait->accessorIndex); if (uabs(std::distance(it->instancingAttributes.begin(), ait)) + 1 < it->instancingAttributes.size()) json += ',';