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..21260ec4c 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,17 @@ 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_ ) ) + { + import_old_attribute_based_on_name( + mesh.vertex_attribute_manager(), mesh.nb_vertices() ); + } 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 +481,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_ ); } } } ); } @@ -510,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< @@ -518,6 +565,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 +615,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 000000000..6c6e7f7a5 Binary files /dev/null and b/tests/data/backward_io/v18_0/v18_0.og_brep differ 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,