diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index b7816fd046..0d3b3af388 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -252,6 +252,9 @@ std::vector layer_height_profile_adaptive( // 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 +#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.); @@ -264,7 +267,7 @@ std::vector layer_height_profile_adaptive( double height = slicing_params.first_object_layer_height; int current_facet = 0; while ((slice_z - height) <= slicing_params.object_print_z_height()) { - height = 999; + height = 999.0; // Slic3r::debugf "\n Slice layer: %d\n", $id; // determine next layer height double cusp_height = as.cusp_height((float)slice_z, cusp_value, current_facet); @@ -318,7 +321,7 @@ std::vector layer_height_profile_adaptive( layer_height_profile.push_back(height); } - coordf_t last = std::max(slicing_params.first_object_layer_height, layer_height_profile[layer_height_profile.size() - 2]); + 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()); @@ -327,6 +330,73 @@ std::vector layer_height_profile_adaptive( return layer_height_profile; } +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING +std::vector smooth_height_profile(const std::vector& profile, const SlicingParameters& slicing_params, + unsigned int radius) +{ + auto gauss_blur = [] (const std::vector& profile, unsigned int radius) -> 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; + }; + + std::vector ret; + size_t size = profile.size(); + ret.reserve(size); + std::vector kernel = gauss_kernel(radius); + + for (size_t i = 0; i < size; ++i) + { + unsigned int id = 0; + double value = 0.0; + for (int j = (int)(i - radius); j <= (int)(i + radius); ++j) + { + if ((0 <= j) && (j < size)) + value += kernel[id] * profile[j]; + + ++id; + } + ret.push_back(value); + } + + return ret; + }; + + std::vector ret = profile; + + std::vector heights; + size_t heights_size = ret.size() / 2; + heights.reserve(heights_size); + for (size_t i = 0; i < heights_size; ++i) + { + heights.push_back(ret[i * 2 + 1]); + } + + heights = gauss_blur(heights, std::max(radius, (unsigned int)1)); + + for (size_t i = 0; i < heights_size; ++i) + { + ret[i * 2 + 1] = clamp(slicing_params.min_layer_height, slicing_params.max_layer_height, heights[i]); + } + + return ret; +} +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING + void adjust_layer_height_profile( const SlicingParameters &slicing_params, std::vector &layer_height_profile, diff --git a/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp index e25cbd3269..545857216f 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -146,6 +146,11 @@ extern std::vector layer_height_profile_from_ranges( extern std::vector layer_height_profile_adaptive( const SlicingParameters& slicing_params, const ModelObject& object, float cusp_value); + +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING +extern std::vector smooth_height_profile(const std::vector& profile, const SlicingParameters& slicing_params, + unsigned int radius); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING #else extern std::vector layer_height_profile_adaptive( const SlicingParameters &slicing_params, diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index f8db1b7b30..465f5dd337 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -44,5 +44,6 @@ // Enable adaptive layer height profile #define ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE (1 && ENABLE_2_2_0_ALPHA1) +#define ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING (1 && ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 8ef0eaa13a..d0cd1fbeb0 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -130,7 +130,12 @@ 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) +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING + , m_smooth_radius(5) +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE , state(Unknown) , band_width(2.0f) , strength(0.005f) @@ -227,9 +232,10 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const float canvas_w = (float)cnv_size.get_width(); float canvas_h = (float)cnv_size.get_height(); + const float scale_gl = wxGetApp().mainframe->scale_factor(); ImGuiWrapper& imgui = *wxGetApp().imgui(); - imgui.set_next_window_pos(canvas_w - THICKNESS_BAR_WIDTH, canvas_h, ImGuiCond_Always, 1.0f, 1.0f); + imgui.set_next_window_pos(canvas_w - scale_gl * 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); @@ -271,12 +277,30 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const 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(); - ImGui::PushItemWidth(100.0f); + 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"); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING + ImGui::Separator(); + if (imgui.button(_(L("Smooth")))) + wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), Event(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, m_smooth_radius)); + + 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_radius; + if (ImGui::SliderInt("##1", &radius, 1, 10)) + m_smooth_radius = (unsigned int)radius; +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING + ImGui::Separator(); if (imgui.button(_(L("Reset")))) wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), SimpleEvent(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE)); @@ -590,6 +614,17 @@ void GLCanvas3D::LayersEditing::adaptive_layer_height_profile(GLCanvas3D& canvas m_layers_texture.valid = false; canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); } + +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING +void GLCanvas3D::LayersEditing::smooth_layer_height_profile(GLCanvas3D& canvas, unsigned int radius) +{ + m_layer_height_profile = smooth_height_profile(m_layer_height_profile, *m_slicing_parameters, radius); + 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_SMOOTHING + #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE void GLCanvas3D::LayersEditing::generate_layer_height_texture() @@ -1219,6 +1254,9 @@ 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); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING +wxDEFINE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, Event); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE #if ENABLE_THUMBNAIL_GENERATOR @@ -1536,6 +1574,16 @@ void GLCanvas3D::adaptive_layer_height_profile(float cusp) m_layers_editing.state = LayersEditing::Completed; m_dirty = true; } + +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING +void GLCanvas3D::smooth_layer_height_profile(unsigned int radius) +{ + m_layers_editing.smooth_layer_height_profile(*this, radius); + m_layers_editing.state = LayersEditing::Completed; + m_dirty = true; +} +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING + #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE bool GLCanvas3D::is_reload_delayed() const diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d1369d086f..d57a5c8d6a 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -107,6 +107,9 @@ 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); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING +wxDECLARE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, Event); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE class GLCanvas3D @@ -179,7 +182,12 @@ private: std::vector m_layer_height_profile; bool m_layer_height_profile_modified; +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE mutable float m_adaptive_cusp; +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING + mutable unsigned int m_smooth_radius; +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE class LayersTexture { @@ -229,6 +237,9 @@ private: void reset_layer_height_profile(GLCanvas3D& canvas); #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE void adaptive_layer_height_profile(GLCanvas3D& canvas, float cusp); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING + void smooth_layer_height_profile(GLCanvas3D& canvas, unsigned int radius); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE static float get_cursor_z_relative(const GLCanvas3D& canvas); @@ -526,6 +537,9 @@ public: #if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE void reset_layer_height_profile(); void adaptive_layer_height_profile(float cusp); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING + void smooth_layer_height_profile(unsigned int radius); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE bool is_reload_delayed() const; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e2b15602cd..3c93486d87 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2092,6 +2092,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) #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); }); +#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING + view3D_canvas->Bind(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, [this](Event& evt) { this->view3D->get_canvas3d()->smooth_layer_height_profile(evt.data); }); +#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE_SMOOTHING #endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE // 3DScene/Toolbar: