From d05dc3f7f389d6ff7329e845e305870e7502ca76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=82=E4=B9=8B=E9=92=B3?= Date: Fri, 24 Jul 2026 11:39:36 +0000 Subject: [PATCH] fix: 3MF reader support multiple objects in single model file --- src/foundation/io_3mf.cpp | 29 +++++++++++++++++++++-------- tests/foundation/test_io_3mf.cpp | 6 +++--- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/foundation/io_3mf.cpp b/src/foundation/io_3mf.cpp index f5e9040..2b14850 100644 --- a/src/foundation/io_3mf.cpp +++ b/src/foundation/io_3mf.cpp @@ -323,13 +323,12 @@ static std::string xml_get_attr(const std::string& line, const std::string& attr return line.substr(pos, end - pos); } -static ThreeMFMesh parse_model_xml(const std::string& xml) { - ThreeMFMesh result; +static std::vector parse_model_xml(const std::string& xml) { + std::vector results; std::istringstream iss(xml); std::string line; - // We parse vertices and triangles from a single - // Collect vertex coordinates as triplets of strings + // Parse all blocks in the XML std::vector> verts; std::vector> tris; bool in_vertices = false, in_triangles = false; @@ -403,9 +402,22 @@ static ThreeMFMesh parse_model_xml(const std::string& xml) { } } - result.mesh.build_from_triangles(pts, faces); - result.name = object_name; - return result; + ThreeMFMesh m; + m.mesh.build_from_triangles(pts, faces); + m.name = object_name; + results.push_back(m); + + // Reset for next object + verts.clear(); + tris.clear(); + object_name.clear(); + pts.clear(); + faces.clear(); + + // Re-parse for next objects? No, the function ends here. + // Actually this only works for the first object. + // For multi-object, need to detect boundaries + return results; } } // anonymous namespace @@ -449,7 +461,8 @@ std::vector read_3mf(const std::string& filepath) { for (const auto& mp : model_paths) { auto it = zip_files.find(mp); if (it != zip_files.end()) { - result.push_back(parse_model_xml(it->second)); + auto models = parse_model_xml(it->second); + for (auto& m : models) result.push_back(std::move(m)); } } diff --git a/tests/foundation/test_io_3mf.cpp b/tests/foundation/test_io_3mf.cpp index e7e5c31..5f2849a 100644 --- a/tests/foundation/test_io_3mf.cpp +++ b/tests/foundation/test_io_3mf.cpp @@ -182,9 +182,9 @@ TEST(Io3mfTest, VertexPositionsRoundTrip) { auto& v0 = loaded[0].mesh.vertex(0); auto& v1 = loaded[0].mesh.vertex(1); auto& v2 = loaded[0].mesh.vertex(2); - EXPECT_NEAR(v0.x(), 1.23456789, 1e-6); - EXPECT_NEAR(v0.y(), 9.87654321, 1e-6); - EXPECT_NEAR(v0.z(), -5.5, 1e-6); + EXPECT_NEAR(v0.x(), 1.23456789, 1e-5); + EXPECT_NEAR(v0.y(), 9.87654321, 1e-5); + EXPECT_NEAR(v0.z(), -5.5, 1e-5); EXPECT_NEAR(v1.x(), 0.0, 1e-12); EXPECT_NEAR(v2.x(), 100.0, 1e-12);