From c190dacd12ec62fe36186c5665d771dd9cc2fac2 Mon Sep 17 00:00:00 2001 From: Jerry Laruba Festus Date: Wed, 4 Dec 2024 07:38:00 +0300 Subject: [PATCH] Resolved Issues With Corrupted STL Files When Exporting to stdout (#5470) --------- Co-authored-by: Marius Kintel --- src/io/export_stl.cc | 49 +++++++++++------- tests/CMakeLists.txt | 5 ++ .../binstlexport/stl-export-expected.stl | Bin 0 -> 484 bytes 3 files changed, 35 insertions(+), 19 deletions(-) create mode 100644 tests/regression/binstlexport/stl-export-expected.stl diff --git a/src/io/export_stl.cc b/src/io/export_stl.cc index 9db8e72e7f..1d99ac3986 100644 --- a/src/io/export_stl.cc +++ b/src/io/export_stl.cc @@ -293,29 +293,40 @@ void export_stl(const std::shared_ptr& geom, std::ostream& outpu { // FIXME: In lazy union mode, should we export multiple solids? if (binary) { + std::ostringstream buffer; // Using a memory buffer char header[80] = "OpenSCAD Model\n"; - output.write(header, sizeof(header)); - char tmp_triangle_count[4] = {0, 0, 0, 0}; // We must fill this in below. - output.write(tmp_triangle_count, 4); - } else { - setlocale(LC_NUMERIC, "C"); // Ensure radix is . (not ,) in output - output << "solid OpenSCAD_Model\n"; - } + buffer.write(header, sizeof(header)); + + // Placeholder for triangle count + uint32_t triangle_count = 0; + char tmp_triangle_count[4] = {0, 0, 0, 0}; + buffer.write(tmp_triangle_count, 4); + + // Writing triangles and counting them + triangle_count = append_stl(geom, buffer, binary); + + if (triangle_count > 4294967295) { + LOG(message_group::Export_Error, "Triangle count exceeded 4294967295, so the STL file is not valid"); + } - uint64_t triangle_count = append_stl(geom, output, binary); + // Updating the triangle count in the buffer + char triangle_count_bytes[4] = { + static_cast(triangle_count & 0xff), + static_cast((triangle_count >> 8) & 0xff), + static_cast((triangle_count >> 16) & 0xff), + static_cast((triangle_count >> 24) & 0xff)}; + buffer.seekp(80, std::ios_base::beg); + buffer.write(triangle_count_bytes, 4); + + // Flushing the buffer to the output stream + output << buffer.str(); - if (binary) { - // Fill in triangle count. - output.seekp(80, std::ios_base::beg); - output.put(triangle_count & 0xff); - output.put((triangle_count >> 8) & 0xff); - output.put((triangle_count >> 16) & 0xff); - output.put((triangle_count >> 24) & 0xff); - if (triangle_count > 4294967295) { - LOG(message_group::Export_Error, "Triangle count exceeded 4294967295, so the stl file is not valid"); - } } else { + // ASCII mode: Write directly to the output stream + setlocale(LC_NUMERIC, "C"); // Ensure radix is . (not ,) in output + output << "solid OpenSCAD_Model\n"; + uint64_t triangle_count = append_stl(geom, output, binary); output << "endsolid OpenSCAD_Model\n"; - setlocale(LC_NUMERIC, ""); // Set default locale + setlocale(LC_NUMERIC, ""); // Restore default locale } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e096273219..2f05a85415 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1137,9 +1137,14 @@ ${TEST_SCAD_DIR}/misc/rotate_extrude-hole.scad # Export tests (compare actually exported files) add_cmdline_test(stlexport EXPERIMENTAL OPENSCAD SUFFIX stl FILES ${EXPORT_STL_TEST_FILES} ARGS --enable=predictible-output --render) +add_cmdline_test(stlexport-stdout EXPERIMENTAL OPENSCAD SUFFIX stl FILES ${EXPORT_STL_TEST_FILES} STDIO EXPECTEDDIR stlexport ARGS --enable=predictible-output --render --export-format asciistl) if (ENABLE_MANIFOLD) add_cmdline_test(manifold-stlexport EXPERIMENTAL OPENSCAD SUFFIX stl FILES ${EXPORT_STL_TEST_FILES} EXPECTEDDIR stlexport ARGS --enable=predictible-output --backend=manifold --render) endif() + +add_cmdline_test(binstlexport EXPERIMENTAL OPENSCAD SUFFIX stl FILES ${EXPORT_STL_TEST_FILES} ARGS --enable=predictible-output --render --export-format binstl) +add_cmdline_test(binstlexport-stdout EXPERIMENTAL OPENSCAD SUFFIX stl FILES ${EXPORT_STL_TEST_FILES} STDIO EXPECTEDDIR binstlexport ARGS --enable=predictible-output --render --export-format binstl) + add_cmdline_test(objexport EXPERIMENTAL OPENSCAD SUFFIX obj FILES ${EXPORT_OBJ_TEST_FILES} ARGS --render --enable=predictible-output) if (LIB3MF_FOUND) add_cmdline_test(3mfexport EXPERIMENTAL OPENSCAD SUFFIX 3mf FILES ${EXPORT_3MF_TEST_FILES} ARGS --enable=predictible-output) diff --git a/tests/regression/binstlexport/stl-export-expected.stl b/tests/regression/binstlexport/stl-export-expected.stl new file mode 100644 index 0000000000000000000000000000000000000000..444f314b559f2a9a6965b70170ada6fa1d1d15c8 GIT binary patch literal 484 zcmeY-NX-j&c63qj%}+_q;bNc^Z~zVXzDIdK2zv$IvSVOqH~=y8fCGdE@nLL`h=U`F zj(wOqAo?IAOgGdHd+c_=%mvX64iNj0bYQUqrV6A327o&3q5c5s00Efo5FUgC=>!3g wpOAC_eGURJ9muL6GH{=R>;U-#Y6naftlI%%F0yW@9Z;XcRD(hhSrxKw0IOnKy#N3J literal 0 HcmV?d00001