From 5605088aadf378788ac94657556a662b5493558b Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Sat, 12 Dec 2020 12:06:15 +0100 Subject: [PATCH] Follow-up on aaaa85c1f8a06d222ccbb745e67bdc56d65b90ed Fix of #5007 - "Reload from disk" causes objects converted to inches to revert to mm 1) Storing and reloading the "source_in_inches" source flag from AMF and 3MF 2) When converting objects with mixed "inches" volumes, do the right thing and do not convert those that do not need conversion. --- src/libslic3r/Format/3mf.cpp | 113 +++++++++++++++++++---------------- src/libslic3r/Format/AMF.cpp | 5 ++ src/libslic3r/Model.cpp | 8 ++- 3 files changed, 70 insertions(+), 56 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index a4fd228fc..dde185fe5 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -56,58 +56,59 @@ const std::string SLA_SUPPORT_POINTS_FILE = "Metadata/Slic3r_PE_sla_support_poin const std::string SLA_DRAIN_HOLES_FILE = "Metadata/Slic3r_PE_sla_drain_holes.txt"; const std::string CUSTOM_GCODE_PER_PRINT_Z_FILE = "Metadata/Prusa_Slicer_custom_gcode_per_print_z.xml"; -const char* MODEL_TAG = "model"; -const char* RESOURCES_TAG = "resources"; -const char* OBJECT_TAG = "object"; -const char* MESH_TAG = "mesh"; -const char* VERTICES_TAG = "vertices"; -const char* VERTEX_TAG = "vertex"; -const char* TRIANGLES_TAG = "triangles"; -const char* TRIANGLE_TAG = "triangle"; -const char* COMPONENTS_TAG = "components"; -const char* COMPONENT_TAG = "component"; -const char* BUILD_TAG = "build"; -const char* ITEM_TAG = "item"; -const char* METADATA_TAG = "metadata"; +static constexpr char* MODEL_TAG = "model"; +static constexpr char* RESOURCES_TAG = "resources"; +static constexpr char* OBJECT_TAG = "object"; +static constexpr char* MESH_TAG = "mesh"; +static constexpr char* VERTICES_TAG = "vertices"; +static constexpr char* VERTEX_TAG = "vertex"; +static constexpr char* TRIANGLES_TAG = "triangles"; +static constexpr char* TRIANGLE_TAG = "triangle"; +static constexpr char* COMPONENTS_TAG = "components"; +static constexpr char* COMPONENT_TAG = "component"; +static constexpr char* BUILD_TAG = "build"; +static constexpr char* ITEM_TAG = "item"; +static constexpr char* METADATA_TAG = "metadata"; -const char* CONFIG_TAG = "config"; -const char* VOLUME_TAG = "volume"; +static constexpr char* CONFIG_TAG = "config"; +static constexpr char* VOLUME_TAG = "volume"; -const char* UNIT_ATTR = "unit"; -const char* NAME_ATTR = "name"; -const char* TYPE_ATTR = "type"; -const char* ID_ATTR = "id"; -const char* X_ATTR = "x"; -const char* Y_ATTR = "y"; -const char* Z_ATTR = "z"; -const char* V1_ATTR = "v1"; -const char* V2_ATTR = "v2"; -const char* V3_ATTR = "v3"; -const char* OBJECTID_ATTR = "objectid"; -const char* TRANSFORM_ATTR = "transform"; -const char* PRINTABLE_ATTR = "printable"; -const char* INSTANCESCOUNT_ATTR = "instances_count"; -const char* CUSTOM_SUPPORTS_ATTR = "slic3rpe:custom_supports"; -const char* CUSTOM_SEAM_ATTR = "slic3rpe:custom_seam"; +static constexpr char* UNIT_ATTR = "unit"; +static constexpr char* NAME_ATTR = "name"; +static constexpr char* TYPE_ATTR = "type"; +static constexpr char* ID_ATTR = "id"; +static constexpr char* X_ATTR = "x"; +static constexpr char* Y_ATTR = "y"; +static constexpr char* Z_ATTR = "z"; +static constexpr char* V1_ATTR = "v1"; +static constexpr char* V2_ATTR = "v2"; +static constexpr char* V3_ATTR = "v3"; +static constexpr char* OBJECTID_ATTR = "objectid"; +static constexpr char* TRANSFORM_ATTR = "transform"; +static constexpr char* PRINTABLE_ATTR = "printable"; +static constexpr char* INSTANCESCOUNT_ATTR = "instances_count"; +static constexpr char* CUSTOM_SUPPORTS_ATTR = "slic3rpe:custom_supports"; +static constexpr char* CUSTOM_SEAM_ATTR = "slic3rpe:custom_seam"; -const char* KEY_ATTR = "key"; -const char* VALUE_ATTR = "value"; -const char* FIRST_TRIANGLE_ID_ATTR = "firstid"; -const char* LAST_TRIANGLE_ID_ATTR = "lastid"; +static constexpr char* KEY_ATTR = "key"; +static constexpr char* VALUE_ATTR = "value"; +static constexpr char* FIRST_TRIANGLE_ID_ATTR = "firstid"; +static constexpr char* LAST_TRIANGLE_ID_ATTR = "lastid"; -const char* OBJECT_TYPE = "object"; -const char* VOLUME_TYPE = "volume"; +static constexpr char* OBJECT_TYPE = "object"; +static constexpr char* VOLUME_TYPE = "volume"; -const char* NAME_KEY = "name"; -const char* MODIFIER_KEY = "modifier"; -const char* VOLUME_TYPE_KEY = "volume_type"; -const char* MATRIX_KEY = "matrix"; -const char* SOURCE_FILE_KEY = "source_file"; -const char* SOURCE_OBJECT_ID_KEY = "source_object_id"; -const char* SOURCE_VOLUME_ID_KEY = "source_volume_id"; -const char* SOURCE_OFFSET_X_KEY = "source_offset_x"; -const char* SOURCE_OFFSET_Y_KEY = "source_offset_y"; -const char* SOURCE_OFFSET_Z_KEY = "source_offset_z"; +static constexpr char* NAME_KEY = "name"; +static constexpr char* MODIFIER_KEY = "modifier"; +static constexpr char* VOLUME_TYPE_KEY = "volume_type"; +static constexpr char* MATRIX_KEY = "matrix"; +static constexpr char* SOURCE_FILE_KEY = "source_file"; +static constexpr char* SOURCE_OBJECT_ID_KEY = "source_object_id"; +static constexpr char* SOURCE_VOLUME_ID_KEY = "source_volume_id"; +static constexpr char* SOURCE_OFFSET_X_KEY = "source_offset_x"; +static constexpr char* SOURCE_OFFSET_Y_KEY = "source_offset_y"; +static constexpr char* SOURCE_OFFSET_Z_KEY = "source_offset_z"; +static constexpr char* SOURCE_IN_INCHES = "source_in_inches"; const unsigned int VALID_OBJECT_TYPES_COUNT = 1; const char* VALID_OBJECT_TYPES[] = @@ -1926,6 +1927,8 @@ namespace Slic3r { volume->source.mesh_offset(1) = ::atof(metadata.value.c_str()); else if (metadata.key == SOURCE_OFFSET_Z_KEY) volume->source.mesh_offset(2) = ::atof(metadata.value.c_str()); + else if (metadata.key == SOURCE_IN_INCHES) + volume->source.is_converted_from_inches = metadata.value.c_str() == "1"; else volume->config.set_deserialize(metadata.key, metadata.value); } @@ -2752,12 +2755,16 @@ namespace Slic3r { if (!volume->source.input_file.empty()) { std::string input_file = xml_escape(m_fullpath_sources ? volume->source.input_file : boost::filesystem::path(volume->source.input_file).filename().string()); - stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_FILE_KEY << "\" " << VALUE_ATTR << "=\"" << input_file << "\"/>\n"; - stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_OBJECT_ID_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.object_idx << "\"/>\n"; - stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_VOLUME_ID_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.volume_idx << "\"/>\n"; - stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_OFFSET_X_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(0) << "\"/>\n"; - stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_OFFSET_Y_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(1) << "\"/>\n"; - stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_OFFSET_Z_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(2) << "\"/>\n"; + std::string prefix = std::string(" <") + METADATA_TAG + " " + TYPE_ATTR + "=\"" + VOLUME_TYPE + "\" " + KEY_ATTR + "=\""; + stream << prefix << SOURCE_FILE_KEY << "\" " << VALUE_ATTR << "=\"" << input_file << "\"/>\n"; + stream << prefix << SOURCE_OBJECT_ID_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.object_idx << "\"/>\n"; + stream << prefix << SOURCE_VOLUME_ID_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.volume_idx << "\"/>\n"; + stream << prefix << SOURCE_OFFSET_X_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(0) << "\"/>\n"; + stream << prefix << SOURCE_OFFSET_Y_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(1) << "\"/>\n"; + stream << prefix << SOURCE_OFFSET_Z_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(2) << "\"/>\n"; + stream << prefix << SOURCE_OFFSET_Z_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(2) << "\"/>\n"; + if (volume->source.is_converted_from_inches) + stream << prefix << SOURCE_IN_INCHES << "\" " << VALUE_ATTR << "=\"1\"/>\n"; } // stores volume's config data diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index a2117d63b..a183aeb46 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -778,6 +778,9 @@ void AMFParserContext::endElement(const char * /* name */) else if (strcmp(opt_key, "source_offset_z") == 0) { m_volume->source.mesh_offset(2) = ::atof(m_value[1].c_str()); } + else if (strcmp(opt_key, "source_in_inches") == 0) { + m_volume->source.is_converted_from_inches = m_value[1] == "1"; + } } } else if (m_path.size() == 3) { if (m_path[1] == NODE_TYPE_MATERIAL) { @@ -1204,6 +1207,8 @@ bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config, stream << " " << volume->source.mesh_offset(0) << "\n"; stream << " " << volume->source.mesh_offset(1) << "\n"; stream << " " << volume->source.mesh_offset(2) << "\n"; + if (volume->source.is_converted_from_inches) + stream << " 1\n"; } stream << std::setprecision(std::numeric_limits::max_digits10); const indexed_triangle_set &its = volume->mesh().its; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index b492fa01d..d7682d276 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1060,9 +1060,11 @@ void ModelObject::convert_units(ModelObjectPtrs& new_objects, bool from_imperial vol->source.object_idx = (int)new_objects.size(); vol->source.volume_idx = vol_idx; - // Perform conversion - if (volume_idxs.empty() || - std::find(volume_idxs.begin(), volume_idxs.end(), vol_idx) != volume_idxs.end()) { + // Perform conversion only if the target "imperial" state is different from the current one. + // This check supports conversion of "mixed" set of volumes, each with different "imperial" state. + if (vol->source.is_converted_from_inches != from_imperial && + (volume_idxs.empty() || + std::find(volume_idxs.begin(), volume_idxs.end(), vol_idx) != volume_idxs.end())) { vol->scale_geometry_after_creation(versor); vol->set_offset(versor.cwiseProduct(volume->get_offset())); vol->source.is_converted_from_inches = from_imperial;