diff --git a/resources/icons/bed/mini.svg b/resources/icons/bed/mini.svg index 1b9476ef8..93c3437bd 100644 --- a/resources/icons/bed/mini.svg +++ b/resources/icons/bed/mini.svg @@ -1,109 +1,70 @@ - - bed_texture_denser - - - - - - - - - - + + MINI_bed_texture + + + + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/admesh/stl.h b/src/admesh/stl.h index fa0edec2b..9224b0459 100644 --- a/src/admesh/stl.h +++ b/src/admesh/stl.h @@ -184,10 +184,21 @@ extern void stl_mirror_xz(stl_file *stl); extern void stl_get_size(stl_file *stl); +// the following function is not used +/* template extern void stl_transform(stl_file *stl, T *trafo3x4) { - for (uint32_t i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) { + Eigen::Matrix trafo3x3; + for (int i = 0; i < 3; ++i) + { + for (int j = 0; j < 3; ++j) + { + trafo3x3(i, j) = (i * 4) + j; + } + } + Eigen::Matrix r = trafo3x3.inverse().transpose(); + for (uint32_t i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) { stl_facet &face = stl->facet_start[i_face]; for (int i_vertex = 0; i_vertex < 3; ++ i_vertex) { stl_vertex &v_dst = face.vertex[i_vertex]; @@ -196,21 +207,18 @@ extern void stl_transform(stl_file *stl, T *trafo3x4) v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6] * v_src(2) + trafo3x4[7]); v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2) + trafo3x4[11]); } - stl_vertex &v_dst = face.normal; - stl_vertex v_src = v_dst; - v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2] * v_src(2)); - v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6] * v_src(2)); - v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2)); - } + face.normal = (r * face.normal.template cast()).template cast().eval(); + } stl_get_size(stl); } +*/ template inline void stl_transform(stl_file *stl, const Eigen::Transform& t) { - const Eigen::Matrix r = t.matrix().template block<3, 3>(0, 0); - for (size_t i = 0; i < stl->stats.number_of_facets; ++ i) { + const Eigen::Matrix r = t.matrix().template block<3, 3>(0, 0).inverse().transpose(); + for (size_t i = 0; i < stl->stats.number_of_facets; ++ i) { stl_facet &f = stl->facet_start[i]; for (size_t j = 0; j < 3; ++j) f.vertex[j] = (t * f.vertex[j].template cast()).template cast().eval(); @@ -223,12 +231,13 @@ inline void stl_transform(stl_file *stl, const Eigen::Transform inline void stl_transform(stl_file *stl, const Eigen::Matrix& m) { - for (size_t i = 0; i < stl->stats.number_of_facets; ++ i) { + const Eigen::Matrix r = m.inverse().transpose(); + for (size_t i = 0; i < stl->stats.number_of_facets; ++ i) { stl_facet &f = stl->facet_start[i]; for (size_t j = 0; j < 3; ++j) f.vertex[j] = (m * f.vertex[j].template cast()).template cast().eval(); - f.normal = (m * f.normal.template cast()).template cast().eval(); - } + f.normal = (r * f.normal.template cast()).template cast().eval(); + } stl_get_size(stl); } diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 56a94b28c..28bcdf50c 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -6,9 +6,6 @@ #include "Geometry.hpp" #include "GCode/PrintExtents.hpp" #include "GCode/WipeTower.hpp" -#if ENABLE_THUMBNAIL_GENERATOR -#include "GCode/ThumbnailData.hpp" -#endif // ENABLE_THUMBNAIL_GENERATOR #include "ShortestPath.hpp" #include "Utils.hpp" @@ -695,7 +692,7 @@ std::vector>> GCode::collec } #if ENABLE_THUMBNAIL_GENERATOR -void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_data, const std::vector* thumbnail_data) +void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb) #else void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_data) #endif // ENABLE_THUMBNAIL_GENERATOR @@ -725,7 +722,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_ try { m_placeholder_parser_failed_templates.clear(); #if ENABLE_THUMBNAIL_GENERATOR - this->_do_export(*print, file, thumbnail_data); + this->_do_export(*print, file, thumbnail_cb); #else this->_do_export(*print, file); #endif // ENABLE_THUMBNAIL_GENERATOR @@ -793,9 +790,9 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_ } #if ENABLE_THUMBNAIL_GENERATOR -void GCode::_do_export(Print& print, FILE* file, const std::vector* thumbnail_data) +void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thumbnail_cb) #else -void GCode::_do_export(Print &print, FILE *file) +void GCode::_do_export(Print& print, FILE* file) #endif // ENABLE_THUMBNAIL_GENERATOR { PROFILE_FUNC(); @@ -812,46 +809,46 @@ void GCode::_do_export(Print &print, FILE *file) // shall be adjusted as well to produce a G-code block compatible with the particular firmware flavor. if (print.config().gcode_flavor.value == gcfMarlin) { m_normal_time_estimator.set_max_acceleration((float)print.config().machine_max_acceleration_extruding.values[0]); - m_normal_time_estimator.set_retract_acceleration((float)print.config().machine_max_acceleration_retracting.values[0]); - m_normal_time_estimator.set_minimum_feedrate((float)print.config().machine_min_extruding_rate.values[0]); - m_normal_time_estimator.set_minimum_travel_feedrate((float)print.config().machine_min_travel_rate.values[0]); - m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)print.config().machine_max_acceleration_x.values[0]); - m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)print.config().machine_max_acceleration_y.values[0]); - m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)print.config().machine_max_acceleration_z.values[0]); - m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)print.config().machine_max_acceleration_e.values[0]); - m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)print.config().machine_max_feedrate_x.values[0]); - m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)print.config().machine_max_feedrate_y.values[0]); - m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)print.config().machine_max_feedrate_z.values[0]); - m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)print.config().machine_max_feedrate_e.values[0]); - m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)print.config().machine_max_jerk_x.values[0]); - m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)print.config().machine_max_jerk_y.values[0]); - m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)print.config().machine_max_jerk_z.values[0]); - m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)print.config().machine_max_jerk_e.values[0]); + m_normal_time_estimator.set_retract_acceleration((float)print.config().machine_max_acceleration_retracting.values[0]); + m_normal_time_estimator.set_minimum_feedrate((float)print.config().machine_min_extruding_rate.values[0]); + m_normal_time_estimator.set_minimum_travel_feedrate((float)print.config().machine_min_travel_rate.values[0]); + m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)print.config().machine_max_acceleration_x.values[0]); + m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)print.config().machine_max_acceleration_y.values[0]); + m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)print.config().machine_max_acceleration_z.values[0]); + m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)print.config().machine_max_acceleration_e.values[0]); + m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)print.config().machine_max_feedrate_x.values[0]); + m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)print.config().machine_max_feedrate_y.values[0]); + m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)print.config().machine_max_feedrate_z.values[0]); + m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)print.config().machine_max_feedrate_e.values[0]); + m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)print.config().machine_max_jerk_x.values[0]); + m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)print.config().machine_max_jerk_y.values[0]); + m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)print.config().machine_max_jerk_z.values[0]); + m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)print.config().machine_max_jerk_e.values[0]); if (m_silent_time_estimator_enabled) { m_silent_time_estimator.reset(); m_silent_time_estimator.set_dialect(print.config().gcode_flavor); - /* "Stealth mode" values can be just a copy of "normal mode" values + /* "Stealth mode" values can be just a copy of "normal mode" values * (when they aren't input for a printer preset). * Thus, use back value from values, instead of second one, which could be absent */ - m_silent_time_estimator.set_max_acceleration((float)print.config().machine_max_acceleration_extruding.values.back()); - m_silent_time_estimator.set_retract_acceleration((float)print.config().machine_max_acceleration_retracting.values.back()); - m_silent_time_estimator.set_minimum_feedrate((float)print.config().machine_min_extruding_rate.values.back()); - m_silent_time_estimator.set_minimum_travel_feedrate((float)print.config().machine_min_travel_rate.values.back()); - m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)print.config().machine_max_acceleration_x.values.back()); - m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)print.config().machine_max_acceleration_y.values.back()); - m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)print.config().machine_max_acceleration_z.values.back()); - m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)print.config().machine_max_acceleration_e.values.back()); - m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)print.config().machine_max_feedrate_x.values.back()); - m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)print.config().machine_max_feedrate_y.values.back()); - m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)print.config().machine_max_feedrate_z.values.back()); - m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)print.config().machine_max_feedrate_e.values.back()); - m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)print.config().machine_max_jerk_x.values.back()); - m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)print.config().machine_max_jerk_y.values.back()); - m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)print.config().machine_max_jerk_z.values.back()); - m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)print.config().machine_max_jerk_e.values.back()); + m_silent_time_estimator.set_max_acceleration((float)print.config().machine_max_acceleration_extruding.values.back()); + m_silent_time_estimator.set_retract_acceleration((float)print.config().machine_max_acceleration_retracting.values.back()); + m_silent_time_estimator.set_minimum_feedrate((float)print.config().machine_min_extruding_rate.values.back()); + m_silent_time_estimator.set_minimum_travel_feedrate((float)print.config().machine_min_travel_rate.values.back()); + m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)print.config().machine_max_acceleration_x.values.back()); + m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)print.config().machine_max_acceleration_y.values.back()); + m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)print.config().machine_max_acceleration_z.values.back()); + m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)print.config().machine_max_acceleration_e.values.back()); + m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)print.config().machine_max_feedrate_x.values.back()); + m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)print.config().machine_max_feedrate_y.values.back()); + m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)print.config().machine_max_feedrate_z.values.back()); + m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)print.config().machine_max_feedrate_e.values.back()); + m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)print.config().machine_max_jerk_x.values.back()); + m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)print.config().machine_max_jerk_y.values.back()); + m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)print.config().machine_max_jerk_z.values.back()); + m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)print.config().machine_max_jerk_e.values.back()); if (print.config().single_extruder_multi_material) { // As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they // are considered to be active for the single extruder multi-material printers only. @@ -909,7 +906,8 @@ void GCode::_do_export(Print &print, FILE *file) std::sort(zs.begin(), zs.end()); m_layer_count += (unsigned int)(object->copies().size() * (std::unique(zs.begin(), zs.end()) - zs.begin())); } - } else { + } + else { // Print all objects with the same print_z together. std::vector zs; for (auto object : print.objects()) { @@ -927,7 +925,7 @@ void GCode::_do_export(Print &print, FILE *file) m_enable_cooling_markers = true; this->apply_print_config(print.config()); this->set_extruders(print.extruders()); - + // Initialize colorprint. m_colorprint_heights = cast(print.config().colorprint_heights.values); @@ -936,31 +934,31 @@ void GCode::_do_export(Print &print, FILE *file) // get the minimum cross-section used in the print std::vector mm3_per_mm; for (auto object : print.objects()) { - for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) { + for (size_t region_id = 0; region_id < object->region_volumes.size(); ++region_id) { const PrintRegion* region = print.regions()[region_id]; for (auto layer : object->layers()) { const LayerRegion* layerm = layer->regions()[region_id]; - if (region->config().get_abs_value("perimeter_speed" ) == 0 || - region->config().get_abs_value("small_perimeter_speed" ) == 0 || - region->config().get_abs_value("external_perimeter_speed" ) == 0 || - region->config().get_abs_value("bridge_speed" ) == 0) + if (region->config().get_abs_value("perimeter_speed") == 0 || + region->config().get_abs_value("small_perimeter_speed") == 0 || + region->config().get_abs_value("external_perimeter_speed") == 0 || + region->config().get_abs_value("bridge_speed") == 0) mm3_per_mm.push_back(layerm->perimeters.min_mm3_per_mm()); - if (region->config().get_abs_value("infill_speed" ) == 0 || - region->config().get_abs_value("solid_infill_speed" ) == 0 || - region->config().get_abs_value("top_solid_infill_speed" ) == 0 || - region->config().get_abs_value("bridge_speed" ) == 0) + if (region->config().get_abs_value("infill_speed") == 0 || + region->config().get_abs_value("solid_infill_speed") == 0 || + region->config().get_abs_value("top_solid_infill_speed") == 0 || + region->config().get_abs_value("bridge_speed") == 0) mm3_per_mm.push_back(layerm->fills.min_mm3_per_mm()); } } - if (object->config().get_abs_value("support_material_speed" ) == 0 || - object->config().get_abs_value("support_material_interface_speed" ) == 0) + if (object->config().get_abs_value("support_material_speed") == 0 || + object->config().get_abs_value("support_material_interface_speed") == 0) for (auto layer : object->support_layers()) mm3_per_mm.push_back(layer->support_fills.min_mm3_per_mm()); } print.throw_if_canceled(); // filter out 0-width segments mm3_per_mm.erase(std::remove_if(mm3_per_mm.begin(), mm3_per_mm.end(), [](double v) { return v < 0.000001; }), mm3_per_mm.end()); - if (! mm3_per_mm.empty()) { + if (!mm3_per_mm.empty()) { // In order to honor max_print_speed we need to find a target volumetric // speed that we can use throughout the print. So we define this target // volumetric speed as the volumetric speed produced by printing the @@ -973,7 +971,7 @@ void GCode::_do_export(Print &print, FILE *file) } } print.throw_if_canceled(); - + m_cooling_buffer = make_unique(*this); if (print.config().spiral_vase.value) m_spiral_vase = make_unique(print.config()); @@ -991,11 +989,12 @@ void GCode::_do_export(Print &print, FILE *file) #if ENABLE_THUMBNAIL_GENERATOR // Write thumbnails using base64 encoding - if (thumbnail_data != nullptr) + if (thumbnail_cb != nullptr) { const size_t max_row_length = 78; - - for (const ThumbnailData& data : *thumbnail_data) + ThumbnailsList thumbnails; + thumbnail_cb(thumbnails, print.full_print_config().option("thumbnails")->values, true, true, false); + for (const ThumbnailData& data : thumbnails) { if (data.is_valid()) { diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 19ec5be3c..40794986a 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -17,6 +17,9 @@ #include "GCodeTimeEstimator.hpp" #include "EdgeGrid.hpp" #include "GCode/Analyzer.hpp" +#if ENABLE_THUMBNAIL_GENERATOR +#include "GCode/ThumbnailData.hpp" +#endif // ENABLE_THUMBNAIL_GENERATOR #include #include @@ -30,9 +33,6 @@ namespace Slic3r { // Forward declarations. class GCode; class GCodePreviewData; -#if ENABLE_THUMBNAIL_GENERATOR -struct ThumbnailData; -#endif // ENABLE_THUMBNAIL_GENERATOR class AvoidCrossingPerimeters { public: @@ -167,7 +167,7 @@ public: // throws std::runtime_exception on error, // throws CanceledException through print->throw_if_canceled(). #if ENABLE_THUMBNAIL_GENERATOR - void do_export(Print* print, const char* path, GCodePreviewData* preview_data = nullptr, const std::vector* thumbnail_data = nullptr); + void do_export(Print* print, const char* path, GCodePreviewData* preview_data = nullptr, ThumbnailsGeneratorCallback thumbnail_cb = nullptr); #else void do_export(Print *print, const char *path, GCodePreviewData *preview_data = nullptr); #endif // ENABLE_THUMBNAIL_GENERATOR @@ -199,7 +199,7 @@ public: protected: #if ENABLE_THUMBNAIL_GENERATOR - void _do_export(Print& print, FILE* file, const std::vector* thumbnail_data); + void _do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thumbnail_cb); #else void _do_export(Print &print, FILE *file); #endif //ENABLE_THUMBNAIL_GENERATOR diff --git a/src/libslic3r/GCode/ThumbnailData.hpp b/src/libslic3r/GCode/ThumbnailData.hpp index 9823ffd31..efe875e15 100644 --- a/src/libslic3r/GCode/ThumbnailData.hpp +++ b/src/libslic3r/GCode/ThumbnailData.hpp @@ -4,6 +4,7 @@ #if ENABLE_THUMBNAIL_GENERATOR #include +#include "libslic3r/Point.hpp" namespace Slic3r { @@ -20,6 +21,9 @@ struct ThumbnailData bool is_valid() const; }; +typedef std::vector ThumbnailsList; +typedef std::function ThumbnailsGeneratorCallback; + } // namespace Slic3r #endif // ENABLE_THUMBNAIL_GENERATOR diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 78a09c511..8b79f5367 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1538,7 +1538,7 @@ void Print::process() // write error into the G-code, cannot execute post-processing scripts). // It is up to the caller to show an error message. #if ENABLE_THUMBNAIL_GENERATOR -std::string Print::export_gcode(const std::string& path_template, GCodePreviewData* preview_data, const std::vector* thumbnail_data) +std::string Print::export_gcode(const std::string& path_template, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb) #else std::string Print::export_gcode(const std::string &path_template, GCodePreviewData *preview_data) #endif // ENABLE_THUMBNAIL_GENERATOR @@ -1559,7 +1559,7 @@ std::string Print::export_gcode(const std::string &path_template, GCodePreviewDa // The following line may die for multiple reasons. GCode gcode; #if ENABLE_THUMBNAIL_GENERATOR - gcode.do_export(this, path.c_str(), preview_data, thumbnail_data); + gcode.do_export(this, path.c_str(), preview_data, thumbnail_cb); #else gcode.do_export(this, path.c_str(), preview_data); #endif // ENABLE_THUMBNAIL_GENERATOR diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 4fcd67166..1649f3c04 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -11,6 +11,9 @@ #include "Slicing.hpp" #include "GCode/ToolOrdering.hpp" #include "GCode/WipeTower.hpp" +#if ENABLE_THUMBNAIL_GENERATOR +#include "GCode/ThumbnailData.hpp" +#endif // ENABLE_THUMBNAIL_GENERATOR namespace Slic3r { @@ -19,9 +22,6 @@ class PrintObject; class ModelObject; class GCode; class GCodePreviewData; -#if ENABLE_THUMBNAIL_GENERATOR -struct ThumbnailData; -#endif // ENABLE_THUMBNAIL_GENERATOR // Print step IDs for keeping track of the print state. enum PrintStep { @@ -311,7 +311,7 @@ public: // Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file. // If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r). #if ENABLE_THUMBNAIL_GENERATOR - std::string export_gcode(const std::string& path_template, GCodePreviewData* preview_data, const std::vector* thumbnail_data = nullptr); + std::string export_gcode(const std::string& path_template, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb = nullptr); #else std::string export_gcode(const std::string &path_template, GCodePreviewData *preview_data); #endif // ENABLE_THUMBNAIL_GENERATOR diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index c4ca46a8c..bf97baaf6 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1522,9 +1522,9 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c 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); - layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges); - updated = true; + //layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_config_ranges, model_object.volumes); + layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges); + updated = true; } return updated; } diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index c62736ffe..81e9bf0c5 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -224,40 +224,59 @@ std::vector layer_height_profile_from_ranges( // Based on the work of @platsch // Fill layer_height_profile by heights ensuring a prescribed maximum cusp height. +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE +std::vector layer_height_profile_adaptive(const SlicingParameters& slicing_params, + const ModelObject& object, float cusp_value) +#else std::vector layer_height_profile_adaptive( const SlicingParameters &slicing_params, const t_layer_config_ranges & /* layer_config_ranges */, const ModelVolumePtrs &volumes) +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE { +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // 1) Initialize the SlicingAdaptive class with the object meshes. SlicingAdaptive as; as.set_slicing_parameters(slicing_params); - for (const ModelVolume *volume : volumes) + as.set_object(object); +#else + // 1) Initialize the SlicingAdaptive class with the object meshes. + SlicingAdaptive as; + as.set_slicing_parameters(slicing_params); + for (const ModelVolume* volume : volumes) if (volume->is_model_part()) as.add_mesh(&volume->mesh()); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + as.prepare(); // 2) Generate layers using the algorithm of @platsch // loop until we have at least one layer and the max slice_z reaches the object height - //FIXME make it configurable - // Cusp value: A maximum allowed distance from a corner of a rectangular extrusion to a chrodal line, in mm. - const coordf_t cusp_value = 0.2; // $self->config->get_value('cusp_value'); +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + double cusp_value = 0.2; +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE - std::vector layer_height_profile; - layer_height_profile.push_back(0.); + std::vector layer_height_profile; + layer_height_profile.push_back(0.0); layer_height_profile.push_back(slicing_params.first_object_layer_height); if (slicing_params.first_object_layer_height_fixed()) { layer_height_profile.push_back(slicing_params.first_object_layer_height); layer_height_profile.push_back(slicing_params.first_object_layer_height); } - coordf_t slice_z = slicing_params.first_object_layer_height; - coordf_t height = slicing_params.first_object_layer_height; + double slice_z = slicing_params.first_object_layer_height; int current_facet = 0; +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + while (slice_z <= slicing_params.object_print_z_height()) { + double height = 999.0; +#else + double height = slicing_params.first_object_layer_height; while ((slice_z - height) <= slicing_params.object_print_z_height()) { - height = 999; + height = 999.0; +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // Slic3r::debugf "\n Slice layer: %d\n", $id; // determine next layer height - coordf_t cusp_height = as.cusp_height(slice_z, cusp_value, current_facet); + double cusp_height = as.cusp_height((float)slice_z, cusp_value, current_facet); + // check for horizontal features and object size /* if($self->config->get_value('match_horizontal_surfaces')) { @@ -303,19 +322,113 @@ std::vector layer_height_profile_adaptive( layer_height_profile.push_back(slice_z); layer_height_profile.push_back(height); slice_z += height; +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE layer_height_profile.push_back(slice_z); layer_height_profile.push_back(height); +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE } - coordf_t last = std::max(slicing_params.first_object_layer_height, layer_height_profile[layer_height_profile.size() - 2]); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + double z_gap = slicing_params.object_print_z_height() - layer_height_profile[layer_height_profile.size() - 2]; + if (z_gap > 0.0) + { + layer_height_profile.push_back(slicing_params.object_print_z_height()); + layer_height_profile.push_back(clamp(slicing_params.min_layer_height, slicing_params.max_layer_height, z_gap)); + } +#else + double last = std::max(slicing_params.first_object_layer_height, layer_height_profile[layer_height_profile.size() - 2]); layer_height_profile.push_back(last); layer_height_profile.push_back(slicing_params.first_object_layer_height); layer_height_profile.push_back(slicing_params.object_print_z_height()); layer_height_profile.push_back(slicing_params.first_object_layer_height); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE return layer_height_profile; } +std::vector smooth_height_profile(const std::vector& profile, const SlicingParameters& slicing_params, const HeightProfileSmoothingParams& smoothing_params) +{ + auto gauss_blur = [&slicing_params](const std::vector& profile, const HeightProfileSmoothingParams& smoothing_params) -> std::vector { + auto gauss_kernel = [] (unsigned int radius) -> std::vector { + unsigned int size = 2 * radius + 1; + std::vector ret; + ret.reserve(size); + + // Reworked from static inline int getGaussianKernelSize(float sigma) taken from opencv-4.1.2\modules\features2d\src\kaze\AKAZEFeatures.cpp + double sigma = 0.3 * (double)(radius - 1) + 0.8; + double two_sq_sigma = 2.0 * sigma * sigma; + double inv_root_two_pi_sq_sigma = 1.0 / ::sqrt(M_PI * two_sq_sigma); + + for (unsigned int i = 0; i < size; ++i) + { + double x = (double)i - (double)radius; + ret.push_back(inv_root_two_pi_sq_sigma * ::exp(-x * x / two_sq_sigma)); + } + + return ret; + }; + + // skip first layer ? + size_t skip_count = slicing_params.first_object_layer_height_fixed() ? 4 : 0; + + // not enough data to smmoth + if ((int)profile.size() - (int)skip_count < 6) + return profile; + + unsigned int radius = std::max(smoothing_params.radius, (unsigned int)1); + std::vector kernel = gauss_kernel(radius); + int two_radius = 2 * (int)radius; + + std::vector ret; + size_t size = profile.size(); + ret.reserve(size); + + // leave first layer untouched + for (size_t i = 0; i < skip_count; ++i) + { + ret.push_back(profile[i]); + } + + // smooth the rest of the profile by biasing a gaussian blur + // the bias moves the smoothed profile closer to the min_layer_height + double delta_h = slicing_params.max_layer_height - slicing_params.min_layer_height; + double inv_delta_h = (delta_h != 0.0) ? 1.0 / delta_h : 1.0; + + double max_dz_band = (double)radius * slicing_params.layer_height; + for (size_t i = skip_count; i < size; i += 2) + { + double zi = profile[i]; + double hi = profile[i + 1]; + ret.push_back(zi); + ret.push_back(0.0); + double& height = ret.back(); + int begin = std::max((int)i - two_radius, (int)skip_count); + int end = std::min((int)i + two_radius, (int)size - 2); + double weight_total = 0.0; + for (int j = begin; j <= end; j += 2) + { + int kernel_id = radius + (j - (int)i) / 2; + double dz = std::abs(zi - profile[j]); + if (dz * slicing_params.layer_height <= max_dz_band) + { + double dh = std::abs(slicing_params.max_layer_height - profile[j + 1]); + double weight = kernel[kernel_id] * sqrt(dh * inv_delta_h); + height += weight * profile[j + 1]; + weight_total += weight; + } + } + + height = clamp(slicing_params.min_layer_height, slicing_params.max_layer_height, (weight_total != 0.0) ? height /= weight_total : hi); + if (smoothing_params.keep_min) + height = std::min(height, hi); + } + + return ret; + }; + + return gauss_blur(profile, smoothing_params); +} + void adjust_layer_height_profile( const SlicingParameters &slicing_params, std::vector &layer_height_profile, @@ -609,7 +722,11 @@ int generate_layer_height_texture( const Vec3crd &color1 = palette_raw[idx1]; const Vec3crd &color2 = palette_raw[idx2]; coordf_t z = cell_to_z * coordf_t(cell); - assert(z >= lo && z <= hi); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + assert((lo - EPSILON <= z) && (z <= hi + EPSILON)); +#else + assert(z >= lo && z <= hi); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // Intensity profile to visualize the layers. coordf_t intensity = cos(M_PI * 0.7 * (mid - z) / h); // Color mapping from layer height to RGB. diff --git a/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp index 064363ec2..03ef7e67d 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -18,8 +18,12 @@ namespace Slic3r class PrintConfig; class PrintObjectConfig; +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE +class ModelObject; +#else class ModelVolume; typedef std::vector ModelVolumePtrs; +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // Parameters to guide object slicing and support generation. // The slicing parameters account for a raft and whether the 1st object layer is printed with a normal or a bridging flow @@ -138,11 +142,29 @@ extern std::vector layer_height_profile_from_ranges( const SlicingParameters &slicing_params, const t_layer_config_ranges &layer_config_ranges); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE +extern std::vector layer_height_profile_adaptive( + const SlicingParameters& slicing_params, + const ModelObject& object, float cusp_value); + +struct HeightProfileSmoothingParams +{ + unsigned int radius; + bool keep_min; + + HeightProfileSmoothingParams() : radius(5), keep_min(false) {} + HeightProfileSmoothingParams(unsigned int radius, bool keep_min) : radius(radius), keep_min(keep_min) {} +}; + +extern std::vector smooth_height_profile( + const std::vector& profile, const SlicingParameters& slicing_params, + const HeightProfileSmoothingParams& smoothing_params); +#else extern std::vector layer_height_profile_adaptive( const SlicingParameters &slicing_params, const t_layer_config_ranges &layer_config_ranges, const ModelVolumePtrs &volumes); - +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE enum LayerHeightEditActionType : unsigned int { LAYER_HEIGHT_EDIT_ACTION_INCREASE = 0, diff --git a/src/libslic3r/SlicingAdaptive.cpp b/src/libslic3r/SlicingAdaptive.cpp index ad03b550b..bc02a89c1 100644 --- a/src/libslic3r/SlicingAdaptive.cpp +++ b/src/libslic3r/SlicingAdaptive.cpp @@ -1,16 +1,22 @@ #include "libslic3r.h" +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE +#include "Model.hpp" +#else #include "TriangleMesh.hpp" +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #include "SlicingAdaptive.hpp" namespace Slic3r { +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE void SlicingAdaptive::clear() { - m_meshes.clear(); + m_meshes.clear(); m_faces.clear(); m_face_normal_z.clear(); } +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE std::pair face_z_span(const stl_facet *f) { @@ -21,21 +27,42 @@ std::pair face_z_span(const stl_facet *f) void SlicingAdaptive::prepare() { - // 1) Collect faces of all meshes. - int nfaces_total = 0; - for (std::vector::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh) +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + if (m_object == nullptr) + return; + + m_faces.clear(); + m_face_normal_z.clear(); + + m_mesh = m_object->raw_mesh(); + const ModelInstance* first_instance = m_object->instances.front(); + m_mesh.transform(first_instance->get_matrix(), first_instance->is_left_handed()); + for (stl_facet& facet : m_mesh.stl.facet_start) + { + facet.normal.normalize(); + } + + // 1) Collect faces from mesh. + m_faces.reserve(m_mesh.stl.stats.number_of_facets); + for (const stl_facet& face : m_mesh.stl.facet_start) + m_faces.emplace_back(&face); +#else + // 1) Collect faces of all meshes. + int nfaces_total = 0; + for (std::vector::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh) nfaces_total += (*it_mesh)->stl.stats.number_of_facets; - m_faces.reserve(nfaces_total); - for (std::vector::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh) - for (const stl_facet &face : (*it_mesh)->stl.facet_start) - m_faces.emplace_back(&face); + m_faces.reserve(nfaces_total); + for (std::vector::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh) + for (const stl_facet& face : (*it_mesh)->stl.facet_start) + m_faces.emplace_back(&face); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // 2) Sort faces lexicographically by their Z span. std::sort(m_faces.begin(), m_faces.end(), [](const stl_facet *f1, const stl_facet *f2) { - std::pair span1 = face_z_span(f1); + std::pair span1 = face_z_span(f1); std::pair span2 = face_z_span(f2); - return span1 < span2; - }); + return span1 < span2; + }); // 3) Generate Z components of the facet normals. m_face_normal_z.assign(m_faces.size(), 0.f); @@ -45,14 +72,14 @@ void SlicingAdaptive::prepare() float SlicingAdaptive::cusp_height(float z, float cusp_value, int ¤t_facet) { - float height = m_slicing_params.max_layer_height; + float height = (float)m_slicing_params.max_layer_height; bool first_hit = false; // find all facets intersecting the slice-layer int ordered_id = current_facet; for (; ordered_id < int(m_faces.size()); ++ ordered_id) { - std::pair zspan = face_z_span(m_faces[ordered_id]); - // facet's minimum is higher than slice_z -> end loop + std::pair zspan = face_z_span(m_faces[ordered_id]); + // facet's minimum is higher than slice_z -> end loop if (zspan.first >= z) break; // facet's maximum is higher than slice_z -> store the first event for next cusp_height call to begin at this point @@ -77,8 +104,8 @@ float SlicingAdaptive::cusp_height(float z, float cusp_value, int ¤t_facet // check for sloped facets inside the determined layer and correct height if necessary if (height > m_slicing_params.min_layer_height) { for (; ordered_id < int(m_faces.size()); ++ ordered_id) { - std::pair zspan = face_z_span(m_faces[ordered_id]); - // facet's minimum is higher than slice_z + height -> end loop + std::pair zspan = face_z_span(m_faces[ordered_id]); + // facet's minimum is higher than slice_z + height -> end loop if (zspan.first >= z + height) break; @@ -117,24 +144,25 @@ float SlicingAdaptive::cusp_height(float z, float cusp_value, int ¤t_facet return height; } +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // Returns the distance to the next horizontal facet in Z-dir // to consider horizontal object features in slice thickness float SlicingAdaptive::horizontal_facet_distance(float z) { for (size_t i = 0; i < m_faces.size(); ++ i) { - std::pair zspan = face_z_span(m_faces[i]); - // facet's minimum is higher than max forward distance -> end loop + std::pair zspan = face_z_span(m_faces[i]); + // facet's minimum is higher than max forward distance -> end loop if (zspan.first > z + m_slicing_params.max_layer_height) break; // min_z == max_z -> horizontal facet - if (zspan.first > z && zspan.first == zspan.second) + if ((zspan.first > z) && (zspan.first == zspan.second)) return zspan.first - z; } // objects maximum? - return (z + m_slicing_params.max_layer_height > m_slicing_params.object_print_z_height()) ? - std::max(m_slicing_params.object_print_z_height() - z, 0.f) : - m_slicing_params.max_layer_height; + return (z + (float)m_slicing_params.max_layer_height > (float)m_slicing_params.object_print_z_height()) ? + std::max((float)m_slicing_params.object_print_z_height() - z, 0.f) : (float)m_slicing_params.max_layer_height; } +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE }; // namespace Slic3r diff --git a/src/libslic3r/SlicingAdaptive.hpp b/src/libslic3r/SlicingAdaptive.hpp index bfd081d81..1d2996986 100644 --- a/src/libslic3r/SlicingAdaptive.hpp +++ b/src/libslic3r/SlicingAdaptive.hpp @@ -5,29 +5,49 @@ #include "Slicing.hpp" #include "admesh/stl.h" +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE +#include "TriangleMesh.hpp" +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE namespace Slic3r { +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE +class ModelVolume; +#else class TriangleMesh; +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE class SlicingAdaptive { public: - void clear(); - void set_slicing_parameters(SlicingParameters params) { m_slicing_params = params; } - void add_mesh(const TriangleMesh *mesh) { m_meshes.push_back(mesh); } - void prepare(); +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + void clear(); +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + void set_slicing_parameters(SlicingParameters params) { m_slicing_params = params; } +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + void set_object(const ModelObject& object) { m_object = &object; } +#else + void add_mesh(const TriangleMesh* mesh) { m_meshes.push_back(mesh); } +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + void prepare(); float cusp_height(float z, float cusp_value, int ¤t_facet); - float horizontal_facet_distance(float z); +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + float horizontal_facet_distance(float z); +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE protected: SlicingParameters m_slicing_params; - std::vector m_meshes; - // Collected faces of all meshes, sorted by raising Z of the bottom most face. +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + const ModelObject* m_object; + TriangleMesh m_mesh; +#else + std::vector m_meshes; +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + // Collected faces of all meshes, sorted by raising Z of the bottom most face. std::vector m_faces; - // Z component of face normals, normalized. + // Z component of face normals, normalized. std::vector m_face_normal_z; }; diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 5d0a7592c..f8db1b7b3 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -42,4 +42,7 @@ #define ENABLE_THUMBNAIL_GENERATOR_DEBUG (0 && ENABLE_THUMBNAIL_GENERATOR) #define ENABLE_THUMBNAIL_GENERATOR_PNG_TO_GCODE (1 && ENABLE_THUMBNAIL_GENERATOR) +// Enable adaptive layer height profile +#define ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE (1 && ENABLE_2_2_0_ALPHA1) + #endif // _technologies_h_ diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 5ab65f340..570841a45 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -20,9 +20,6 @@ #include "libslic3r/Utils.hpp" #include "libslic3r/GCode/PostProcessor.hpp" #include "libslic3r/GCode/PreviewData.hpp" -#if ENABLE_THUMBNAIL_GENERATOR -#include "libslic3r/GCode/ThumbnailData.hpp" -#endif // ENABLE_THUMBNAIL_GENERATOR #include "libslic3r/libslic3r.h" #include @@ -91,7 +88,7 @@ void BackgroundSlicingProcess::process_fff() m_print->process(); wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_slicing_completed_id)); #if ENABLE_THUMBNAIL_GENERATOR - m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data, m_thumbnail_data); + m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data, m_thumbnail_cb); #else m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data); #endif // ENABLE_THUMBNAIL_GENERATOR @@ -139,9 +136,12 @@ void BackgroundSlicingProcess::process_sla() m_sla_print->export_raster(zipper); #if ENABLE_THUMBNAIL_GENERATOR - if (m_thumbnail_data != nullptr) + if (m_thumbnail_cb != nullptr) { - for (const ThumbnailData& data : *m_thumbnail_data) + ThumbnailsList thumbnails; + m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, true, false); +// m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, false, false); // renders also supports and pad + for (const ThumbnailData& data : thumbnails) { if (data.is_valid()) write_thumbnail(zipper, data); @@ -461,9 +461,12 @@ void BackgroundSlicingProcess::prepare_upload() Zipper zipper{source_path.string()}; m_sla_print->export_raster(zipper, m_upload_job.upload_data.upload_path.string()); #if ENABLE_THUMBNAIL_GENERATOR - if (m_thumbnail_data != nullptr) + if (m_thumbnail_cb != nullptr) { - for (const ThumbnailData& data : *m_thumbnail_data) + ThumbnailsList thumbnails; + m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, true, false); +// m_thumbnail_cb(thumbnails, current_print()->full_print_config().option("thumbnails")->values, true, false, false); // renders also supports and pad + for (const ThumbnailData& data : thumbnails) { if (data.is_valid()) write_thumbnail(zipper, data); diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index a603d52ac..984686e35 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -17,9 +17,6 @@ namespace Slic3r { class DynamicPrintConfig; class GCodePreviewData; -#if ENABLE_THUMBNAIL_GENERATOR -struct ThumbnailData; -#endif // ENABLE_THUMBNAIL_GENERATOR class Model; class SLAPrint; @@ -53,7 +50,7 @@ public: void set_sla_print(SLAPrint *print) { m_sla_print = print; } void set_gcode_preview_data(GCodePreviewData *gpd) { m_gcode_preview_data = gpd; } #if ENABLE_THUMBNAIL_GENERATOR - void set_thumbnail_data(const std::vector* data) { m_thumbnail_data = data; } + void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; } #endif // ENABLE_THUMBNAIL_GENERATOR // The following wxCommandEvent will be sent to the UI thread / Platter window, when the slicing is finished @@ -159,8 +156,8 @@ private: // Data structure, to which the G-code export writes its annotations. GCodePreviewData *m_gcode_preview_data = nullptr; #if ENABLE_THUMBNAIL_GENERATOR - // Data structures, used to write thumbnails into gcode. - const std::vector* m_thumbnail_data = nullptr; + // Callback function, used to write thumbnails into gcode. + ThumbnailsGeneratorCallback m_thumbnail_cb = nullptr; #endif // ENABLE_THUMBNAIL_GENERATOR // Temporary G-code, there is one defined for the BackgroundSlicingProcess, differentiated from the other processes by a process ID. std::string m_temp_output_path; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 6c940ac70..3f10f9bd2 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -131,6 +131,9 @@ GLCanvas3D::LayersEditing::LayersEditing() , m_object_max_z(0.f) , m_slicing_parameters(nullptr) , m_layer_height_profile_modified(false) +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + , m_adaptive_cusp(0.2f) +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE , state(Unknown) , band_width(2.0f) , strength(0.005f) @@ -151,7 +154,9 @@ GLCanvas3D::LayersEditing::~LayersEditing() } const float GLCanvas3D::LayersEditing::THICKNESS_BAR_WIDTH = 70.0f; +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE const float GLCanvas3D::LayersEditing::THICKNESS_RESET_BUTTON_HEIGHT = 22.0f; +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE bool GLCanvas3D::LayersEditing::init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename) { @@ -218,13 +223,103 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const if (!m_enabled) return; +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + static const ImVec4 orange(0.757f, 0.404f, 0.216f, 1.0f); + + const Size& cnv_size = canvas.get_canvas_size(); + float canvas_w = (float)cnv_size.get_width(); + float canvas_h = (float)cnv_size.get_height(); + + ImGuiWrapper& imgui = *wxGetApp().imgui(); + imgui.set_next_window_pos(canvas_w - imgui.get_style_scaling() * THICKNESS_BAR_WIDTH, canvas_h, ImGuiCond_Always, 1.0f, 1.0f); + imgui.set_next_window_bg_alpha(0.5f); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + + imgui.begin(_(L("Layer height profile")), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse); + + ImGui::PushStyleColor(ImGuiCol_Text, orange); + imgui.text(_(L("Left mouse button:"))); + ImGui::PopStyleColor(); + ImGui::SameLine(); + imgui.text(_(L("Add detail"))); + + ImGui::PushStyleColor(ImGuiCol_Text, orange); + imgui.text(_(L("Right mouse button:"))); + ImGui::PopStyleColor(); + ImGui::SameLine(); + imgui.text(_(L("Remove detail"))); + + ImGui::PushStyleColor(ImGuiCol_Text, orange); + imgui.text(_(L("Shift + Left mouse button:"))); + ImGui::PopStyleColor(); + ImGui::SameLine(); + imgui.text(_(L("Reset to base"))); + + ImGui::PushStyleColor(ImGuiCol_Text, orange); + imgui.text(_(L("Shift + Right mouse button:"))); + ImGui::PopStyleColor(); + ImGui::SameLine(); + imgui.text(_(L("Smoothing"))); + + ImGui::PushStyleColor(ImGuiCol_Text, orange); + imgui.text(_(L("Mouse wheel:"))); + ImGui::PopStyleColor(); + ImGui::SameLine(); + imgui.text(_(L("Increase/decrease edit area"))); + + ImGui::Separator(); + if (imgui.button(_(L("Adaptive")))) + wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), Event(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, m_adaptive_cusp)); + + ImGui::SameLine(); + float text_align = ImGui::GetCursorPosX(); + imgui.text(_(L("Cusp (mm)"))); + ImGui::SameLine(); + float widget_align = ImGui::GetCursorPosX(); + ImGui::PushItemWidth(120.0f); + m_adaptive_cusp = std::min(m_adaptive_cusp, (float)m_slicing_parameters->max_layer_height); + ImGui::SliderFloat("", &m_adaptive_cusp, 0.0f, (float)m_slicing_parameters->max_layer_height, "%.2f"); + + ImGui::Separator(); + if (imgui.button(_(L("Smooth")))) + wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), HeightProfileSmoothEvent(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, m_smooth_params )); + + ImGui::SameLine(); + ImGui::SetCursorPosX(text_align); + imgui.text(_(L("Radius"))); + ImGui::SameLine(); + ImGui::PushItemWidth(120.0f); + ImGui::SetCursorPosX(widget_align); + int radius = (int)m_smooth_params.radius; + if (ImGui::SliderInt("##1", &radius, 1, 10)) + m_smooth_params.radius = (unsigned int)radius; + + ImGui::SetCursorPosX(text_align); + imgui.text(_(L("Keep min"))); + ImGui::SameLine(); + ImGui::PushItemWidth(120.0f); + ImGui::SetCursorPosX(widget_align); + imgui.checkbox("##2", m_smooth_params.keep_min); + + ImGui::Separator(); + if (imgui.button(_(L("Reset")))) + wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), SimpleEvent(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE)); + + imgui.end(); + + ImGui::PopStyleVar(); + + const Rect& bar_rect = get_bar_rect_viewport(canvas); +#else const Rect& bar_rect = get_bar_rect_viewport(canvas); const Rect& reset_rect = get_reset_rect_viewport(canvas); _render_tooltip_texture(canvas, bar_rect, reset_rect); _render_reset_texture(reset_rect); - _render_active_object_annotations(canvas, bar_rect); - _render_profile(bar_rect); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + render_active_object_annotations(canvas, bar_rect); + render_profile(bar_rect); } float GLCanvas3D::LayersEditing::get_cursor_z_relative(const GLCanvas3D& canvas) @@ -249,11 +344,13 @@ bool GLCanvas3D::LayersEditing::bar_rect_contains(const GLCanvas3D& canvas, floa return (rect.get_left() <= x) && (x <= rect.get_right()) && (rect.get_top() <= y) && (y <= rect.get_bottom()); } +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE bool GLCanvas3D::LayersEditing::reset_rect_contains(const GLCanvas3D& canvas, float x, float y) { const Rect& rect = get_reset_rect_screen(canvas); return (rect.get_left() <= x) && (x <= rect.get_right()) && (rect.get_top() <= y) && (y <= rect.get_bottom()); } +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE Rect GLCanvas3D::LayersEditing::get_bar_rect_screen(const GLCanvas3D& canvas) { @@ -261,9 +358,14 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_screen(const GLCanvas3D& canvas) float w = (float)cnv_size.get_width(); float h = (float)cnv_size.get_height(); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + return Rect(w - thickness_bar_width(canvas), 0.0f, w, h); +#else return Rect(w - thickness_bar_width(canvas), 0.0f, w, h - reset_button_height(canvas)); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE } +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE Rect GLCanvas3D::LayersEditing::get_reset_rect_screen(const GLCanvas3D& canvas) { const Size& cnv_size = canvas.get_canvas_size(); @@ -272,6 +374,7 @@ Rect GLCanvas3D::LayersEditing::get_reset_rect_screen(const GLCanvas3D& canvas) return Rect(w - thickness_bar_width(canvas), h - reset_button_height(canvas), w, h); } +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas) { @@ -282,9 +385,14 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas) float zoom = (float)canvas.get_camera().get_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, half_h * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom); +#else return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, half_h * inv_zoom, half_w * inv_zoom, (-half_h + reset_button_height(canvas)) * inv_zoom); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE } +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE Rect GLCanvas3D::LayersEditing::get_reset_rect_viewport(const GLCanvas3D& canvas) { const Size& cnv_size = canvas.get_canvas_size(); @@ -296,13 +404,14 @@ Rect GLCanvas3D::LayersEditing::get_reset_rect_viewport(const GLCanvas3D& canvas return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, (-half_h + reset_button_height(canvas)) * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom); } +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE - -bool GLCanvas3D::LayersEditing::_is_initialized() const +bool GLCanvas3D::LayersEditing::is_initialized() const { return m_shader.is_initialized(); } +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE void GLCanvas3D::LayersEditing::_render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const { // TODO: do this with ImGui @@ -348,8 +457,9 @@ void GLCanvas3D::LayersEditing::_render_reset_texture(const Rect& reset_rect) co GLTexture::render_texture(m_reset_texture.get_id(), reset_rect.get_left(), reset_rect.get_right(), reset_rect.get_bottom(), reset_rect.get_top()); } +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE -void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const +void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const { m_shader.start_using(); @@ -380,7 +490,7 @@ void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas m_shader.stop_using(); } -void GLCanvas3D::LayersEditing::_render_profile(const Rect& bar_rect) const +void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect) const { //FIXME show some kind of legend. @@ -497,6 +607,24 @@ void GLCanvas3D::LayersEditing::reset_layer_height_profile(GLCanvas3D& canvas) canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); } +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE +void GLCanvas3D::LayersEditing::adaptive_layer_height_profile(GLCanvas3D& canvas, float cusp) +{ + m_layer_height_profile = layer_height_profile_adaptive(*m_slicing_parameters, *m_model_object, cusp); + const_cast(m_model_object)->layer_height_profile = m_layer_height_profile; + m_layers_texture.valid = false; + canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); +} + +void GLCanvas3D::LayersEditing::smooth_layer_height_profile(GLCanvas3D& canvas, const HeightProfileSmoothingParams& smoothing_params) +{ + m_layer_height_profile = smooth_height_profile(m_layer_height_profile, *m_slicing_parameters, smoothing_params); + const_cast(m_model_object)->layer_height_profile = m_layer_height_profile; + m_layers_texture.valid = false; + canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); +} +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + void GLCanvas3D::LayersEditing::generate_layer_height_texture() { this->update_slicing_parameters(); @@ -558,6 +686,7 @@ float GLCanvas3D::LayersEditing::thickness_bar_width(const GLCanvas3D &canvas) * THICKNESS_BAR_WIDTH; } +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE float GLCanvas3D::LayersEditing::reset_button_height(const GLCanvas3D &canvas) { return @@ -568,6 +697,7 @@ float GLCanvas3D::LayersEditing::reset_button_height(const GLCanvas3D &canvas) #endif * THICKNESS_RESET_BUTTON_HEIGHT; } +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE const Point GLCanvas3D::Mouse::Drag::Invalid_2D_Point(INT_MAX, INT_MAX); @@ -1119,6 +1249,11 @@ wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent); wxDEFINE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE +wxDEFINE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event); +wxDEFINE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #if ENABLE_THUMBNAIL_GENERATOR const double GLCanvas3D::DefaultCameraZoomToBoxMarginFactor = 1.25; @@ -1421,6 +1556,29 @@ bool GLCanvas3D::is_layers_editing_allowed() const return m_layers_editing.is_allowed(); } +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE +void GLCanvas3D::reset_layer_height_profile() +{ + m_layers_editing.reset_layer_height_profile(*this); + m_layers_editing.state = LayersEditing::Completed; + m_dirty = true; +} + +void GLCanvas3D::adaptive_layer_height_profile(float cusp) +{ + m_layers_editing.adaptive_layer_height_profile(*this, cusp); + m_layers_editing.state = LayersEditing::Completed; + m_dirty = true; +} + +void GLCanvas3D::smooth_layer_height_profile(const HeightProfileSmoothingParams& smoothing_params) +{ + m_layers_editing.smooth_layer_height_profile(*this, smoothing_params); + m_layers_editing.state = LayersEditing::Completed; + m_dirty = true; +} +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + bool GLCanvas3D::is_reload_delayed() const { return m_reload_delayed; @@ -2830,6 +2988,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_layers_editing.state = LayersEditing::Editing; _perform_layer_editing_action(&evt); } +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE else if ((layer_editing_object_idx != -1) && m_layers_editing.reset_rect_contains(*this, pos(0), pos(1))) { if (evt.LeftDown()) @@ -2842,6 +3001,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; } } +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE else if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled) { if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index c72b935d0..c673bc39b 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -81,6 +81,8 @@ template using Vec2dsEvent = ArrayEvent; using Vec3dEvent = Event; template using Vec3dsEvent = ArrayEvent; +using HeightProfileSmoothEvent = Event; + wxDECLARE_EVENT(EVT_GLCANVAS_INIT, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, RBtnEvent); @@ -104,6 +106,11 @@ wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent); wxDECLARE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); wxDECLARE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE +wxDECLARE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event); +wxDECLARE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE class GLCanvas3D { @@ -153,13 +160,17 @@ private: private: static const float THICKNESS_BAR_WIDTH; +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE static const float THICKNESS_RESET_BUTTON_HEIGHT; +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE bool m_enabled; Shader m_shader; unsigned int m_z_texture_id; +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE mutable GLTexture m_tooltip_texture; mutable GLTexture m_reset_texture; +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // Not owned by LayersEditing. const DynamicPrintConfig *m_config; // ModelObject for the currently selected object (Model::objects[last_object_id]). @@ -171,6 +182,11 @@ private: std::vector m_layer_height_profile; bool m_layer_height_profile_modified; +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + mutable float m_adaptive_cusp; + mutable HeightProfileSmoothingParams m_smooth_params; +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + class LayersTexture { public: @@ -217,28 +233,42 @@ private: void adjust_layer_height_profile(); void accept_changes(GLCanvas3D& canvas); void reset_layer_height_profile(GLCanvas3D& canvas); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + void adaptive_layer_height_profile(GLCanvas3D& canvas, float cusp); + void smooth_layer_height_profile(GLCanvas3D& canvas, const HeightProfileSmoothingParams& smoothing_paramsn); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE static float get_cursor_z_relative(const GLCanvas3D& canvas); static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y); +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE static bool reset_rect_contains(const GLCanvas3D& canvas, float x, float y); +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE static Rect get_bar_rect_screen(const GLCanvas3D& canvas); +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE static Rect get_reset_rect_screen(const GLCanvas3D& canvas); +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE static Rect get_bar_rect_viewport(const GLCanvas3D& canvas); +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE static Rect get_reset_rect_viewport(const GLCanvas3D& canvas); +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE float object_max_z() const { return m_object_max_z; } private: - bool _is_initialized() const; + bool is_initialized() const; void generate_layer_height_texture(); +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE void _render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const; void _render_reset_texture(const Rect& reset_rect) const; - void _render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const; - void _render_profile(const Rect& bar_rect) const; +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + void render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const; + void render_profile(const Rect& bar_rect) const; void update_slicing_parameters(); static float thickness_bar_width(const GLCanvas3D &canvas); +#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE static float reset_button_height(const GLCanvas3D &canvas); +#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE }; struct Mouse @@ -501,6 +531,12 @@ public: bool is_layers_editing_enabled() const; bool is_layers_editing_allowed() const; +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + void reset_layer_height_profile(); + void adaptive_layer_height_profile(float cusp); + void smooth_layer_height_profile(const HeightProfileSmoothingParams& smoothing_params); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + bool is_reload_delayed() const; void enable_layers_editing(bool enable); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 94319927d..61a42d06a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1388,9 +1388,6 @@ struct Plater::priv Slic3r::Model model; PrinterTechnology printer_technology = ptFFF; Slic3r::GCodePreviewData gcode_preview_data; -#if ENABLE_THUMBNAIL_GENERATOR - std::vector thumbnail_data; -#endif // ENABLE_THUMBNAIL_GENERATOR // GUI elements wxSizer* panel_sizer{ nullptr }; @@ -1948,6 +1945,7 @@ struct Plater::priv #if ENABLE_THUMBNAIL_GENERATOR void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background); + void generate_thumbnails(ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background); #endif // ENABLE_THUMBNAIL_GENERATOR void msw_rescale_object_menu(); @@ -2018,7 +2016,15 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) background_process.set_sla_print(&sla_print); background_process.set_gcode_preview_data(&gcode_preview_data); #if ENABLE_THUMBNAIL_GENERATOR - background_process.set_thumbnail_data(&thumbnail_data); + background_process.set_thumbnail_cb([this](ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background) + { + std::packaged_task task([this](ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background) { + generate_thumbnails(thumbnails, sizes, printable_only, parts_only, transparent_background); + }); + std::future result = task.get_future(); + wxTheApp->CallAfter([&]() { task(thumbnails, sizes, printable_only, parts_only, transparent_background); }); + result.wait(); + }); #endif // ENABLE_THUMBNAIL_GENERATOR background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED); background_process.set_finished_event(EVT_PROCESS_COMPLETED); @@ -2089,6 +2095,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) view3D_canvas->Bind(EVT_GLCANVAS_RESETGIZMOS, [this](SimpleEvent&) { reset_all_gizmos(); }); view3D_canvas->Bind(EVT_GLCANVAS_UNDO, [this](SimpleEvent&) { this->undo(); }); view3D_canvas->Bind(EVT_GLCANVAS_REDO, [this](SimpleEvent&) { this->redo(); }); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE + view3D_canvas->Bind(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, [this](SimpleEvent&) { this->view3D->get_canvas3d()->reset_layer_height_profile(); }); + view3D_canvas->Bind(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, [this](Event& evt) { this->view3D->get_canvas3d()->adaptive_layer_height_profile(evt.data); }); + view3D_canvas->Bind(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, [this](HeightProfileSmoothEvent& evt) { this->view3D->get_canvas3d()->smooth_layer_height_profile(evt.data); }); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // 3DScene/Toolbar: view3D_canvas->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); @@ -3068,37 +3079,6 @@ bool Plater::priv::restart_background_process(unsigned int state) ( ((state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART) != 0 && ! this->background_process.finished()) || (state & UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT) != 0 || (state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ) ) { -#if ENABLE_THUMBNAIL_GENERATOR - if (((state & UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT) == 0) && - (this->background_process.state() != BackgroundSlicingProcess::STATE_RUNNING)) - { - // update thumbnail data - const std::vector &thumbnail_sizes = this->background_process.current_print()->full_print_config().option("thumbnails")->values; - if (this->printer_technology == ptFFF) - { - // for ptFFF we need to generate the thumbnails before the export of gcode starts - this->thumbnail_data.clear(); - for (const Vec2d &sized : thumbnail_sizes) - { - this->thumbnail_data.push_back(ThumbnailData()); - Point size(sized); // round to ints - generate_thumbnail(this->thumbnail_data.back(), size.x(), size.y(), true, true, false); - } - } - else if (this->printer_technology == ptSLA) - { - // for ptSLA generate thumbnails without supports and pad (not yet calculated) - // to render also supports and pad see on_slicing_update() - this->thumbnail_data.clear(); - for (const Vec2d &sized : thumbnail_sizes) - { - this->thumbnail_data.push_back(ThumbnailData()); - Point size(sized); // round to ints - generate_thumbnail(this->thumbnail_data.back(), size.x(), size.y(), true, true, false); - } - } - } -#endif // ENABLE_THUMBNAIL_GENERATOR // The print is valid and it can be started. if (this->background_process.start()) { this->statusbar()->set_cancel_callback([this]() { @@ -3438,25 +3418,6 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) } else if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_PREVIEW) { // Update the SLA preview. Only called if not RELOAD_SLA_SUPPORT_POINTS, as the block above will refresh the preview anyways. this->preview->reload_print(); - - // uncomment the following lines if you want to render into the thumbnail also supports and pad for SLA printer -/* -#if ENABLE_THUMBNAIL_GENERATOR - // update thumbnail data - // for ptSLA generate the thumbnail after supports and pad have been calculated to have them rendered - if ((this->printer_technology == ptSLA) && (evt.status.percent == -3)) - { - const std::vector& thumbnail_sizes = this->background_process.current_print()->full_print_config().option("thumbnails")->values; - this->thumbnail_data.clear(); - for (const Vec2d &sized : thumbnail_sizes) - { - this->thumbnail_data.push_back(ThumbnailData()); - Point size(sized); // round to ints - generate_thumbnail(this->thumbnail_data.back(), size.x(), size.y(), true, false, false); - } - } -#endif // ENABLE_THUMBNAIL_GENERATOR -*/ } } @@ -3687,6 +3648,19 @@ void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsig { view3D->get_canvas3d()->render_thumbnail(data, w, h, printable_only, parts_only, transparent_background); } + +void Plater::priv::generate_thumbnails(ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool transparent_background) +{ + thumbnails.clear(); + for (const Vec2d& size : sizes) + { + thumbnails.push_back(ThumbnailData()); + Point isize(size); // round to ints + generate_thumbnail(thumbnails.back(), isize.x(), isize.y(), printable_only, parts_only, transparent_background); + if (!thumbnails.back().is_valid()) + thumbnails.pop_back(); + } +} #endif // ENABLE_THUMBNAIL_GENERATOR void Plater::priv::msw_rescale_object_menu()