From df0af3a65a365bbda9b9bb8bdb433d2397629be2 Mon Sep 17 00:00:00 2001 From: Petru Conduraru Date: Sun, 19 Jul 2026 21:32:33 +0300 Subject: [PATCH] GltfSerializer: opt-in --gltf-extras with GlobalId, type and name Issue #790 asked for IFC metadata in glTF node extras so the glb is self-describing. Off by default to keep file size unchanged, per the maintainer's concern about embedding data; the flag writes GlobalId, entity type and Name on every node, including hierarchy group nodes. Generated with the assistance of an AI coding tool. --- src/ifcgeom/GeometrySerializer.h | 9 ++++++++- src/serializers/GltfSerializer.cpp | 8 +++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/GeometrySerializer.h b/src/ifcgeom/GeometrySerializer.h index 6a3ba7f095..e0cd282994 100644 --- a/src/ifcgeom/GeometrySerializer.h +++ b/src/ifcgeom/GeometrySerializer.h @@ -68,6 +68,13 @@ inline namespace settings { static constexpr bool defaultvalue = false; }; + struct GltfExtras : public SettingBase { + static constexpr const char* const name = "gltf-extras"; + static constexpr const char* const description = "Write the IFC GlobalId, entity type and name of every element into the " + "glTF node extras, so the output is self-describing without a sidecar file. Applicable to GLB output."; + static constexpr bool defaultvalue = false; + }; + struct FloatingPointDigits : public SettingBase { static constexpr const char* const name = "digits"; static constexpr const char* const description = "Sets the precision to be used to format floating-point values, 15 by default. " @@ -97,7 +104,7 @@ inline namespace settings { class SerializerSettings : public SettingsContainer < // @todo should we use tuple_cat here to unify the settings into a single class? - std::tuple> + std::tuple> {}; } diff --git a/src/serializers/GltfSerializer.cpp b/src/serializers/GltfSerializer.cpp index bce50bc11a..c8ee52fe10 100644 --- a/src/serializers/GltfSerializer.cpp +++ b/src/serializers/GltfSerializer.cpp @@ -250,6 +250,9 @@ void GltfSerializer::write(const IfcGeom::TriangulationElement* o) { node_indices_[(*it)->product()] = new_node_index; node_array_.push_back(new_node_index); parent_node["name"] = object_id(*it); + if (settings_.get().get()) { + parent_node["extras"] = { {"GlobalId", (*it)->guid()}, {"IfcType", (*it)->type()}, {"Name", (*it)->name()} }; + } parent_node["children"] = json::array({current_node_index}); json_["nodes"].push_back(parent_node); @@ -290,7 +293,10 @@ void GltfSerializer::write(const IfcGeom::TriangulationElement* o) { } } node["name"] = object_id(o); - + if (settings_.get().get()) { + node["extras"] = { {"GlobalId", o->guid()}, {"IfcType", o->type()}, {"Name", o->name()} }; + } + int current_mesh_index; // See if this mesh has already been processed