From 8aa91fbda2cad6ba0aef051078290934fd7b218f Mon Sep 17 00:00:00 2001 From: BenPinet Date: Tue, 25 Aug 2026 12:12:25 +0200 Subject: [PATCH 1/2] feat(VertexIdentifier): add a unique_vertex_attribute_id --- .../model/mixin/core/vertex_identifier.hpp | 2 + .../model/helpers/convert_model_meshes.cpp | 18 +++- .../model/mixin/core/vertex_identifier.cpp | 84 ++++++++++++++---- tests/data/backward_io/v18_0/v18_0.og_brep | Bin 0 -> 26287 bytes tests/model/test-brep.cpp | 41 +++++++-- 5 files changed, 119 insertions(+), 26 deletions(-) create mode 100644 tests/data/backward_io/v18_0/v18_0.og_brep diff --git a/include/geode/model/mixin/core/vertex_identifier.hpp b/include/geode/model/mixin/core/vertex_identifier.hpp index ee6e2cc99..4a34a330f 100644 --- a/include/geode/model/mixin/core/vertex_identifier.hpp +++ b/include/geode/model/mixin/core/vertex_identifier.hpp @@ -134,6 +134,8 @@ namespace geode */ void save_unique_vertices( std::string_view directory ) const; + [[nodiscard]] const uuid& unique_vertex_attribute_id() const; + public: /*! * Add a component in the VertexIdentifier diff --git a/src/geode/model/helpers/convert_model_meshes.cpp b/src/geode/model/helpers/convert_model_meshes.cpp index 93113dae1..b081d7a10 100644 --- a/src/geode/model/helpers/convert_model_meshes.cpp +++ b/src/geode/model/helpers/convert_model_meshes.cpp @@ -84,6 +84,8 @@ namespace } const auto unique_vertices = save_unique_vertices( model, mesh, surface.component_id() ); + const auto& unique_vertex_attribute_id = + model.unique_vertex_attribute_id(); if( mesh_type == geode::TriangulatedSurface< Model::dim >::type_name_static() ) { @@ -94,15 +96,19 @@ namespace geode::OpenGeodeException::TYPE::internal, "[do_convert_surface] Cannot convert SurfaceMesh " "to TriangulatedSurface" ); + tri_surface.value()->vertex_attribute_manager().delete_attribute( + unique_vertex_attribute_id ); builder.update_surface_mesh( surface, std::move( tri_surface ).value() ); } else if( mesh_type == geode::PolygonalSurface< Model::dim >::type_name_static() ) { - builder.update_surface_mesh( surface, - std::move( geode::convert_surface_mesh_into_polygonal_surface( - mesh ) ) ); + auto poly_surface = + geode::convert_surface_mesh_into_polygonal_surface( mesh ); + poly_surface->vertex_attribute_manager().delete_attribute( + unique_vertex_attribute_id ); + builder.update_surface_mesh( surface, std::move( poly_surface ) ); } set_unique_vertices( builder, unique_vertices, surface.component_id() ); } @@ -149,6 +155,8 @@ namespace } const auto unique_vertices = save_unique_vertices( model, mesh, block.component_id() ); + const auto& unique_vertex_attribute_id = + model.unique_vertex_attribute_id(); if( mesh_type == geode::TetrahedralSolid3D::type_name_static() ) { auto tet_solid = @@ -158,6 +166,8 @@ namespace geode::OpenGeodeException::TYPE::internal, "[do_convert_block] Cannot convert " "SolidMesh to TetrahedralSolid" ); + tet_solid.value()->vertex_attribute_manager().delete_attribute( + unique_vertex_attribute_id ); builder.update_block_mesh( block, std::move( tet_solid ).value() ); } else if( mesh_type == geode::HybridSolid3D::type_name_static() ) @@ -168,6 +178,8 @@ namespace hybrid_solid.has_value(), nullptr, geode::OpenGeodeException::TYPE::internal, "[do_convert_block] Cannot convert SolidMesh to HybridSolid" ); + hybrid_solid.value()->vertex_attribute_manager().delete_attribute( + unique_vertex_attribute_id ); builder.update_block_mesh( block, std::move( hybrid_solid ).value() ); } diff --git a/src/geode/model/mixin/core/vertex_identifier.cpp b/src/geode/model/mixin/core/vertex_identifier.cpp index 7f65a8c95..b9193e3ea 100644 --- a/src/geode/model/mixin/core/vertex_identifier.cpp +++ b/src/geode/model/mixin/core/vertex_identifier.cpp @@ -186,6 +186,11 @@ namespace geode return false; } + const uuid& unique_vertex_attribute_id() const + { + return unique_vertex_id_; + } + template < typename MeshComponent > void register_component( const MeshComponent& component ) { @@ -193,20 +198,19 @@ namespace geode attribute_properties.assignable = false; attribute_properties.interpolable = false; attribute_properties.transferable = false; - AttributeValues< index_t > unqiue_vertex_attribute_values; - unqiue_vertex_attribute_values.default_value = NO_ID; - unqiue_vertex_attribute_values.no_value = NO_ID; + AttributeValues< index_t > unique_vertex_attribute_values; + unique_vertex_attribute_values.default_value = NO_ID; + unique_vertex_attribute_values.no_value = NO_ID; const auto& mesh = component.mesh(); - const auto unique_vertices_attribute_id = - mesh.vertex_attribute_manager() - .template create_attribute< VariableAttribute, index_t >( - UNIQUE_VERTICES_NAME, unqiue_vertex_attribute_values, - attribute_properties ); + mesh.vertex_attribute_manager() + .template create_attribute< VariableAttribute, index_t >( + UNIQUE_VERTICES_NAME, unique_vertex_id_, + unique_vertex_attribute_values, attribute_properties ); const auto [_, inserted] = vertex2unique_vertex_.emplace( component.id(), mesh.vertex_attribute_manager() .template find_attribute< VariableAttribute, index_t >( - unique_vertices_attribute_id ) ); + unique_vertex_id_ ) ); OpenGeodeModelException::check_exception( inserted, component.component_id(), OpenGeodeException::TYPE::data, "[VertexIdentifier::register_component] Component ", @@ -217,19 +221,51 @@ namespace geode void load_component( const MeshComponent& component ) { const auto& mesh = component.mesh(); - const auto unique_vertices_ids = - mesh.vertex_attribute_manager().attribute_ids_matching_name( - UNIQUE_VERTICES_NAME ); - OpenGeodeModelException::check_exception( - unique_vertices_ids.has_value(), nullptr, - OpenGeodeException::TYPE::data, - "[VertexIdentifier::load_component] Unique vertices " - "attribute not found." ); + if( !mesh.vertex_attribute_manager().attribute_exists( + unique_vertex_id_ ) ) + { + // For old files before v18 of OpenGeode the unique vertices + // attribute was not identified with an id but with a name + // This changes the id of the attribute to unique_vertex_id_ + const auto unique_vertices_ids = + mesh.vertex_attribute_manager().attribute_ids_matching_name( + UNIQUE_VERTICES_NAME ); + OpenGeodeModelException::check_exception( + unique_vertices_ids.has_value(), nullptr, + OpenGeodeException::TYPE::data, + "[VertexIdentifier::load_component] Unique vertices " + "attribute not found." ); + OpenGeodeModelException::check_exception( + unique_vertices_ids.value().size() == 1, nullptr, + OpenGeodeException::TYPE::data, + "[VertexIdentifier::load_component] Unique vertices " + "attribute is not unique." ); + const auto old_attribute = + mesh.vertex_attribute_manager() + .template find_attribute< VariableAttribute, index_t >( + unique_vertices_ids.value().front() ); + mesh.vertex_attribute_manager() + .template create_attribute< VariableAttribute, index_t >( + UNIQUE_VERTICES_NAME, unique_vertex_id_, + old_attribute->default_values(), + old_attribute->properties() ); + const auto new_attribute = + mesh.vertex_attribute_manager() + .template find_attribute< VariableAttribute, index_t >( + unique_vertex_id_ ); + for( const auto vertex : Range{ mesh.nb_vertices() } ) + { + new_attribute->set_value( + vertex, old_attribute->value( vertex ) ); + } + mesh.vertex_attribute_manager().delete_attribute( + unique_vertices_ids.value().front() ); + } const auto [_, inserted] = vertex2unique_vertex_.emplace( component.id(), mesh.vertex_attribute_manager() .template find_attribute< VariableAttribute, index_t >( - unique_vertices_ids.value().front() ) ); + unique_vertex_id_ ) ); OpenGeodeModelException::check_exception( inserted, component.component_id(), OpenGeodeException::TYPE::data, "[VertexIdentifier::load_component] Component ", @@ -479,6 +515,12 @@ namespace geode archive.object( impl.unique_vertices_ ); archive.ext( impl.component_vertices_, bitsery::ext::StdSmartPtr{} ); + }, + []( Archive& archive, Impl& impl ) { + archive.object( impl.unique_vertices_ ); + archive.ext( impl.component_vertices_, + bitsery::ext::StdSmartPtr{} ); + archive.object( impl.unique_vertex_id_ ); } } } ); } @@ -518,6 +560,7 @@ namespace geode absl::flat_hash_map< uuid, std::shared_ptr< VariableAttribute< index_t > > > vertex2unique_vertex_; + geode::uuid unique_vertex_id_; }; VertexIdentifier::VertexIdentifier() = default; @@ -567,6 +610,11 @@ namespace geode unique_vertex_id, component_id ); } + const uuid& VertexIdentifier::unique_vertex_attribute_id() const + { + return impl_->unique_vertex_attribute_id(); + } + template < typename MeshComponent > void VertexIdentifier::load_mesh_component( const MeshComponent& component, BuilderKey /*key*/ ) diff --git a/tests/data/backward_io/v18_0/v18_0.og_brep b/tests/data/backward_io/v18_0/v18_0.og_brep new file mode 100644 index 0000000000000000000000000000000000000000..6c6e7f7a570b81c29ab20efcbdd2d2e7cf22976d GIT binary patch literal 26287 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 XuoW}2xz-)!80EN+RXog|IvoE8-Pm;( literal 0 HcmV?d00001 diff --git a/tests/model/test-brep.cpp b/tests/model/test-brep.cpp index 967eb670c..c6cf815b0 100644 --- a/tests/model/test-brep.cpp +++ b/tests/model/test-brep.cpp @@ -1624,6 +1624,42 @@ void test_backward_io() "[Backward_IO] Incorrect brep unique_vertex_id." ); } test_registry( brep_v17, 4, 6, 9, 5, 1, 5, 2, 2, 2, 1, 3 ); + auto brep_v18_0 = geode::load_brep( + absl::StrCat( geode::DATA_PATH, "backward_io/v18_0/v18_0.og_brep" ) ); + geode::BRepBuilder brep_builder_v18{ brep_v18_0 }; + for( const auto& block : brep_v18_0.blocks() ) + { + geode::OpenGeodeModelException::test( block.id() == block.mesh().id(), + "[Backward_IO] Brep block should have the same uuid as its mesh." ); + } + for( const auto& surface : brep_v18_0.surfaces() ) + { + geode::OpenGeodeModelException::test( + surface.id() == surface.mesh().id(), + "[Backward_IO] Brep surface should have the same uuid as its " + "mesh." ); + } + for( const auto& line : brep_v18_0.lines() ) + { + geode::OpenGeodeModelException::test( line.id() == line.mesh().id(), + "[Backward_IO] Brep line should have the same uuid as its mesh." ); + } + for( const auto& corner : brep_v18_0.corners() ) + { + geode::OpenGeodeModelException::test( corner.id() == corner.mesh().id(), + "[Backward_IO] Brep corner should have the same uuid as its " + "mesh." ); + } + for( const auto& surface : brep_v18_0.surfaces() ) + { + auto vertex_index = + brep_builder_v18.surface_mesh_builder( surface )->create_vertex(); + geode::OpenGeodeModelException::test( + brep_v18_0.unique_vertex( { surface.component_id(), vertex_index } ) + == geode::NO_ID, + "[Backward_IO] Incorrect brep unique_vertex_id." ); + } + test_registry( brep_v18_0, 4, 6, 9, 5, 1, 5, 2, 2, 2, 1, 3 ); } void test_components_filter() @@ -1717,19 +1753,14 @@ void test() test_block_collection_ranges( model, block_uuid, block_collection_uuid ); test_clone( model ); test_steal_mesh( model ); - DEBUG( "io" ); const auto file_io = absl::StrCat( "test.", model.native_extension() ); geode::save_brep( model, file_io ); - DEBUG( "start load" ); auto model2 = geode::load_brep( file_io ); geode::BRepBuilder model2_builder{ model2 }; for( const auto& surface : model2.surfaces() ) { auto vertex_index = model2_builder.surface_mesh_builder( surface )->create_vertex(); - DEBUG( vertex_index ); - DEBUG( - model2.unique_vertex( { surface.component_id(), vertex_index } ) ); geode::OpenGeodeModelException::test( model2.unique_vertex( { surface.component_id(), vertex_index } ) == geode::NO_ID, From a91ec663a8b51905bd36bbd4ee85e44de2d8554a Mon Sep 17 00:00:00 2001 From: BenPinet Date: Wed, 26 Aug 2026 09:50:08 +0200 Subject: [PATCH 2/2] comments --- .../model/mixin/core/vertex_identifier.cpp | 77 ++++++++++--------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/src/geode/model/mixin/core/vertex_identifier.cpp b/src/geode/model/mixin/core/vertex_identifier.cpp index b9193e3ea..21260ec4c 100644 --- a/src/geode/model/mixin/core/vertex_identifier.cpp +++ b/src/geode/model/mixin/core/vertex_identifier.cpp @@ -224,42 +224,8 @@ namespace geode if( !mesh.vertex_attribute_manager().attribute_exists( unique_vertex_id_ ) ) { - // For old files before v18 of OpenGeode the unique vertices - // attribute was not identified with an id but with a name - // This changes the id of the attribute to unique_vertex_id_ - const auto unique_vertices_ids = - mesh.vertex_attribute_manager().attribute_ids_matching_name( - UNIQUE_VERTICES_NAME ); - OpenGeodeModelException::check_exception( - unique_vertices_ids.has_value(), nullptr, - OpenGeodeException::TYPE::data, - "[VertexIdentifier::load_component] Unique vertices " - "attribute not found." ); - OpenGeodeModelException::check_exception( - unique_vertices_ids.value().size() == 1, nullptr, - OpenGeodeException::TYPE::data, - "[VertexIdentifier::load_component] Unique vertices " - "attribute is not unique." ); - const auto old_attribute = - mesh.vertex_attribute_manager() - .template find_attribute< VariableAttribute, index_t >( - unique_vertices_ids.value().front() ); - mesh.vertex_attribute_manager() - .template create_attribute< VariableAttribute, index_t >( - UNIQUE_VERTICES_NAME, unique_vertex_id_, - old_attribute->default_values(), - old_attribute->properties() ); - const auto new_attribute = - mesh.vertex_attribute_manager() - .template find_attribute< VariableAttribute, index_t >( - unique_vertex_id_ ); - for( const auto vertex : Range{ mesh.nb_vertices() } ) - { - new_attribute->set_value( - vertex, old_attribute->value( vertex ) ); - } - mesh.vertex_attribute_manager().delete_attribute( - unique_vertices_ids.value().front() ); + import_old_attribute_based_on_name( + mesh.vertex_attribute_manager(), mesh.nb_vertices() ); } const auto [_, inserted] = vertex2unique_vertex_.emplace( component.id(), @@ -552,6 +518,45 @@ namespace geode } ); } + void import_old_attribute_based_on_name( + AttributeManager& vertex_attribute_manager, + const index_t nb_vertices ) + { + const auto unique_vertices_ids = + vertex_attribute_manager.attribute_ids_matching_name( + UNIQUE_VERTICES_NAME ); + OpenGeodeModelException::check_exception( + unique_vertices_ids.has_value(), nullptr, + OpenGeodeException::TYPE::data, + "[VertexIdentifier::load_component] Unique vertices " + "attribute not found." ); + OpenGeodeModelException::check_exception( + unique_vertices_ids.value().size() == 1, nullptr, + OpenGeodeException::TYPE::data, + "[VertexIdentifier::load_component] Unique vertices " + "attribute is not unique." ); + const auto old_attribute = + vertex_attribute_manager + .template find_attribute< VariableAttribute, index_t >( + unique_vertices_ids.value().front() ); + vertex_attribute_manager + .template create_attribute< VariableAttribute, index_t >( + UNIQUE_VERTICES_NAME, unique_vertex_id_, + old_attribute->default_values(), + old_attribute->properties() ); + const auto new_attribute = + vertex_attribute_manager + .template find_attribute< VariableAttribute, index_t >( + unique_vertex_id_ ); + for( const auto vertex : Range{ nb_vertices } ) + { + new_attribute->set_value( + vertex, old_attribute->value( vertex ) ); + } + vertex_attribute_manager.delete_attribute( + unique_vertices_ids.value().front() ); + } + private: OpenGeodeVertexSet unique_vertices_; std::shared_ptr<