Merge branch 'master' into lm_tm_hollowing
This commit is contained in:
@@ -34,8 +34,12 @@ namespace pt = boost::property_tree;
|
||||
// VERSION NUMBERS
|
||||
// 0 : .3mf, files saved by older slic3r or other applications. No version definition in them.
|
||||
// 1 : Introduction of 3mf versioning. No other change in data saved into 3mf files.
|
||||
// 2 : Meshes saved in their local system; Volumes' matrices and source data added to Metadata/Slic3r_PE_model.config file.
|
||||
const unsigned int VERSION_3MF = 2;
|
||||
// 2 : Volumes' matrices and source data added to Metadata/Slic3r_PE_model.config file, meshes transformed back to their coordinate system on loading.
|
||||
// WARNING !! -> the version number has been rolled back to 1
|
||||
// the next change should use 3
|
||||
const unsigned int VERSION_3MF = 1;
|
||||
// Allow loading version 2 file as well.
|
||||
const unsigned int VERSION_3MF_COMPATIBLE = 2;
|
||||
const char* SLIC3RPE_3MF_VERSION = "slic3rpe:Version3mf"; // definition of the metadata name saved into .model file
|
||||
|
||||
const std::string MODEL_FOLDER = "3D/";
|
||||
@@ -52,7 +56,7 @@ const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights
|
||||
const std::string LAYER_CONFIG_RANGES_FILE = "Metadata/Prusa_Slicer_layer_config_ranges.xml";
|
||||
const std::string SLA_SUPPORT_POINTS_FILE = "Metadata/Slic3r_PE_sla_support_points.txt";
|
||||
const std::string SLA_DRAIN_HOLES_FILE = "Metadata/Slic3r_PE_sla_drain_holes.txt";
|
||||
const std::string CUSTOM_GCODE_PER_HEIGHT_FILE = "Metadata/Prusa_Slicer_custom_gcode_per_height.xml";
|
||||
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";
|
||||
@@ -422,7 +426,7 @@ namespace Slic3r {
|
||||
void _extract_sla_support_points_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
void _extract_sla_drain_holes_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
|
||||
void _extract_custom_gcode_per_height_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
void _extract_custom_gcode_per_print_z_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
|
||||
void _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config, const std::string& archive_filename);
|
||||
bool _extract_model_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, Model& model);
|
||||
@@ -638,10 +642,10 @@ namespace Slic3r {
|
||||
// extract slic3r print config file
|
||||
_extract_print_config_from_archive(archive, stat, config, filename);
|
||||
}
|
||||
if (boost::algorithm::iequals(name, CUSTOM_GCODE_PER_HEIGHT_FILE))
|
||||
if (boost::algorithm::iequals(name, CUSTOM_GCODE_PER_PRINT_Z_FILE))
|
||||
{
|
||||
// extract slic3r layer config ranges file
|
||||
_extract_custom_gcode_per_height_from_archive(archive, stat);
|
||||
_extract_custom_gcode_per_print_z_from_archive(archive, stat);
|
||||
}
|
||||
else if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE))
|
||||
{
|
||||
@@ -1163,7 +1167,7 @@ namespace Slic3r {
|
||||
return true;
|
||||
}
|
||||
|
||||
void _3MF_Importer::_extract_custom_gcode_per_height_from_archive(::mz_zip_archive &archive, const mz_zip_archive_file_stat &stat)
|
||||
void _3MF_Importer::_extract_custom_gcode_per_print_z_from_archive(::mz_zip_archive &archive, const mz_zip_archive_file_stat &stat)
|
||||
{
|
||||
if (stat.m_uncomp_size > 0)
|
||||
{
|
||||
@@ -1178,24 +1182,23 @@ namespace Slic3r {
|
||||
pt::ptree main_tree;
|
||||
pt::read_xml(iss, main_tree);
|
||||
|
||||
if (main_tree.front().first != "custom_gcodes_per_height")
|
||||
if (main_tree.front().first != "custom_gcodes_per_print_z")
|
||||
return;
|
||||
pt::ptree code_tree = main_tree.front().second;
|
||||
|
||||
if (!m_model->custom_gcode_per_height.empty())
|
||||
m_model->custom_gcode_per_height.clear();
|
||||
m_model->custom_gcode_per_print_z.clear();
|
||||
|
||||
for (const auto& code : code_tree)
|
||||
{
|
||||
if (code.first != "code")
|
||||
continue;
|
||||
pt::ptree tree = code.second;
|
||||
double height = tree.get<double>("<xmlattr>.height");
|
||||
std::string gcode = tree.get<std::string>("<xmlattr>.gcode");
|
||||
int extruder = tree.get<int>("<xmlattr>.extruder");
|
||||
std::string color = tree.get<std::string>("<xmlattr>.color");
|
||||
double print_z = tree.get<double> ("<xmlattr>.print_z" );
|
||||
std::string gcode = tree.get<std::string> ("<xmlattr>.gcode" );
|
||||
int extruder = tree.get<int> ("<xmlattr>.extruder" );
|
||||
std::string color = tree.get<std::string> ("<xmlattr>.color" );
|
||||
|
||||
m_model->custom_gcode_per_height.push_back(Model::CustomGCode(height, gcode, extruder, color)) ;
|
||||
m_model->custom_gcode_per_print_z.push_back(Model::CustomGCode{print_z, gcode, extruder, color}) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1611,7 +1614,7 @@ namespace Slic3r {
|
||||
{
|
||||
m_version = (unsigned int)atoi(m_curr_characters.c_str());
|
||||
|
||||
if (m_check_version && (m_version > VERSION_3MF))
|
||||
if (m_check_version && (m_version > VERSION_3MF_COMPATIBLE))
|
||||
{
|
||||
// std::string msg = _(L("The selected 3mf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatible."));
|
||||
// throw version_error(msg.c_str());
|
||||
@@ -1797,20 +1800,19 @@ namespace Slic3r {
|
||||
return false;
|
||||
}
|
||||
|
||||
Slic3r::Geometry::Transformation transform;
|
||||
if (m_version > 1)
|
||||
Transform3d volume_matrix_to_object = Transform3d::Identity();
|
||||
bool has_transform = false;
|
||||
// extract the volume transformation from the volume's metadata, if present
|
||||
for (const Metadata& metadata : volume_data.metadata)
|
||||
{
|
||||
// extract the volume transformation from the volume's metadata, if present
|
||||
for (const Metadata& metadata : volume_data.metadata)
|
||||
if (metadata.key == MATRIX_KEY)
|
||||
{
|
||||
if (metadata.key == MATRIX_KEY)
|
||||
{
|
||||
transform.set_from_string(metadata.value);
|
||||
break;
|
||||
}
|
||||
volume_matrix_to_object = Slic3r::Geometry::transform3d_from_string(metadata.value);
|
||||
has_transform = ! volume_matrix_to_object.isApprox(Transform3d::Identity(), 1e-10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Transform3d inv_matrix = transform.get_matrix().inverse();
|
||||
Transform3d inv_matrix = volume_matrix_to_object.inverse();
|
||||
|
||||
// splits volume out of imported geometry
|
||||
TriangleMesh triangle_mesh;
|
||||
@@ -1831,10 +1833,10 @@ namespace Slic3r {
|
||||
{
|
||||
unsigned int tri_id = geometry.triangles[src_start_id + ii + v] * 3;
|
||||
Vec3f vertex(geometry.vertices[tri_id + 0], geometry.vertices[tri_id + 1], geometry.vertices[tri_id + 2]);
|
||||
if (m_version > 1)
|
||||
facet.vertex[v] = has_transform ?
|
||||
// revert the vertices to the original mesh reference system
|
||||
vertex = (inv_matrix * vertex.cast<double>()).cast<float>();
|
||||
::memcpy(facet.vertex[v].data(), (const void*)vertex.data(), 3 * sizeof(float));
|
||||
(inv_matrix * vertex.cast<double>()).cast<float>() :
|
||||
vertex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1843,8 +1845,8 @@ namespace Slic3r {
|
||||
|
||||
ModelVolume* volume = object.add_volume(std::move(triangle_mesh));
|
||||
// apply the volume matrix taken from the metadata, if present
|
||||
if (m_version > 1)
|
||||
volume->set_transformation(transform);
|
||||
if (has_transform)
|
||||
volume->set_transformation(Slic3r::Geometry::Transformation(volume_matrix_to_object));
|
||||
volume->calculate_convex_hull();
|
||||
|
||||
// apply the remaining volume's metadata
|
||||
@@ -1985,7 +1987,7 @@ namespace Slic3r {
|
||||
bool _add_sla_drain_holes_file_to_archive(mz_zip_archive& archive, Model& model);
|
||||
bool _add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config);
|
||||
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data);
|
||||
bool _add_custom_gcode_per_height_file_to_archive(mz_zip_archive& archive, Model& model);
|
||||
bool _add_custom_gcode_per_print_z_file_to_archive(mz_zip_archive& archive, Model& model);
|
||||
};
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
@@ -2096,9 +2098,9 @@ namespace Slic3r {
|
||||
}
|
||||
|
||||
|
||||
// Adds custom gcode per height file ("Metadata/Prusa_Slicer_custom_gcode_per_height.xml").
|
||||
// Adds custom gcode per height file ("Metadata/Prusa_Slicer_custom_gcode_per_print_z.xml").
|
||||
// All custom gcode per height of whole Model are stored here
|
||||
if (!_add_custom_gcode_per_height_file_to_archive(archive, model))
|
||||
if (!_add_custom_gcode_per_print_z_file_to_archive(archive, model))
|
||||
{
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
@@ -2622,6 +2624,9 @@ namespace Slic3r {
|
||||
bool _3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data)
|
||||
{
|
||||
std::stringstream stream;
|
||||
// Store mesh transformation in full precision, as the volumes are stored transformed and they need to be transformed back
|
||||
// when loaded as accurately as possible.
|
||||
stream << std::setprecision(std::numeric_limits<double>::max_digits10);
|
||||
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
stream << "<" << CONFIG_TAG << ">\n";
|
||||
|
||||
@@ -2719,20 +2724,20 @@ namespace Slic3r {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _3MF_Exporter::_add_custom_gcode_per_height_file_to_archive( mz_zip_archive& archive, Model& model)
|
||||
bool _3MF_Exporter::_add_custom_gcode_per_print_z_file_to_archive( mz_zip_archive& archive, Model& model)
|
||||
{
|
||||
std::string out = "";
|
||||
|
||||
if (!model.custom_gcode_per_height.empty())
|
||||
if (!model.custom_gcode_per_print_z.empty())
|
||||
{
|
||||
pt::ptree tree;
|
||||
pt::ptree& main_tree = tree.add("custom_gcodes_per_height", "");
|
||||
pt::ptree& main_tree = tree.add("custom_gcodes_per_print_z", "");
|
||||
|
||||
for (const Model::CustomGCode& code : model.custom_gcode_per_height)
|
||||
for (const Model::CustomGCode& code : model.custom_gcode_per_print_z)
|
||||
{
|
||||
pt::ptree& code_tree = main_tree.add("code", "");
|
||||
// store minX and maxZ
|
||||
code_tree.put("<xmlattr>.height" , code.height );
|
||||
code_tree.put("<xmlattr>.print_z" , code.print_z );
|
||||
code_tree.put("<xmlattr>.gcode" , code.gcode );
|
||||
code_tree.put("<xmlattr>.extruder" , code.extruder );
|
||||
code_tree.put("<xmlattr>.color" , code.color );
|
||||
@@ -2751,9 +2756,9 @@ bool _3MF_Exporter::_add_custom_gcode_per_height_file_to_archive( mz_zip_archive
|
||||
|
||||
if (!out.empty())
|
||||
{
|
||||
if (!mz_zip_writer_add_mem(&archive, CUSTOM_GCODE_PER_HEIGHT_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION))
|
||||
if (!mz_zip_writer_add_mem(&archive, CUSTOM_GCODE_PER_PRINT_Z_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION))
|
||||
{
|
||||
add_error("Unable to add custom Gcodes per height file to archive");
|
||||
add_error("Unable to add custom Gcodes per print_z file to archive");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,11 @@ namespace pt = boost::property_tree;
|
||||
// Added x and y components of rotation
|
||||
// Added x, y and z components of scale
|
||||
// Added x, y and z components of mirror
|
||||
// 3 : Meshes saved in their local system; Added volumes' matrices and source data
|
||||
const unsigned int VERSION_AMF = 3;
|
||||
// 3 : Added volumes' matrices and source data, meshes transformed back to their coordinate system on loading.
|
||||
// WARNING !! -> the version number has been rolled back to 2
|
||||
// the next change should use 4
|
||||
const unsigned int VERSION_AMF = 2;
|
||||
const unsigned int VERSION_AMF_COMPATIBLE = 3;
|
||||
const char* SLIC3RPE_AMF_VERSION = "slic3rpe_amf_version";
|
||||
|
||||
const char* SLIC3R_CONFIG_TYPE = "slic3rpe_config";
|
||||
@@ -228,6 +231,8 @@ struct AMFParserContext
|
||||
ModelVolume *m_volume;
|
||||
// Faces collected for the current m_volume.
|
||||
std::vector<int> m_volume_facets;
|
||||
// Transformation matrix of a volume mesh from its coordinate system to Object's coordinate system.
|
||||
Transform3d m_volume_transform;
|
||||
// Current material allocated for an amf/metadata subtree.
|
||||
ModelMaterial *m_material;
|
||||
// Current instance allocated for an amf/constellation/instance subtree.
|
||||
@@ -319,6 +324,7 @@ void AMFParserContext::startElement(const char *name, const char **atts)
|
||||
else if (strcmp(name, "volume") == 0) {
|
||||
assert(! m_volume);
|
||||
m_volume = m_object->add_volume(TriangleMesh());
|
||||
m_volume_transform = Transform3d::Identity();
|
||||
node_type_new = NODE_TYPE_VOLUME;
|
||||
}
|
||||
} else if (m_path[2] == NODE_TYPE_INSTANCE) {
|
||||
@@ -578,27 +584,25 @@ void AMFParserContext::endElement(const char * /* name */)
|
||||
stl.stats.original_num_facets = stl.stats.number_of_facets;
|
||||
stl_allocate(&stl);
|
||||
|
||||
Slic3r::Geometry::Transformation transform;
|
||||
if (m_version > 2)
|
||||
transform = m_volume->get_transformation();
|
||||
|
||||
Transform3d inv_matrix = transform.get_matrix().inverse();
|
||||
|
||||
bool has_transform = ! m_volume_transform.isApprox(Transform3d::Identity(), 1e-10);
|
||||
Transform3d inv_matrix = m_volume_transform.inverse();
|
||||
for (size_t i = 0; i < m_volume_facets.size();) {
|
||||
stl_facet &facet = stl.facet_start[i/3];
|
||||
for (unsigned int v = 0; v < 3; ++v)
|
||||
{
|
||||
unsigned int tri_id = m_volume_facets[i++] * 3;
|
||||
Vec3f vertex(m_object_vertices[tri_id + 0], m_object_vertices[tri_id + 1], m_object_vertices[tri_id + 2]);
|
||||
if (m_version > 2)
|
||||
facet.vertex[v] = has_transform ?
|
||||
// revert the vertices to the original mesh reference system
|
||||
vertex = (inv_matrix * vertex.cast<double>()).cast<float>();
|
||||
::memcpy((void*)facet.vertex[v].data(), (const void*)vertex.data(), 3 * sizeof(float));
|
||||
(inv_matrix * vertex.cast<double>()).cast<float>() :
|
||||
vertex;
|
||||
}
|
||||
}
|
||||
}
|
||||
stl_get_size(&stl);
|
||||
mesh.repair();
|
||||
m_volume->set_mesh(std::move(mesh));
|
||||
if (has_transform)
|
||||
m_volume->set_transformation(m_volume_transform);
|
||||
if (m_volume->source.input_file.empty() && (m_volume->type() == ModelVolumeType::MODEL_PART))
|
||||
{
|
||||
m_volume->source.object_idx = (int)m_model.objects.size() - 1;
|
||||
@@ -637,7 +641,7 @@ void AMFParserContext::endElement(const char * /* name */)
|
||||
int extruder = atoi(m_value[2].c_str());
|
||||
const std::string& color = m_value[3];
|
||||
|
||||
m_model.custom_gcode_per_height.push_back(Model::CustomGCode(height, gcode, extruder, color));
|
||||
m_model.custom_gcode_per_print_z.push_back(Model::CustomGCode{height, gcode, extruder, color});
|
||||
|
||||
for (std::string& val: m_value)
|
||||
val.clear();
|
||||
@@ -718,9 +722,7 @@ void AMFParserContext::endElement(const char * /* name */)
|
||||
m_volume->set_type(ModelVolume::type_from_string(m_value[1]));
|
||||
}
|
||||
else if (strcmp(opt_key, "matrix") == 0) {
|
||||
Geometry::Transformation transform;
|
||||
transform.set_from_string(m_value[1]);
|
||||
m_volume->set_transformation(transform);
|
||||
m_volume_transform = Slic3r::Geometry::transform3d_from_string(m_value[1]);
|
||||
}
|
||||
else if (strcmp(opt_key, "source_file") == 0) {
|
||||
m_volume->source.input_file = m_value[1];
|
||||
@@ -910,7 +912,7 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
||||
|
||||
ctx.endDocument();
|
||||
|
||||
if (check_version && (ctx.m_version > VERSION_AMF))
|
||||
if (check_version && (ctx.m_version > VERSION_AMF_COMPATIBLE))
|
||||
{
|
||||
// std::string msg = _(L("The selected amf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatible."));
|
||||
// throw std::runtime_error(msg.c_str());
|
||||
@@ -1146,6 +1148,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
||||
stream << " <metadata type=\"slic3r.volume_type\">" << ModelVolume::type_to_string(volume->type()) << "</metadata>\n";
|
||||
stream << " <metadata type=\"slic3r.matrix\">";
|
||||
const Transform3d& matrix = volume->get_matrix();
|
||||
stream << std::setprecision(std::numeric_limits<double>::max_digits10);
|
||||
for (int r = 0; r < 4; ++r)
|
||||
{
|
||||
for (int c = 0; c < 4; ++c)
|
||||
@@ -1165,6 +1168,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
||||
stream << " <metadata type=\"slic3r.source_offset_y\">" << volume->source.mesh_offset(1) << "</metadata>\n";
|
||||
stream << " <metadata type=\"slic3r.source_offset_z\">" << volume->source.mesh_offset(2) << "</metadata>\n";
|
||||
}
|
||||
stream << std::setprecision(std::numeric_limits<float>::max_digits10);
|
||||
const indexed_triangle_set &its = volume->mesh().its;
|
||||
for (size_t i = 0; i < its.indices.size(); ++i) {
|
||||
stream << " <triangle>\n";
|
||||
@@ -1221,21 +1225,21 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
||||
stream << " </constellation>\n";
|
||||
}
|
||||
|
||||
if (!model->custom_gcode_per_height.empty())
|
||||
if (!model->custom_gcode_per_print_z.empty())
|
||||
{
|
||||
std::string out = "";
|
||||
pt::ptree tree;
|
||||
|
||||
pt::ptree& main_tree = tree.add("custom_gcodes_per_height", "");
|
||||
|
||||
for (const Model::CustomGCode& code : model->custom_gcode_per_height)
|
||||
for (const Model::CustomGCode& code : model->custom_gcode_per_print_z)
|
||||
{
|
||||
pt::ptree& code_tree = main_tree.add("code", "");
|
||||
// store minX and maxZ
|
||||
code_tree.put("<xmlattr>.height", code.height);
|
||||
code_tree.put("<xmlattr>.gcode", code.gcode);
|
||||
code_tree.put("<xmlattr>.extruder", code.extruder);
|
||||
code_tree.put("<xmlattr>.color", code.color);
|
||||
code_tree.put("<xmlattr>.print_z" , code.print_z );
|
||||
code_tree.put("<xmlattr>.gcode" , code.gcode );
|
||||
code_tree.put("<xmlattr>.extruder" , code.extruder );
|
||||
code_tree.put("<xmlattr>.color" , code.color );
|
||||
}
|
||||
|
||||
if (!tree.empty())
|
||||
|
||||
Reference in New Issue
Block a user