diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index fa984dcfbb..810d7ef4b9 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -637,6 +637,21 @@ Transform3d Transformation::get_matrix_no_scaling_factor() const return copy.get_matrix(); } +Transform3d Transformation::get_matrix_with_applied_shrinkage_compensation(const Vec3d &shrinkage_compensation) const { + const Transform3d shrinkage_trafo = Geometry::scale_transform(shrinkage_compensation); + const Vec3d trafo_offset = this->get_offset(); + const Vec3d trafo_offset_xy = Vec3d(trafo_offset.x(), trafo_offset.y(), 0.); + + Transformation copy(*this); + copy.set_offset(Axis::X, 0.); + copy.set_offset(Axis::Y, 0.); + + Transform3d trafo_after_shrinkage = (shrinkage_trafo * copy.get_matrix()); + trafo_after_shrinkage.translation() += trafo_offset_xy; + + return trafo_after_shrinkage; +} + Transformation Transformation::operator * (const Transformation& other) const { return Transformation(get_matrix() * other.get_matrix()); diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index c5d81bda54..3afe6923da 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -460,6 +460,8 @@ public: Transform3d get_matrix_no_offset() const; Transform3d get_matrix_no_scaling_factor() const; + Transform3d get_matrix_with_applied_shrinkage_compensation(const Vec3d &shrinkage_compensation) const; + void set_matrix(const Transform3d& transform) { m_matrix = transform; } Transformation operator * (const Transformation& other) const; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index d6b83c283b..2de86a5283 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1998,6 +1998,22 @@ void ModelVolume::convert_from_meters() this->source.is_converted_from_meters = true; } +std::vector ModelVolume::get_extruders_from_multi_material_painting() const { + if (!this->is_mm_painted()) + return {}; + + assert(static_cast(TriangleStateType::Extruder1) - 1 == 0); + const TriangleSelector::TriangleSplittingData &data = this->mm_segmentation_facets.get_data(); + + std::vector extruders; + for (size_t state_idx = static_cast(TriangleStateType::Extruder1); state_idx < data.used_states.size(); ++state_idx) { + if (data.used_states[state_idx]) + extruders.emplace_back(state_idx - 1); + } + + return extruders; +} + void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const { mesh->transform(dont_translate ? get_matrix_no_offset() : get_matrix()); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 214842d3e5..7ef98db151 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -910,6 +910,9 @@ public: bool is_seam_painted() const { return !this->seam_facets.empty(); } bool is_mm_painted() const { return !this->mm_segmentation_facets.empty(); } + // Returns 0-based indices of extruders painted by multi-material painting gizmo. + std::vector get_extruders_from_multi_material_painting() const; + protected: friend class Print; friend class SLAPrint; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 046334058e..6e34c514d6 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -490,7 +490,9 @@ static std::vector s_Preset_filament_options { "filament_retract_layer_change", "filament_wipe", "filament_retract_before_wipe", "filament_retract_length_toolchange", "filament_retract_restart_extra_toolchange", "filament_travel_ramping_lift", "filament_travel_slope", "filament_travel_max_lift", "filament_travel_lift_before_obstacle", // Profile compatibility - "filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits" + "filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits", + // Shrinkage compensation + "filament_shrinkage_compensation_xy", "filament_shrinkage_compensation_z", }; static std::vector s_Preset_machine_limits_options { diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 116fc88d3b..ddf38250af 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -209,7 +209,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n // Spiral Vase forces different kind of slicing than the normal model: // In Spiral Vase mode, holes are closed and only the largest area contour is kept at each layer. // Therefore toggling the Spiral Vase on / off requires complete reslicing. - || opt_key == "spiral_vase") { + || opt_key == "spiral_vase" + || opt_key == "filament_shrinkage_compensation_xy" + || opt_key == "filament_shrinkage_compensation_z") { osteps.emplace_back(posSlice); } else if ( opt_key == "complete_objects" @@ -525,6 +527,9 @@ std::string Print::validate(std::vector* warnings) const goto DONE; } DONE:; + + if (!this->has_same_shrinkage_compensations()) + warnings->emplace_back("_FILAMENT_SHRINKAGE_DIFFER"); } if (m_objects.empty()) @@ -584,12 +589,19 @@ std::string Print::validate(std::vector* warnings) const //FIXME It is quite expensive to generate object layers just to get the print height! if (auto layers = generate_object_layers(print_object.slicing_parameters(), layer_height_profile(print_object_idx)); ! layers.empty() && layers.back() > this->config().max_print_height + EPSILON) { - return - // Test whether the last slicing plane is below or above the print volume. - 0.5 * (layers[layers.size() - 2] + layers.back()) > this->config().max_print_height + EPSILON ? - format(_u8L("The object %1% exceeds the maximum build volume height."), print_object.model_object()->name) : - format(_u8L("While the object %1% itself fits the build volume, its last layer exceeds the maximum build volume height."), print_object.model_object()->name) + - " " + _u8L("You might want to reduce the size of your model or change current print settings and retry."); + + const double shrinkage_compensation_z = this->shrinkage_compensation().z(); + if (shrinkage_compensation_z != 1. && layers.back() > (this->config().max_print_height / shrinkage_compensation_z + EPSILON)) { + // The object exceeds the maximum build volume height because of shrinkage compensation. + return format(_u8L("While the object %1% itself fits the build volume, it exceeds the maximum build volume height because of material shrinkage compensation."), print_object.model_object()->name); + } else if (0.5 * (layers[layers.size() - 2] + layers.back()) > this->config().max_print_height + EPSILON) { + // The last slicing plane is below the print volume. + return format(_u8L("The object %1% exceeds the maximum build volume height."), print_object.model_object()->name); + } else { + // The last slicing plane is above the print volume. + return format(_u8L("While the object %1% itself fits the build volume, its last layer exceeds the maximum build volume height."), print_object.model_object()->name) + + " " + _u8L("You might want to reduce the size of your model or change current print settings and retry."); + } } } @@ -1618,6 +1630,40 @@ std::string Print::output_filename(const std::string &filename_base) const return this->PrintBase::output_filename(output_filename_format, ".gcode", filename_base, &config); } +// Returns if all used filaments have same shrinkage compensations. +bool Print::has_same_shrinkage_compensations() const { + const std::vector extruders = this->extruders(); + if (extruders.empty()) + return false; + + const double filament_shrinkage_compensation_xy = m_config.filament_shrinkage_compensation_xy.get_at(extruders.front()); + const double filament_shrinkage_compensation_z = m_config.filament_shrinkage_compensation_z.get_at(extruders.front()); + + for (unsigned int extruder : extruders) { + if (filament_shrinkage_compensation_xy != m_config.filament_shrinkage_compensation_xy.get_at(extruder) || + filament_shrinkage_compensation_z != m_config.filament_shrinkage_compensation_z.get_at(extruder)) { + return false; + } + } + + return true; +} + +// Returns scaling for each axis representing shrinkage compensations in each axis. +Vec3d Print::shrinkage_compensation() const +{ + if (!this->has_same_shrinkage_compensations()) + return Vec3d::Ones(); + + const unsigned int first_extruder = this->extruders().front(); + const double xy_compensation_percent = std::clamp(m_config.filament_shrinkage_compensation_xy.get_at(first_extruder), -99., 99.); + const double z_compensation_percent = std::clamp(m_config.filament_shrinkage_compensation_z.get_at(first_extruder), -99., 99.); + const double xy_compensation = 100. / (100. - xy_compensation_percent); + const double z_compensation = 100. / (100. - z_compensation_percent); + + return { xy_compensation, xy_compensation, z_compensation }; +} + const std::string PrintStatistics::FilamentUsedG = "filament used [g]"; const std::string PrintStatistics::FilamentUsedGMask = "; filament used [g] ="; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 1acc6d0b7c..0da013da73 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -327,7 +327,7 @@ public: // The slicing parameters are dependent on various configuration values // (layer height, first layer height, raft settings, print nozzle diameter etc). const SlicingParameters& slicing_parameters() const { return m_slicing_params; } - static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z); + static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation); size_t num_printing_regions() const throw() { return m_shared_regions->all_regions.size(); } const PrintRegion& printing_region(size_t idx) const throw() { return *m_shared_regions->all_regions[idx].get(); } @@ -665,6 +665,12 @@ public: const Polygons& get_sequential_print_clearance_contours() const { return m_sequential_print_clearance_contours; } static bool sequential_print_horizontal_clearance_valid(const Print& print, Polygons* polygons = nullptr); + // Returns if all used filaments have same shrinkage compensations. + bool has_same_shrinkage_compensations() const; + + // Returns scaling for each axis representing shrinkage compensations in each axis. + Vec3d shrinkage_compensation() const; + protected: // Invalidates the step, and its depending steps in Print. bool invalidate_step(PrintStep step); diff --git a/src/libslic3r/PrintApply.cpp b/src/libslic3r/PrintApply.cpp index 03e1dff23f..57c20a6b4d 100644 --- a/src/libslic3r/PrintApply.cpp +++ b/src/libslic3r/PrintApply.cpp @@ -134,13 +134,14 @@ struct PrintObjectTrafoAndInstances }; // Generate a list of trafos and XY offsets for instances of a ModelObject -static std::vector print_objects_from_model_object(const ModelObject &model_object) +static std::vector print_objects_from_model_object(const ModelObject &model_object, const Vec3d &shrinkage_compensation) { std::set trafos; PrintObjectTrafoAndInstances trafo; for (ModelInstance *model_instance : model_object.instances) if (model_instance->is_printable()) { - trafo.trafo = model_instance->get_matrix(); + Geometry::Transformation model_instance_transformation = model_instance->get_transformation(); + trafo.trafo = model_instance_transformation.get_matrix_with_applied_shrinkage_compensation(shrinkage_compensation); auto shift = Point::new_scale(trafo.trafo.data()[12], trafo.trafo.data()[13]); // Reset the XY axes of the transformation. trafo.trafo.data()[12] = 0; @@ -1281,7 +1282,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ // Walk over all new model objects and check, whether there are matching PrintObjects. for (ModelObject *model_object : m_model.objects) { ModelObjectStatus &model_object_status = const_cast(model_object_status_db.reuse(*model_object)); - model_object_status.print_instances = print_objects_from_model_object(*model_object); + model_object_status.print_instances = print_objects_from_model_object(*model_object, this->shrinkage_compensation()); std::vector old; old.reserve(print_object_status_db.count(*model_object)); for (const PrintObjectStatus &print_object_status : print_object_status_db.get_range(*model_object)) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 632a48fdcc..b14ff3e11b 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1332,6 +1332,28 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionString(L("(Unknown)"))); def->cli = ConfigOptionDef::nocli; + def = this->add("filament_shrinkage_compensation_xy", coPercents); + def->label = L("Shrinkage XY"); + def->tooltip = L("Enter your filament shrinkage percentages for the X and Y axes here to apply scaling of the object to " + "compensate for shrinkage in the X and Y axes. For example, if you measured 99mm instead of 100mm, " + "then you should put here 1%."); + def->sidetext = L("%"); + def->mode = comAdvanced; + def->min = -10.; + def->max = 10.; + def->set_default_value(new ConfigOptionPercents { 0 }); + + def = this->add("filament_shrinkage_compensation_z", coPercents); + def->label = L("Shrinkage Z"); + def->tooltip = L("Enter your filament shrinkage percentages for the Z axis here to apply scaling of the object to " + "compensate for shrinkage in the Z axis. For example, if you measured 99mm instead of 100mm, " + "then you should put here 1%."); + def->sidetext = L("%"); + def->mode = comAdvanced; + def->min = -10.; + def->max = 10.; + def->set_default_value(new ConfigOptionPercents { 0. }); + def = this->add("fill_angle", coFloat); def->label = L("Fill angle"); def->category = L("Infill"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 72ba652e5f..e95f486776 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -745,6 +745,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloats, filament_multitool_ramming_flow)) ((ConfigOptionFloats, filament_stamping_loading_speed)) ((ConfigOptionFloats, filament_stamping_distance)) + ((ConfigOptionPercents, filament_shrinkage_compensation_xy)) + ((ConfigOptionPercents, filament_shrinkage_compensation_z)) ((ConfigOptionBool, gcode_comments)) ((ConfigOptionEnum, gcode_flavor)) ((ConfigOptionEnum, gcode_label_objects)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index ac8d440846..d4b8736e49 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -2620,15 +2620,14 @@ PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &defau return config; } -void PrintObject::update_slicing_parameters() -{ - if (!m_slicing_params.valid) - m_slicing_params = SlicingParameters::create_from_config( - this->print()->config(), m_config, this->model_object()->max_z(), this->object_extruders()); +void PrintObject::update_slicing_parameters() { + if (!m_slicing_params.valid) { + m_slicing_params = SlicingParameters::create_from_config(this->print()->config(), m_config, this->model_object()->max_z(), + this->object_extruders(), this->print()->shrinkage_compensation()); + } } -SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full_config, const ModelObject& model_object, float object_max_z) -{ +SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation) { PrintConfig print_config; PrintObjectConfig object_config; PrintRegionConfig default_region_config; @@ -2661,7 +2660,8 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full if (object_max_z <= 0.f) object_max_z = (float)model_object.raw_bounding_box().size().z(); - return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders); + + return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders, object_shrinkage_compensation); } // returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions) @@ -2682,7 +2682,6 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c if (layer_height_profile.empty()) { // use the constructor because the assignement is crashing on ASAN OsX layer_height_profile = model_object.layer_height_profile.get(); -// layer_height_profile = model_object.layer_height_profile; // The layer height returned is sampled with high density for the UI layer height painting // and smoothing tool to work. updated = true; @@ -2693,8 +2692,9 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c // Must not be of even length. ((layer_height_profile.size() & 1) != 0 || // Last entry must be at the top of the object. - std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_parameters.object_print_z_max + slicing_parameters.object_print_z_min) > 1e-3)) + std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_parameters.object_print_z_uncompensated_max + slicing_parameters.object_print_z_min) > 1e-3)) { layer_height_profile.clear(); + } if (layer_height_profile.empty()) { //layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_config_ranges, model_object.volumes); diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index a2414d6998..091c46dc54 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -63,10 +63,11 @@ coordf_t Slicing::max_layer_height_from_nozzle(const DynamicPrintConfig &print_c } SlicingParameters SlicingParameters::create_from_config( - const PrintConfig &print_config, - const PrintObjectConfig &object_config, - coordf_t object_height, - const std::vector &object_extruders) + const PrintConfig &print_config, + const PrintObjectConfig &object_config, + coordf_t object_height, + const std::vector &object_extruders, + const Vec3d &object_shrinkage_compensation) { assert(! print_config.first_layer_height.percent); coordf_t first_layer_height = (print_config.first_layer_height.value <= 0) ? @@ -85,7 +86,9 @@ SlicingParameters SlicingParameters::create_from_config( params.first_print_layer_height = first_layer_height; params.first_object_layer_height = first_layer_height; params.object_print_z_min = 0.; - params.object_print_z_max = object_height; + params.object_print_z_max = object_height * object_shrinkage_compensation.z(); + params.object_print_z_uncompensated_max = object_height; + params.object_shrinkage_compensation_z = object_shrinkage_compensation.z(); params.base_raft_layers = object_config.raft_layers.value; params.soluble_interface = soluble_interface; @@ -152,6 +155,7 @@ SlicingParameters SlicingParameters::create_from_config( coordf_t print_z = params.raft_contact_top_z + params.gap_raft_object; params.object_print_z_min = print_z; params.object_print_z_max += print_z; + params.object_print_z_uncompensated_max += print_z; } params.valid = true; @@ -224,10 +228,10 @@ std::vector layer_height_profile_from_ranges( lh_append(hi, height); } - if (coordf_t z = last_z(); z < slicing_params.object_print_z_height()) { + if (coordf_t z = last_z(); z < slicing_params.object_print_z_uncompensated_height()) { // Insert a step of normal layer height up to the object top. lh_append(z, slicing_params.layer_height); - lh_append(slicing_params.object_print_z_height(), slicing_params.layer_height); + lh_append(slicing_params.object_print_z_uncompensated_height(), slicing_params.layer_height); } return layer_height_profile; @@ -418,12 +422,12 @@ void adjust_layer_height_profile( std::pair z_span_variable = std::pair( slicing_params.first_object_layer_height_fixed() ? slicing_params.first_object_layer_height : 0., - slicing_params.object_print_z_height()); + slicing_params.object_print_z_uncompensated_height()); if (z < z_span_variable.first || z > z_span_variable.second) return; assert(layer_height_profile.size() >= 2); - assert(std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_params.object_print_z_height()) < EPSILON); + assert(std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_params.object_print_z_uncompensated_height()) < EPSILON); // 1) Get the current layer thickness at z. coordf_t current_layer_height = slicing_params.layer_height; @@ -584,7 +588,7 @@ void adjust_layer_height_profile( assert(layer_height_profile.size() > 2); assert(layer_height_profile.size() % 2 == 0); assert(layer_height_profile[0] == 0.); - assert(std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_params.object_print_z_height()) < EPSILON); + assert(std::abs(layer_height_profile[layer_height_profile.size() - 2] - slicing_params.object_print_z_uncompensated_height()) < EPSILON); #ifdef _DEBUG for (size_t i = 2; i < layer_height_profile.size(); i += 2) assert(layer_height_profile[i - 2] <= layer_height_profile[i]); @@ -613,6 +617,7 @@ std::vector generate_object_layers( out.push_back(print_z); } + const coordf_t shrinkage_compensation_z = slicing_params.object_shrinkage_compensation_z; size_t idx_layer_height_profile = 0; // loop until we have at least one layer and the max slice_z reaches the object height coordf_t slice_z = print_z + 0.5 * slicing_params.min_layer_height; @@ -621,17 +626,18 @@ std::vector generate_object_layers( if (idx_layer_height_profile < layer_height_profile.size()) { size_t next = idx_layer_height_profile + 2; for (;;) { - if (next >= layer_height_profile.size() || slice_z < layer_height_profile[next]) + if (next >= layer_height_profile.size() || slice_z < layer_height_profile[next] * shrinkage_compensation_z) break; idx_layer_height_profile = next; next += 2; } - coordf_t z1 = layer_height_profile[idx_layer_height_profile]; - coordf_t h1 = layer_height_profile[idx_layer_height_profile + 1]; + + const coordf_t z1 = layer_height_profile[idx_layer_height_profile] * shrinkage_compensation_z; + const coordf_t h1 = layer_height_profile[idx_layer_height_profile + 1]; height = h1; if (next < layer_height_profile.size()) { - coordf_t z2 = layer_height_profile[next]; - coordf_t h2 = layer_height_profile[next + 1]; + const coordf_t z2 = layer_height_profile[next] * shrinkage_compensation_z; + const coordf_t h2 = layer_height_profile[next + 1]; height = lerp(h1, h2, (slice_z - z1) / (z2 - z1)); assert(height >= slicing_params.min_layer_height - EPSILON && height <= slicing_params.max_layer_height + EPSILON); } diff --git a/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp index 7c2b93e21c..9e4b0499cc 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -33,10 +33,11 @@ struct SlicingParameters SlicingParameters() = default; static SlicingParameters create_from_config( - const PrintConfig &print_config, - const PrintObjectConfig &object_config, - coordf_t object_height, - const std::vector &object_extruders); + const PrintConfig &print_config, + const PrintObjectConfig &object_config, + coordf_t object_height, + const std::vector &object_extruders, + const Vec3d &object_shrinkage_compensation); // Has any raft layers? bool has_raft() const { return raft_layers() > 0; } @@ -46,8 +47,13 @@ struct SlicingParameters bool first_object_layer_height_fixed() const { return ! has_raft() || first_object_layer_bridging; } // Height of the object to be printed. This value does not contain the raft height. + // This value is scaled by shrinkage compensation in the Z-axis. coordf_t object_print_z_height() const { return object_print_z_max - object_print_z_min; } + // Height of the object to be printed. This value does not contain the raft height. + // This value isn't scaled by shrinkage compensation in the Z-axis. + coordf_t object_print_z_uncompensated_height() const { return object_print_z_uncompensated_max - object_print_z_min; } + bool valid { false }; // Number of raft layers. @@ -99,7 +105,13 @@ struct SlicingParameters coordf_t raft_contact_top_z { 0 }; // In case of a soluble interface, object_print_z_min == raft_contact_top_z, otherwise there is a gap between the raft and the 1st object layer. coordf_t object_print_z_min { 0 }; + // This value of maximum print Z is scaled by shrinkage compensation in the Z-axis. coordf_t object_print_z_max { 0 }; + + // This value of maximum print Z isn't scaled by shrinkage compensation. + coordf_t object_print_z_uncompensated_max { 0 }; + // Scaling factor for compensating shrinkage in Z-axis. + coordf_t object_shrinkage_compensation_z { 0 }; }; static_assert(IsTriviallyCopyable::value, "SlicingParameters class is not POD (and it should be - see constructor)."); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 5e19f3fe27..65090b6676 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -628,11 +628,10 @@ void GLCanvas3D::LayersEditing::accept_changes(GLCanvas3D& canvas) m_layer_height_profile_modified = false; } -void GLCanvas3D::LayersEditing::update_slicing_parameters() -{ - if (m_slicing_parameters == nullptr) { - m_slicing_parameters = new SlicingParameters(); - *m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object, m_object_max_z); +void GLCanvas3D::LayersEditing::update_slicing_parameters() { + if (m_slicing_parameters == nullptr) { + m_slicing_parameters = new SlicingParameters(); + *m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object, m_object_max_z, m_shrinkage_compensation); } } @@ -1605,9 +1604,11 @@ void GLCanvas3D::set_config(const DynamicPrintConfig* config) m_config = config; m_layers_editing.set_config(config); - if (config) { - PrinterTechnology ptech = current_printer_technology(); + const PrinterTechnology ptech = current_printer_technology(); + if (const Print *print = fff_print(); ptech == ptFFF && print != nullptr) + m_layers_editing.set_shrinkage_compensation(fff_print()->shrinkage_compensation()); + if (config) { auto slot = ArrangeSettingsDb_AppCfg::slotFFF; if (ptech == ptSLA) { @@ -3200,9 +3201,9 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) } } - // If Undo/Redo list is opened, + // If Undo/Redo list is opened, // update them according to the event - if (m_undoredo_toolbar.is_item_pressed("undo") || + if (m_undoredo_toolbar.is_item_pressed("undo") || m_undoredo_toolbar.is_item_pressed("redo")) { m_mouse_wheel = int((double)evt.GetWheelRotation() / (double)evt.GetWheelDelta()); return; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 09ff631ed5..3975b02b08 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -219,6 +219,8 @@ class GLCanvas3D SlicingParameters *m_slicing_parameters{ nullptr }; std::vector m_layer_height_profile; bool m_layer_height_profile_modified{ false }; + // Shrinkage compensation to apply when we need to use object_max_z with Z compensation. + Vec3d m_shrinkage_compensation{ Vec3d::Ones() }; mutable float m_adaptive_quality{ 0.5f }; mutable HeightProfileSmoothingParams m_smooth_params; @@ -299,6 +301,8 @@ class GLCanvas3D std::pair> get_layers_height_data(); + void set_shrinkage_compensation(const Vec3d &shrinkage_compensation) { m_shrinkage_compensation = shrinkage_compensation; }; + private: bool is_initialized() const; void generate_layer_height_texture(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 62e0c5f6b6..53ae3677a0 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1938,6 +1938,10 @@ void Plater::priv::process_validation_warning(const std::vector& wa if (text == "_BED_TEMPS_DIFFER") text = _u8L("Bed temperatures for the used filaments differ significantly."); + if (text == "_FILAMENT_SHRINKAGE_DIFFER") + text = _u8L("Filament shrinkage will not be used because filament shrinkage " + "for the used filaments differs significantly."); + notification_manager->push_notification( NotificationType::ValidateWarning, NotificationManager::NotificationLevel::WarningNotificationLevel, diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index fdf0d3a339..017de90fcd 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2237,6 +2237,10 @@ void TabFilament::build() }; optgroup->append_line(line); + optgroup = page->new_optgroup(L("Shrinkage compensation")); + optgroup->append_single_option_line("filament_shrinkage_compensation_xy"); + optgroup->append_single_option_line("filament_shrinkage_compensation_z"); + optgroup = page->new_optgroup(L("Wipe tower parameters")); optgroup->append_single_option_line("filament_minimal_purge_on_wipe_tower");